1 18 package org.apache.batik.bridge; 19 20 import java.awt.Color ; 21 import java.awt.Paint ; 22 import java.awt.geom.AffineTransform ; 23 import java.util.Iterator ; 24 import java.util.LinkedList ; 25 import java.util.List ; 26 27 import org.apache.batik.dom.svg.SVGOMDocument; 28 import org.apache.batik.dom.util.XLinkSupport; 29 import org.apache.batik.ext.awt.MultipleGradientPaint; 30 import org.apache.batik.gvt.GraphicsNode; 31 import org.apache.batik.util.ParsedURL; 32 import org.w3c.dom.Element ; 33 import org.w3c.dom.Node ; 34 35 41 public abstract class AbstractSVGGradientElementBridge extends AbstractSVGBridge 42 implements PaintBridge, ErrorConstants { 43 44 47 protected AbstractSVGGradientElementBridge() {} 48 49 58 public Paint createPaint(BridgeContext ctx, 59 Element paintElement, 60 Element paintedElement, 61 GraphicsNode paintedNode, 62 float opacity) { 63 64 String s; 65 66 List stops = extractStop(paintElement, opacity, ctx); 68 if (stops == null) { 70 return null; 71 } 72 int stopLength = stops.size(); 73 if (stopLength == 1) { 75 return ((Stop)stops.get(0)).color; 76 } 77 float [] offsets = new float[stopLength]; 78 Color [] colors = new Color [stopLength]; 79 Iterator iter = stops.iterator(); 80 for (int i=0; iter.hasNext(); ++i) { 81 Stop stop = (Stop)iter.next(); 82 offsets[i] = stop.offset; 83 colors[i] = stop.color; 84 } 85 86 MultipleGradientPaint.CycleMethodEnum spreadMethod 88 = MultipleGradientPaint.NO_CYCLE; 89 s = SVGUtilities.getChainableAttributeNS 90 (paintElement, null, SVG_SPREAD_METHOD_ATTRIBUTE, ctx); 91 if (s.length() != 0) { 92 spreadMethod = convertSpreadMethod(paintElement, s); 93 } 94 95 MultipleGradientPaint.ColorSpaceEnum colorSpace 97 = CSSUtilities.convertColorInterpolation(paintElement); 98 99 AffineTransform transform; 101 s = SVGUtilities.getChainableAttributeNS 102 (paintElement, null, SVG_GRADIENT_TRANSFORM_ATTRIBUTE, ctx); 103 if (s.length() != 0) { 104 transform = SVGUtilities.convertTransform 105 (paintElement, SVG_GRADIENT_TRANSFORM_ATTRIBUTE, s); 106 } else { 107 transform = new AffineTransform (); 108 } 109 110 Paint paint = buildGradient(paintElement, 111 paintedElement, 112 paintedNode, 113 spreadMethod, 114 colorSpace, 115 transform, 116 colors, 117 offsets, 118 ctx); 119 return paint; 120 } 121 122 135 protected abstract 136 Paint buildGradient(Element paintElement, 137 Element paintedElement, 138 GraphicsNode paintedNode, 139 MultipleGradientPaint.CycleMethodEnum spreadMethod, 140 MultipleGradientPaint.ColorSpaceEnum colorSpace, 141 AffineTransform transform, 142 Color [] colors, 143 float [] offsets, 144 BridgeContext ctx); 145 146 148 154 protected static MultipleGradientPaint.CycleMethodEnum convertSpreadMethod 155 (Element paintElement, String s) { 156 if (SVG_REPEAT_VALUE.equals(s)) { 157 return MultipleGradientPaint.REPEAT; 158 } 159 if (SVG_REFLECT_VALUE.equals(s)) { 160 return MultipleGradientPaint.REFLECT; 161 } 162 if (SVG_PAD_VALUE.equals(s)) { 163 return MultipleGradientPaint.NO_CYCLE; 164 } 165 throw new BridgeException 166 (paintElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 167 new Object [] {SVG_SPREAD_METHOD_ATTRIBUTE, s}); 168 } 169 170 179 protected static List extractStop(Element paintElement, 180 float opacity, 181 BridgeContext ctx) { 182 183 List refs = new LinkedList (); 184 for (;;) { 185 List stops = extractLocalStop(paintElement, opacity, ctx); 186 if (stops != null) { 187 return stops; } 189 String uri = XLinkSupport.getXLinkHref(paintElement); 190 if (uri.length() == 0) { 191 return null; } 193 SVGOMDocument doc = (SVGOMDocument)paintElement.getOwnerDocument(); 195 ParsedURL purl = new ParsedURL(doc.getURL(), uri); 196 if (!purl.complete()) 197 throw new BridgeException(paintElement, 198 ERR_URI_MALFORMED, 199 new Object [] {uri}); 200 201 if (contains(refs, purl)) { 202 throw new BridgeException(paintElement, 203 ERR_XLINK_HREF_CIRCULAR_DEPENDENCIES, 204 new Object [] {uri}); 205 } 206 refs.add(purl); 207 paintElement = ctx.getReferencedElement(paintElement, uri); 208 } 209 } 210 211 219 protected static List extractLocalStop(Element gradientElement, 220 float opacity, 221 BridgeContext ctx) { 222 LinkedList stops = null; 223 Stop previous = null; 224 for (Node n = gradientElement.getFirstChild(); 225 n != null; 226 n = n.getNextSibling()) { 227 228 if ((n.getNodeType() != Node.ELEMENT_NODE)) { 229 continue; 230 } 231 232 Element e = (Element )n; 233 Bridge bridge = ctx.getBridge(e); 234 if (bridge == null || !(bridge instanceof SVGStopElementBridge)) { 235 continue; 236 } 237 Stop stop = ((SVGStopElementBridge)bridge).createStop 238 (ctx, gradientElement, e, opacity); 239 if (stops == null) { 240 stops = new LinkedList (); 241 } 242 if (previous != null) { 243 if (stop.offset < previous.offset) { 244 stop.offset = previous.offset; 245 } 246 } 247 stops.add(stop); 248 previous = stop; 249 } 250 return stops; 251 } 252 253 259 private static boolean contains(List urls, ParsedURL key) { 260 Iterator iter = urls.iterator(); 261 while (iter.hasNext()) { 262 if (key.equals(iter.next())) 263 return true; 264 } 265 return false; 266 } 267 268 271 public static class Stop { 272 273 274 public Color color; 275 276 public float offset; 277 278 284 public Stop(Color color, float offset) { 285 this.color = color; 286 this.offset = offset; 287 } 288 } 289 290 293 public static class SVGStopElementBridge extends AbstractSVGBridge 294 implements Bridge { 295 296 299 public String getLocalName() { 300 return SVG_STOP_TAG; 301 } 302 303 311 public Stop createStop(BridgeContext ctx, 312 Element gradientElement, 313 Element stopElement, 314 float opacity) { 315 316 String s = stopElement.getAttributeNS(null, SVG_OFFSET_ATTRIBUTE); 317 if (s.length() == 0) { 318 throw new BridgeException(stopElement, ERR_ATTRIBUTE_MISSING, 319 new Object [] {SVG_OFFSET_ATTRIBUTE}); 320 } 321 float offset; 322 try { 323 offset = SVGUtilities.convertRatio(s); 324 } catch (NumberFormatException ex) { 325 throw new BridgeException 326 (stopElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 327 new Object [] {SVG_OFFSET_ATTRIBUTE, s, ex}); 328 } 329 Color color 330 = CSSUtilities.convertStopColor(stopElement, opacity, ctx); 331 332 return new Stop(color, offset); 333 } 334 } 335 } 336 | Popular Tags |