| 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 &nb
|