1 18 package org.apache.batik.bridge; 19 20 import java.awt.Graphics2D ; 21 import java.awt.Paint ; 22 import java.awt.Shape ; 23 import java.awt.geom.AffineTransform ; 24 import java.awt.geom.Rectangle2D ; 25 import java.util.Iterator ; 26 import java.util.LinkedList ; 27 import java.util.List ; 28 29 import org.apache.batik.dom.svg.SVGOMDocument; 30 import org.apache.batik.dom.util.XLinkSupport; 31 import org.apache.batik.ext.awt.image.ConcreteComponentTransferFunction; 32 import org.apache.batik.ext.awt.image.renderable.ComponentTransferRable8Bit; 33 import org.apache.batik.ext.awt.image.renderable.Filter; 34 import org.apache.batik.gvt.AbstractGraphicsNode; 35 import org.apache.batik.gvt.RootGraphicsNode; 36 import org.apache.batik.gvt.GraphicsNode; 37 import org.apache.batik.gvt.PatternPaint; 38 import org.apache.batik.util.ParsedURL; 39 import org.w3c.dom.Element ; 40 import org.w3c.dom.Node ; 41 42 48 public class SVGPatternElementBridge extends AbstractSVGBridge 49 implements PaintBridge, ErrorConstants { 50 51 54 public SVGPatternElementBridge() {} 55 56 59 public String getLocalName() { 60 return SVG_PATTERN_TAG; 61 } 62 63 72 public Paint createPaint(BridgeContext ctx, 73 Element patternElement, 74 Element paintedElement, 75 GraphicsNode paintedNode, 76 float opacity) { 77 78 79 RootGraphicsNode patternContentNode; 81 patternContentNode = (RootGraphicsNode) 82 ctx.getElementData(patternElement); 83 84 if (patternContentNode == null) { 85 patternContentNode = extractPatternContent(patternElement, ctx); 86 ctx.setElementData(patternElement, patternContentNode); 87 } 88 if (patternContentNode == null) { 89 return null; } 91 92 Rectangle2D patternRegion = SVGUtilities.convertPatternRegion 95 (patternElement, paintedElement, paintedNode, ctx); 96 97 String s; 98 99 AffineTransform patternTransform; 101 s = SVGUtilities.getChainableAttributeNS 102 (patternElement, null, SVG_PATTERN_TRANSFORM_ATTRIBUTE, ctx); 103 if (s.length() != 0) { 104 patternTransform = SVGUtilities.convertTransform 105 (patternElement, SVG_PATTERN_TRANSFORM_ATTRIBUTE, s); 106 } else { 107 patternTransform = new AffineTransform (); 108 } 109 110 boolean overflowIsHidden = CSSUtilities.convertOverflow(patternElement); 112 113 short contentCoordSystem; 115 s = SVGUtilities.getChainableAttributeNS 116 (patternElement, null, SVG_PATTERN_CONTENT_UNITS_ATTRIBUTE, ctx); 117 if (s.length() == 0) { 118 contentCoordSystem = SVGUtilities.USER_SPACE_ON_USE; 119 } else { 120 contentCoordSystem = SVGUtilities.parseCoordinateSystem 121 (patternElement, SVG_PATTERN_CONTENT_UNITS_ATTRIBUTE, s); 122 } 123 124 AffineTransform patternContentTransform = new AffineTransform (); 150 151 patternContentTransform.translate(patternRegion.getX(), 155 patternRegion.getY()); 156 157 161 String viewBoxStr = SVGUtilities.getChainableAttributeNS 163 (patternElement, null, SVG_VIEW_BOX_ATTRIBUTE, ctx); 164 165 if (viewBoxStr.length() > 0) { 166 String aspectRatioStr = SVGUtilities.getChainableAttributeNS 169 (patternElement, null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, ctx); 170 float w = (float)patternRegion.getWidth(); 171 float h = (float)patternRegion.getHeight(); 172 AffineTransform preserveAspectRatioTransform 173 = ViewBox.getPreserveAspectRatioTransform 174 (patternElement, viewBoxStr, aspectRatioStr, w, h); 175 176 patternContentTransform.concatenate(preserveAspectRatioTransform); 177 } else { 178 if (contentCoordSystem == SVGUtilities.OBJECT_BOUNDING_BOX){ 182 AffineTransform patternContentUnitsTransform 183 = new AffineTransform (); 184 Rectangle2D objectBoundingBox = 185 paintedNode.getGeometryBounds(); 186 patternContentUnitsTransform.translate 187 (objectBoundingBox.getX(), 188 objectBoundingBox.getY()); 189 190 patternContentUnitsTransform.scale 191 (objectBoundingBox.getWidth(), 192 objectBoundingBox.getHeight()); 193 194 patternContentTransform.concatenate 195 (patternContentUnitsTransform); 196 } 197 } 198 199 GraphicsNode gn = new PatternGraphicsNode(patternContentNode); 205 206 gn.setTransform(patternContentTransform); 207 208 if (opacity != 1) { 210 Filter filter = gn.getGraphicsNodeRable(true); 211 filter = new ComponentTransferRable8Bit 212 (filter, 213 ConcreteComponentTransferFunction.getLinearTransfer 214 (opacity, 0), ConcreteComponentTransferFunction.getIdentityTransfer(), ConcreteComponentTransferFunction.getIdentityTransfer(), ConcreteComponentTransferFunction.getIdentityTransfer()); gn.setFilter(filter); 219 } 220 221 222 223 return new PatternPaint(gn, 224 patternRegion, 225 !overflowIsHidden, 226 patternTransform); 227 228 } 229 230 239 protected static 240 RootGraphicsNode extractPatternContent(Element patternElement, 241 BridgeContext ctx) { 242 243 List refs = new LinkedList (); 244 for (;;) { 245 RootGraphicsNode content 246 = extractLocalPatternContent(patternElement, ctx); 247 if (content != null) { 248 return content; } 250 String uri = XLinkSupport.getXLinkHref(patternElement); 251 if (uri.length() == 0) { 252 return null; } 254 SVGOMDocument doc = 256 (SVGOMDocument)patternElement.getOwnerDocument(); 257 ParsedURL purl = new ParsedURL(doc.getURL(), uri); 258 if (!purl.complete()) 259 throw new BridgeException(patternElement, 260 ERR_URI_MALFORMED, 261 new Object [] {uri}); 262 263 if (contains(refs, purl)) { 264 throw new BridgeException(patternElement, 265 ERR_XLINK_HREF_CIRCULAR_DEPENDENCIES, 266 new Object [] {uri}); 267 } 268 refs.add(purl); 269 patternElement = ctx.getReferencedElement(patternElement, uri); 270 } 271 } 272 273 279 protected static 280 RootGraphicsNode extractLocalPatternContent(Element e, 281 BridgeContext ctx) { 282 283 GVTBuilder builder = ctx.getGVTBuilder(); 284 RootGraphicsNode content = null; 285 for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) { 286 if (n.getNodeType() != Node.ELEMENT_NODE) { 288 continue; 289 } 290 291 GraphicsNode gn = builder.build(ctx, (Element )n); 292 if (gn != null) { 294 if (content == null) { 296 content = new RootGraphicsNode(); 297 } 298 content.getChildren().add(gn); 299 } 300 } 301 return content; 302 } 303 304 310 private static boolean contains(List urls, ParsedURL key) { 311 Iterator iter = urls.iterator(); 312 while (iter.hasNext()) { 313 if (key.equals(iter.next())) 314 return true; 315 } 316 return false; 317 } 318 319 public static class PatternGraphicsNode extends AbstractGraphicsNode { 320 GraphicsNode pcn; 321 Rectangle2D pBounds; 322 Rectangle2D gBounds; 323 Rectangle2D sBounds; 324 Shape oShape; 325 public PatternGraphicsNode(GraphicsNode gn) { 326 this.pcn = gn; 327 } 328 public void primitivePaint(Graphics2D g2d) { 329 pcn.paint(g2d); 330 } 331 public Rectangle2D getPrimitiveBounds() { 332 if (pBounds != null) return pBounds; 333 pBounds = pcn.getTransformedBounds(IDENTITY); 334 return pBounds; 335 } 336 public Rectangle2D getGeometryBounds() { 337 if (gBounds != null) return gBounds; 338 gBounds = pcn.getTransformedGeometryBounds(IDENTITY); 339 return gBounds; 340 } 341 public Rectangle2D getSensitiveBounds() { 342 if (sBounds != null) return sBounds; 343 sBounds = pcn.getTransformedSensitiveBounds(IDENTITY); 344 return sBounds; 345 } 346 public Shape getOutline() { 347 if (oShape != null) return oShape; 348 oShape = pcn.getOutline(); 349 AffineTransform tr = pcn.getTransform(); 350 if (tr != null) 351 oShape = tr.createTransformedShape(oShape); 352 return oShape; 353 } 354 protected void invalidateGeometryCache() { 355 pBounds = null; 356 gBounds = null; 357 sBounds = null; 358 oShape = null; 359 super.invalidateGeometryCache(); 360 } 361 362 } 363 364 } 365 366 | Popular Tags |