1 18 package org.apache.batik.svggen; 19 20 import java.awt.BasicStroke ; 21 import java.awt.Color ; 22 import java.awt.Dimension ; 23 import java.awt.Font ; 24 import java.awt.FontMetrics ; 25 import java.awt.Graphics ; 26 import java.awt.Graphics2D ; 27 import java.awt.GraphicsConfiguration ; 28 import java.awt.Image ; 29 import java.awt.Shape ; 30 import java.awt.Stroke ; 31 import java.awt.font.GlyphVector ; 32 import java.awt.font.TextLayout ; 33 import java.awt.geom.AffineTransform ; 34 import java.awt.geom.NoninvertibleTransformException ; 35 import java.awt.image.BufferedImage ; 36 import java.awt.image.BufferedImageOp ; 37 import java.awt.image.ImageObserver ; 38 import java.awt.image.RenderedImage ; 39 import java.awt.image.renderable.RenderableImage ; 40 import java.io.FileOutputStream ; 41 import java.io.IOException ; 42 import java.io.OutputStreamWriter ; 43 import java.io.Writer ; 44 import java.text.AttributedCharacterIterator ; 45 46 import org.apache.batik.ext.awt.g2d.AbstractGraphics2D; 47 import org.apache.batik.ext.awt.g2d.GraphicContext; 48 import org.apache.batik.util.XMLConstants; 49 import org.w3c.dom.Document ; 50 import org.w3c.dom.DocumentFragment ; 51 import org.w3c.dom.Element ; 52 import org.w3c.dom.Node ; 53 54 83 public class SVGGraphics2D extends AbstractGraphics2D 84 implements Cloneable , SVGSyntax, XMLConstants, ErrorConstants { 85 88 public static final String DEFAULT_XML_ENCODING = "ISO-8859-1"; 89 90 97 public static final int DEFAULT_MAX_GC_OVERRIDES = 3; 98 99 100 106 protected DOMTreeManager domTreeManager; 107 108 118 protected DOMGroupManager domGroupManager; 119 120 123 protected SVGGeneratorContext generatorCtx; 124 125 129 protected SVGShape shapeConverter; 130 131 134 protected Dimension svgCanvasSize; 135 136 139 protected Graphics2D fmg; 140 141 { 142 BufferedImage bi 143 = new BufferedImage (1, 1, BufferedImage.TYPE_INT_ARGB); 144 145 fmg = bi.createGraphics(); 146 } 147 148 151 public final Dimension getSVGCanvasSize(){ 152 return svgCanvasSize; 153 } 154 155 161 public final void setSVGCanvasSize(Dimension svgCanvasSize) { 162 this.svgCanvasSize = new Dimension (svgCanvasSize); 163 } 164 165 168 public final SVGGeneratorContext getGeneratorContext() { 169 return generatorCtx; 170 } 171 172 176 public final SVGShape getShapeConverter() { 177 return shapeConverter; 178 } 179 180 183 public final DOMTreeManager getDOMTreeManager(){ 184 return domTreeManager; 185 } 186 187 191 protected final void setDOMTreeManager(DOMTreeManager treeMgr) { 192 this.domTreeManager = treeMgr; 193 generatorCtx.genericImageHandler.setDOMTreeManager(domTreeManager); 194 } 195 196 199 protected final DOMGroupManager getDOMGroupManager(){ 200 return domGroupManager; 201 } 202 203 207 protected final void setDOMGroupManager(DOMGroupManager groupMgr) { 208 this.domGroupManager = groupMgr; 209 } 210 211 215 public final Document getDOMFactory(){ 216 return generatorCtx.domFactory; 217 } 218 219 222 public final ImageHandler getImageHandler(){ 223 return generatorCtx.imageHandler; 224 } 225 226 229 public final GenericImageHandler getGenericImageHandler(){ 230 return generatorCtx.genericImageHandler; 231 } 232 233 236 public final ExtensionHandler getExtensionHandler(){ 237 return generatorCtx.extensionHandler; 238 } 239 240 244 public final void setExtensionHandler(ExtensionHandler extensionHandler) { 245 generatorCtx.setExtensionHandler(extensionHandler); 246 } 247 248 253 public SVGGraphics2D(Document domFactory) { 254 this(SVGGeneratorContext.createDefault(domFactory), false); 255 } 256 257 269 public SVGGraphics2D(Document domFactory, 270 ImageHandler imageHandler, 271 ExtensionHandler extensionHandler, 272 boolean textAsShapes) { 273 this(buildSVGGeneratorContext(domFactory, 274 imageHandler, 275 extensionHandler), 276 textAsShapes); 277 } 278 279 283 public static SVGGeneratorContext 284 buildSVGGeneratorContext(Document domFactory, 285 ImageHandler imageHandler, 286 ExtensionHandler extensionHandler){ 287 288 SVGGeneratorContext generatorCtx = new SVGGeneratorContext(domFactory); 289 generatorCtx.setIDGenerator(new SVGIDGenerator()); 290 generatorCtx.setExtensionHandler(extensionHandler); 291 generatorCtx.setImageHandler(imageHandler); 292 generatorCtx.setStyleHandler(new DefaultStyleHandler()); 293 generatorCtx.setComment("Generated by the Batik Graphics2D SVG Generator"); 294 generatorCtx.setErrorHandler(new DefaultErrorHandler()); 295 296 return generatorCtx; 297 } 298 299 308 public SVGGraphics2D(SVGGeneratorContext generatorCtx, 309 boolean textAsShapes) { 310 super(textAsShapes); 311 312 if (generatorCtx == null) 313 throw new SVGGraphics2DRuntimeException(ERR_CONTEXT_NULL); 315 316 setGeneratorContext(generatorCtx); 317 } 318 319 322 protected void setGeneratorContext(SVGGeneratorContext generatorCtx) { 323 this.generatorCtx = generatorCtx; 324 325 this.gc = new GraphicContext(new AffineTransform ()); 326 327 SVGGeneratorContext.GraphicContextDefaults gcDefaults = 328 generatorCtx.getGraphicContextDefaults(); 329 330 if(gcDefaults != null){ 331 if(gcDefaults.getPaint() != null){ 332 gc.setPaint(gcDefaults.getPaint()); 333 } 334 if(gcDefaults.getStroke() != null){ 335 gc.setStroke(gcDefaults.getStroke()); 336 } 337 if(gcDefaults.getComposite() != null){ 338 gc.setComposite(gcDefaults.getComposite()); 339 } 340 if(gcDefaults.getClip() != null){ 341 gc.setClip(gcDefaults.getClip()); 342 } 343 if(gcDefaults.getRenderingHints() != null){ 344 gc.setRenderingHints(gcDefaults.getRenderingHints()); 345 } 346 if(gcDefaults.getFont() != null){ 347 gc.setFont(gcDefaults.getFont()); 348 } 349 if(gcDefaults.getBackground() != null){ 350 gc.setBackground(gcDefaults.getBackground()); 351 } 352 } 353 354 this.shapeConverter = new SVGShape(generatorCtx); 355 this.domTreeManager = new DOMTreeManager(gc, 356 generatorCtx, 357 DEFAULT_MAX_GC_OVERRIDES); 358 this.domGroupManager = new DOMGroupManager(gc, domTreeManager); 359 this.domTreeManager.addGroupManager(domGroupManager); 360 generatorCtx.genericImageHandler.setDOMTreeManager(domTreeManager); 361 } 362 363 368 public SVGGraphics2D(SVGGraphics2D g) { 369 super(g); 370 this.generatorCtx = g.generatorCtx; 371 this.gc.validateTransformStack(); 372 this.shapeConverter = g.shapeConverter; 373 this.domTreeManager = g.domTreeManager; 374 this.domGroupManager = new DOMGroupManager(this.gc, this.domTreeManager); 375 this.domTreeManager.addGroupManager(this.domGroupManager); 376 } 377 378 382 public void stream(String svgFileName) throws SVGGraphics2DIOException { 383 stream(svgFileName, false); 384 } 385 386 392 public void stream(String svgFileName, boolean useCss) 393 throws SVGGraphics2DIOException { 394 try { 395 OutputStreamWriter writer = 396 new OutputStreamWriter (new FileOutputStream (svgFileName), 397 DEFAULT_XML_ENCODING); 398 stream(writer, useCss); 399 writer.flush(); 400 writer.close(); 401 } catch (SVGGraphics2DIOException io) { 402 throw io; 405 } catch (IOException e) { 406 generatorCtx.errorHandler. 407 handleError(new SVGGraphics2DIOException(e)); 408 } 409 } 410 411 414 public void stream(Writer writer) throws SVGGraphics2DIOException { 415 stream(writer, false); 416 } 417 418 423 public void stream(Writer writer, boolean useCss) 424 throws SVGGraphics2DIOException { 425 Element svgRoot = getRoot(); 426 stream(svgRoot, writer, useCss); 427 } 428 429 432 public void stream(Element svgRoot, Writer writer) 433 throws SVGGraphics2DIOException { 434 stream(svgRoot, writer, false); 435 } 436 437 443 public void stream(Element svgRoot, Writer writer, boolean useCss) 444 throws SVGGraphics2DIOException { 445 Node rootParent = svgRoot.getParentNode(); 446 Node nextSibling = svgRoot.getNextSibling(); 447 448 try { 449 svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI, 454 XMLNS_PREFIX, 455 SVG_NAMESPACE_URI); 456 457 svgRoot.setAttributeNS(XMLNS_NAMESPACE_URI, 458 XMLNS_PREFIX + ":" + XLINK_PREFIX, 459 XLINK_NAMESPACE_URI); 460 461 DocumentFragment svgDocument = 462 svgRoot.getOwnerDocument().createDocumentFragment(); 463 svgDocument.appendChild(svgRoot); 464 465 if (useCss) 466 SVGCSSStyler.style(svgDocument); 467 468 XmlWriter.writeXml(svgDocument, writer); 469 writer.flush(); 470 } catch (SVGGraphics2DIOException e) { 471 generatorCtx.errorHandler. 476 handleError(e); 477 } catch (IOException io) { 478 generatorCtx.errorHandler. 479 handleError(new SVGGraphics2DIOException(io)); 480 } finally { 481 if (rootParent != null) { 483 if (nextSibling == null) { 484 rootParent.appendChild(svgRoot); 485 } else { 486 rootParent.insertBefore(svgRoot, nextSibling); 487 } 488 } 489 } 490 } 491 492 497 public java.util.List getDefinitionSet(){ 498 return domTreeManager.getDefinitionSet(); 499 } 500 501 508 public Element getTopLevelGroup(){ 509 return getTopLevelGroup(true); 510 } 511 512 522 public Element getTopLevelGroup(boolean includeDefinitionSet){ 523 return domTreeManager.getTopLevelGroup(includeDefinitionSet); 524 } 525 526 530 public void setTopLevelGroup(Element topLevelGroup){ 531 domTreeManager.setTopLevelGroup(topLevelGroup); 532 } 533 534 538 public Element getRoot(){ 539 return getRoot(null); 540 } 541 542 551 public Element getRoot(Element svgRoot) { 552 svgRoot = domTreeManager.getRoot(svgRoot); 553 if (svgCanvasSize != null){ 554 svgRoot.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE, 555 "" + svgCanvasSize.width); 556 svgRoot.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE, 557 "" + svgCanvasSize.height); 558 } 559 return svgRoot; 560 } 561 562 568 public Graphics create(){ 569 return new SVGGraphics2D(this); 570 } 571 572 573 588 public void setXORMode(Color c1) { 589 generatorCtx.errorHandler. 590 handleError(new SVGGraphics2DRuntimeException(ERR_XOR)); 591 } 592 593 601 public FontMetrics getFontMetrics(Font f){ 602 return fmg.getFontMetrics(f); 603 } 604 605 624 public void copyArea(int x, int y, int width, int height, 625 int dx, int dy){ 626 } 628 629 653 public boolean drawImage(Image img, int x, int y, 654 ImageObserver observer) { 655 Element imageElement = 656 getGenericImageHandler().createElement(getGeneratorContext()); 657 AffineTransform xform = getGenericImageHandler().handleImage( 658 img, imageElement, 659 x, y, 660 img.getWidth(null), 661 img.getHeight(null), 662 getGeneratorContext()); 663 664 if (xform == null) { 665 domGroupManager.addElement(imageElement); 666 } else { 667 AffineTransform inverseTransform = null; 668 try { 669 inverseTransform = xform.createInverse(); 670 } catch(NoninvertibleTransformException e) { 671 throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED); 674 } 675 gc.transform(xform); 676 domGroupManager.addElement(imageElement); 677 gc.transform(inverseTransform); 678 } 679 return true; 680 } 681 682 715 public boolean drawImage(Image img, int x, int y, 716 int width, int height, 717 ImageObserver observer){ 718 Element imageElement = 719 getGenericImageHandler().createElement(getGeneratorContext()); 720 AffineTransform xform 721 = getGenericImageHandler().handleImage( 722 img, imageElement, 723 x, y, 724 width, height, 725 getGeneratorContext()); 726 727 if (xform == null) { 728 domGroupManager.addElement(imageElement); 729 } else { 730 AffineTransform inverseTransform = null; 731 try { 732 inverseTransform = xform.createInverse(); 733 } catch(NoninvertibleTransformException e) { 734 throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED); 737 } 738 gc.transform(xform); 739 domGroupManager.addElement(imageElement); 740 gc.transform(inverseTransform); 741 } 742 return true; 743 } 744 745 772 public void dispose() { 773 this.domTreeManager.removeGroupManager(this.domGroupManager); 774 } 775 776 792 public void draw(Shape s) { 793 Stroke stroke = gc.getStroke(); 797 if (stroke instanceof BasicStroke ) { 798 Element svgShape = shapeConverter.toSVG(s); 799 if (svgShape != null) { 800 domGroupManager.addElement(svgShape, DOMGroupManager.DRAW); 801 } 802 } else { 803 Shape strokedShape = stroke.createStrokedShape(s); 804 fill(strokedShape); 805 } 806 } 807 808 809 834 public boolean drawImage(Image img, 835 AffineTransform xform, 836 ImageObserver obs){ 837 boolean retVal = true; 838 839 if (xform == null) { 840 retVal = drawImage(img, 0, 0, null); 841 } else if(xform.getDeterminant() != 0){ 842 AffineTransform inverseTransform = null; 843 try{ 844 inverseTransform = xform.createInverse(); 845 } catch(NoninvertibleTransformException e){ 846 throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED); 849 } 850 851 gc.transform(xform); 852 retVal = drawImage(img, 0, 0, null); 853 gc.transform(inverseTransform); 854 } else { 855 AffineTransform savTransform = new AffineTransform (gc.getTransform()); 856 gc.transform(xform); 857 retVal = drawImage(img, 0, 0, null); 858 gc.setTransform(savTransform); 859 } 860 861 return retVal; 862 863 } 864 865 866 889 public void drawImage(BufferedImage img, 890 BufferedImageOp op, 891 int x, 892 int y){ 893 977 img = op.filter(img, null); 982 drawImage(img, x, y, null); 983 } 985 986 987 1007 public void drawRenderedImage(RenderedImage img, 1008 AffineTransform trans2) { 1009 1010 Element image = 1011 getGenericImageHandler().createElement(getGeneratorContext()); 1012 AffineTransform trans1 1013 = getGenericImageHandler().handleImage( 1014 img, image, 1015 img.getMinX(), 1016 img.getMinY(), 1017 img.getWidth(), 1018 img.getHeight(), 1019 getGeneratorContext()); 1020 1021 AffineTransform xform; 1022 1023 if (trans2 == null) { 1026 xform = trans1; 1027 } else { 1028 if(trans1 == null) { 1029 xform = trans2; 1030 } else { 1031 xform = new AffineTransform (trans2); 1032 xform.concatenate(trans1); 1033 } 1034 } 1035 1036 if(xform == null) { 1037 domGroupManager.addElement(image); 1038 } else if(xform.getDeterminant() != 0){ 1039 AffineTransform inverseTransform = null; 1040 try{ 1041 inverseTransform = xform.createInverse(); 1042 }catch(NoninvertibleTransformException e){ 1043 throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED); 1046 } 1047 gc.transform(xform); 1048 domGroupManager.addElement(image); 1049 gc.transform(inverseTransform); 1050 } else { 1051 AffineTransform savTransform = new AffineTransform (gc.getTransform()); 1052 gc.transform(xform); 1053 domGroupManager.addElement(image); 1054 gc.setTransform(savTransform); 1055 } 1056 } 1057 1058 1088 public void drawRenderableImage(RenderableImage img, 1089 AffineTransform trans2){ 1090 1091 Element image = 1092 getGenericImageHandler().createElement(getGeneratorContext()); 1093 1094 AffineTransform trans1 = 1095 getGenericImageHandler().handleImage( 1096 img, image, 1097 img.getMinX(), 1098 img.getMinY(), 1099 img.getWidth(), 1100 img.getHeight(), 1101 getGeneratorContext()); 1102 1103 AffineTransform xform; 1104 1105 if (trans2 == null) { 1108 xform = trans1; 1109 } else { 1110 if(trans1 == null) { 1111 xform = trans2; 1112 } else { 1113 xform = new AffineTransform (trans2); 1114 xform.concatenate(trans1); 1115 } 1116 } 1117 1118 if (xform == null) { 1119 domGroupManager.addElement(image); 1120 } else if(xform.getDeterminant() != 0){ 1121 AffineTransform inverseTransform = null; 1122 try{ 1123 inverseTransform = xform.createInverse(); 1124 }catch(NoninvertibleTransformException e){ 1125 throw new SVGGraphics2DRuntimeException(ERR_UNEXPECTED); 1128 } 1129 gc.transform(xform); 1130 domGroupManager.addElement(image); 1131 gc.transform(inverseTransform); 1132 } else { 1133 AffineTransform savTransform = new AffineTransform (gc.getTransform()); 1134 gc.transform(xform); 1135 domGroupManager.addElement(image); 1136 gc.setTransform(savTransform); 1137 } 1138 } 1139 1140 1141 1165 public void drawString(String s, float x, float y) { 1166 if (!textAsShapes) { 1167 1168 if (generatorCtx.svgFont) { 1169 domTreeManager.gcConverter.getFontConverter().recordFontUsage(s, getFont()); 1173 } 1174 1175 Font font = getFont(); 1176 1177 AffineTransform txtTxf = null; 1179 AffineTransform savTxf = getTransform(); 1180 1181 if (font != null){ 1182 txtTxf = font.getTransform(); 1183 if (txtTxf != null && !txtTxf.isIdentity()){ 1184 AffineTransform t = new AffineTransform (); 1188 t.translate(x, y); 1189 t.concatenate(txtTxf); 1190 t.translate(-x, -y); 1191 this.transform(t); 1192 } else { 1193 txtTxf = null; 1194 } 1195 } 1196 1197 Element text = 1198 getDOMFactory().createElementNS(SVG_NAMESPACE_URI, SVG_TEXT_TAG); 1199 text.setAttributeNS(null, SVG_X_ATTRIBUTE, 1200 generatorCtx.doubleString(x)); 1201 text.setAttributeNS(null, SVG_Y_ATTRIBUTE, 1202 generatorCtx.doubleString(y)); 1203 text.setAttributeNS(XML_NAMESPACE_URI, 1204 XML_SPACE_ATTRIBUTE, 1205 XML_PRESERVE_VALUE); 1206 text.appendChild(getDOMFactory().createTextNode(s)); 1207 domGroupManager.addElement(text, DOMGroupManager.FILL); 1208 1209 if (txtTxf != null){ 1210 this.setTransform(savTxf); 1211 } 1212 1213 } else { 1214 GlyphVector gv = getFont(). 1215 createGlyphVector(getFontRenderContext(), s); 1216 drawGlyphVector(gv, x, y); 1217 } 1218 } 1219 1220 1249 public void drawString(AttributedCharacterIterator iterator, 1250 float x, float y) { 1251 TextLayout layout = new TextLayout (iterator, getFontRenderContext()); 1252 layout.draw(this, x, y); 1253 } 1254 1255 1256 1270 public void fill(Shape s) { 1271 Element svgShape = shapeConverter.toSVG(s); 1272 if (svgShape != null) { 1273 domGroupManager.addElement(svgShape, DOMGroupManager.FILL); 1274 } 1275 } 1276 1277 1281 public GraphicsConfiguration getDeviceConfiguration(){ 1282 return null; 1284 } 1285 1286} 1287 | Popular Tags |