1 18 package org.apache.batik.bridge; 19 20 import java.awt.geom.AffineTransform ; 21 import java.awt.geom.Point2D ; 22 import java.awt.geom.Rectangle2D ; 23 24 import org.apache.batik.css.engine.SVGCSSEngine; 25 import org.apache.batik.css.engine.value.Value; 26 import org.apache.batik.ext.awt.image.renderable.ClipRable8Bit; 27 import org.apache.batik.ext.awt.image.renderable.Filter; 28 import org.apache.batik.gvt.CompositeGraphicsNode; 29 import org.apache.batik.gvt.GraphicsNode; 30 import org.apache.batik.gvt.Marker; 31 import org.w3c.dom.Element ; 32 import org.w3c.dom.Node ; 33 34 40 public class SVGMarkerElementBridge extends AbstractSVGBridge 41 implements MarkerBridge, ErrorConstants { 42 43 46 protected SVGMarkerElementBridge() {} 47 48 51 public String getLocalName() { 52 return SVG_MARKER_TAG; 53 } 54 55 62 public Marker createMarker(BridgeContext ctx, 63 Element markerElement, 64 Element paintedElement) { 65 66 GVTBuilder builder = ctx.getGVTBuilder(); 67 68 CompositeGraphicsNode markerContentNode 69 = new CompositeGraphicsNode(); 70 71 boolean hasChildren = false; 73 for(Node n = markerElement.getFirstChild(); 74 n != null; 75 n = n.getNextSibling()) { 76 77 if (n.getNodeType() != Node.ELEMENT_NODE) { 79 continue; 80 } 81 Element child = (Element )n; 82 GraphicsNode markerNode = builder.build(ctx, child) ; 83 if (markerNode == null) { 85 continue; } 87 hasChildren = true; 88 markerContentNode.getChildren().add(markerNode); 89 } 90 if (!hasChildren) { 91 return null; } 93 94 String s; 95 UnitProcessor.Context uctx 96 = UnitProcessor.createContext(ctx, paintedElement); 97 98 float markerWidth = 3; 100 s = markerElement.getAttributeNS(null, SVG_MARKER_WIDTH_ATTRIBUTE); 101 if (s.length() != 0) { 102 markerWidth = UnitProcessor.svgHorizontalLengthToUserSpace 103 (s, SVG_MARKER_WIDTH_ATTRIBUTE, uctx); 104 } 105 if (markerWidth == 0) { 106 return null; 108 } 109 110 float markerHeight = 3; 112 s = markerElement.getAttributeNS(null, SVG_MARKER_HEIGHT_ATTRIBUTE); 113 if (s.length() != 0) { 114 markerHeight = UnitProcessor.svgVerticalLengthToUserSpace 115 (s, SVG_MARKER_HEIGHT_ATTRIBUTE, uctx); 116 } 117 if (markerHeight == 0) { 118 return null; 120 } 121 122 double orient; 124 s = markerElement.getAttributeNS(null, SVG_ORIENT_ATTRIBUTE); 125 if (s.length() == 0) { 126 orient = 0; 127 } else if (SVG_AUTO_VALUE.equals(s)) { 128 orient = Double.NaN; 129 } else { 130 try { 131 orient = SVGUtilities.convertSVGNumber(s); 132 } catch (NumberFormatException ex) { 133 throw new BridgeException 134 (markerElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 135 new Object [] {SVG_ORIENT_ATTRIBUTE, s}); 136 } 137 } 138 139 Value val = CSSUtilities.getComputedStyle 141 (paintedElement, SVGCSSEngine.STROKE_WIDTH_INDEX); 142 float strokeWidth = val.getFloatValue(); 143 144 short unitsType; 146 s = markerElement.getAttributeNS(null, SVG_MARKER_UNITS_ATTRIBUTE); 147 if (s.length() == 0) { 148 unitsType = SVGUtilities.STROKE_WIDTH; 149 } else { 150 unitsType = SVGUtilities.parseMarkerCoordinateSystem 151 (markerElement, SVG_MARKER_UNITS_ATTRIBUTE, s); 152 } 153 154 158 AffineTransform markerTxf; 160 if (unitsType == SVGUtilities.STROKE_WIDTH) { 161 markerTxf = new AffineTransform (); 162 markerTxf.scale(strokeWidth, strokeWidth); 163 } else { 164 markerTxf = new AffineTransform (); 165 } 166 167 AffineTransform preserveAspectRatioTransform 170 = ViewBox.getPreserveAspectRatioTransform(markerElement, 171 markerWidth, 172 markerHeight); 173 if (preserveAspectRatioTransform == null) { 174 return null; 176 } else { 177 markerTxf.concatenate(preserveAspectRatioTransform); 178 } 179 markerContentNode.setTransform(markerTxf); 181 182 if (CSSUtilities.convertOverflow(markerElement)) { Rectangle2D markerClip; 185 float [] offsets = CSSUtilities.convertClip(markerElement); 186 if (offsets == null) { markerClip 188 = new Rectangle2D.Float (0, 189 0, 190 strokeWidth * markerWidth, 191 strokeWidth * markerHeight); 192 } else { markerClip = new Rectangle2D.Float 198 (offsets[3], 199 offsets[0], 200 strokeWidth * markerWidth - offsets[1] - offsets[3], 201 strokeWidth * markerHeight - offsets[2] - offsets[0]); 202 } 203 204 CompositeGraphicsNode comp = new CompositeGraphicsNode(); 205 comp.getChildren().add(markerContentNode); 206 Filter clipSrc = comp.getGraphicsNodeRable(true); 207 comp.setClip(new ClipRable8Bit(clipSrc, markerClip)); 208 markerContentNode = comp; 209 } 210 211 float refX = 0; 213 s = markerElement.getAttributeNS(null, SVG_REF_X_ATTRIBUTE); 214 if (s.length() != 0) { 215 refX = UnitProcessor.svgHorizontalCoordinateToUserSpace 216 (s, SVG_REF_X_ATTRIBUTE, uctx); 217 } 218 219 float refY = 0; 221 s = markerElement.getAttributeNS(null, SVG_REF_Y_ATTRIBUTE); 222 if (s.length() != 0) { 223 refY = UnitProcessor.svgVerticalCoordinateToUserSpace 224 (s, SVG_REF_Y_ATTRIBUTE, uctx); 225 } 226 227 231 float ref[] = {refX, refY}; 238 markerTxf.transform(ref, 0, ref, 0, 1); 239 Marker marker = new Marker(markerContentNode, 240 new Point2D.Float (ref[0], ref[1]), 241 orient); 242 243 return marker; 244 } 245 } 246 | Popular Tags |