1 18 package org.apache.batik.bridge; 19 20 import java.awt.geom.AffineTransform ; 21 import java.util.StringTokenizer ; 22 23 import org.apache.batik.parser.AWTTransformProducer; 24 import org.apache.batik.parser.FragmentIdentifierHandler; 25 import org.apache.batik.parser.FragmentIdentifierParser; 26 import org.apache.batik.parser.ParseException; 27 import org.apache.batik.parser.PreserveAspectRatioParser; 28 import org.apache.batik.util.SVGConstants; 29 import org.w3c.dom.Document ; 30 import org.w3c.dom.Element ; 31 import org.w3c.dom.Node ; 32 import org.w3c.dom.svg.SVGPreserveAspectRatio; 33 34 40 public abstract class ViewBox implements SVGConstants, ErrorConstants { 41 42 45 protected ViewBox() { } 46 47 59 public static AffineTransform getViewTransform(String ref, 60 Element e, 61 float w, 62 float h) { 63 64 if (ref == null || ref.length() == 0) { 66 return getPreserveAspectRatioTransform(e, w, h); 67 } 68 69 ViewHandler vh = new ViewHandler(); 70 FragmentIdentifierParser p = new FragmentIdentifierParser(); 71 p.setFragmentIdentifierHandler(vh); 72 p.parse(ref); 73 74 Element attrDefElement = e; if (vh.hasId) { 76 Document document = e.getOwnerDocument(); 77 attrDefElement = document.getElementById(vh.id); 78 } 79 if (attrDefElement == null) { 80 throw new BridgeException(e, ERR_URI_MALFORMED, 81 new Object [] {ref}); 82 } 83 if (!(attrDefElement.getNamespaceURI().equals(SVG_NAMESPACE_URI) 86 && attrDefElement.getLocalName().equals(SVG_VIEW_TAG))) { 87 attrDefElement = getClosestAncestorSVGElement(e); 88 } 89 90 float [] vb; 92 if (vh.hasViewBox) { 93 vb = vh.viewBox; 94 } else { 95 String viewBoxStr = attrDefElement.getAttributeNS 96 (null, SVG_VIEW_BOX_ATTRIBUTE); 97 vb = parseViewBoxAttribute(attrDefElement, viewBoxStr); 98 } 99 100 short align; 102 boolean meet; 103 if (vh.hasPreserveAspectRatio) { 104 align = vh.align; 105 meet = vh.meet; 106 } else { 107 String aspectRatio = attrDefElement.getAttributeNS 108 (null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE); 109 PreserveAspectRatioParser pp = new PreserveAspectRatioParser(); 110 ViewHandler ph = new ViewHandler(); 111 pp.setPreserveAspectRatioHandler(ph); 112 try { 113 pp.parse(aspectRatio); 114 } catch (ParseException ex) { 115 throw new BridgeException 116 (attrDefElement, ERR_ATTRIBUTE_VALUE_MALFORMED, 117 new Object [] {SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, 118 aspectRatio, ex}); 119 } 120 align = ph.align; 121 meet = ph.meet; 122 } 123 124 AffineTransform transform 126 = getPreserveAspectRatioTransform(vb, align, meet, w, h); 127 if (vh.hasTransform) { 128 transform.concatenate(vh.getAffineTransform()); 129 } 130 return transform; 131 } 132 133 138 private static Element getClosestAncestorSVGElement(Element e) { 139 for (Node n = e; 140 n != null && n.getNodeType() == Node.ELEMENT_NODE; 141 n = n.getParentNode()) { 142 Element tmp = (Element )n; 143 if (tmp.getNamespaceURI().equals(SVG_NAMESPACE_URI) 144 && tmp.getLocalName().equals(SVG_SVG_TAG)) { 145 return tmp; 146 } 147 } 148 return null; 149 } 150 151 159 public static AffineTransform getPreserveAspectRatioTransform(Element e, 160 float w, 161 float h) { 162 String viewBox 163 = e.getAttributeNS(null, SVG_VIEW_BOX_ATTRIBUTE); 164 165 String aspectRatio 166 = e.getAttributeNS(null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE); 167 168 return getPreserveAspectRatioTransform(e, viewBox, aspectRatio, w, h); 169 } 170 171 180 public static 181 AffineTransform getPreserveAspectRatioTransform(Element e, 182 String viewBox, 183 String aspectRatio, 184 float w, 185 float h) { 186 187 if (viewBox.length() == 0) { 189 return new AffineTransform (); 190 } 191 float[] vb = parseViewBoxAttribute(e, viewBox); 192 193 PreserveAspectRatioParser p = new PreserveAspectRatioParser(); 195 ViewHandler ph = new ViewHandler(); 196 p.setPreserveAspectRatioHandler(ph); 197 try { 198 p.parse(aspectRatio); 199 } catch (ParseException ex) { 200 throw new BridgeException 201 (e, ERR_ATTRIBUTE_VALUE_MALFORMED, 202 new Object [] {SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, 203 aspectRatio, ex}); 204 } 205 206 return getPreserveAspectRatioTransform(vb, ph.align, ph.meet, w, h); 207 } 208 209 218 public static 219 AffineTransform getPreserveAspectRatioTransform(Element e, 220 float [] vb, 221 float w, 222 float h) { 223 224 String aspectRatio 225 = e.getAttributeNS(null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE); 226 227 PreserveAspectRatioParser p = new PreserveAspectRatioParser(); 229 ViewHandler ph = new ViewHandler(); 230 p.setPreserveAspectRatioHandler(ph); 231 try { 232 p.parse(aspectRatio); 233 } catch (ParseException ex) { 234 throw new BridgeException 235 (e, ERR_ATTRIBUTE_VALUE_MALFORMED, 236 new Object [] {SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, 237 aspectRatio, ex}); 238 } 239 240 return getPreserveAspectRatioTransform(vb, ph.align, ph.meet, w, h); 241 } 242 243 249 public static float[] parseViewBoxAttribute(Element e, String value) { 250 if (value.length() == 0) { 251 return null; 252 } 253 int i = 0; 254 float[] vb = new float[4]; 255 StringTokenizer st = new StringTokenizer (value, " ,"); 256 try { 257 while (i < 4 && st.hasMoreTokens()) { 258 vb[i] = Float.parseFloat(st.nextToken()); 259 i++; 260 } 261 } catch (NumberFormatException ex) { 262 throw new BridgeException 263 (e, ERR_ATTRIBUTE_VALUE_MALFORMED, 264 new Object [] {SVG_VIEW_BOX_ATTRIBUTE, value, ex}); 265 } 266 if (i != 4) { 267 throw new BridgeException 268 (e, ERR_ATTRIBUTE_VALUE_MALFORMED, 269 new Object [] {SVG_VIEW_BOX_ATTRIBUTE, value}); 270 } 271 if (vb[2] < 0 || vb[3] < 0) { 273 throw new BridgeException 274 (e, ERR_ATTRIBUTE_VALUE_MALFORMED, 275 new Object [] {SVG_VIEW_BOX_ATTRIBUTE, value}); 276 } 277 if (vb[2] == 0 || vb[3] == 0) { 279 return null; } 281 return vb; 282 } 283 284 294 public static 295 AffineTransform getPreserveAspectRatioTransform(float [] vb, 296 short align, 297 boolean meet, 298 float w, 299 float h) { 300 if (vb == null) { 301 return new AffineTransform (); 302 } 303 304 AffineTransform result = new AffineTransform (); 305 float vpar = vb[2] / vb[3]; 306 float svgar = w / h; 307 308 if (align == SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE) { 309 result.scale(w / vb[2], h / vb[3]); 310 result.translate(-vb[0], -vb[1]); 311 } else if (vpar < svgar && meet || vpar >= svgar && !meet) { 312 float sf = h / vb[3]; 313 result.scale(sf, sf); 314 switch (align) { 315 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMIN: 316 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMID: 317 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMAX: 318 result.translate(-vb[0], -vb[1]); 319 break; 320 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN: 321 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID: 322 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX: 323 result.translate(-vb[0] - (vb[2] - w * vb[3] / h) / 2 , -vb[1]); 324 break; 325 default: 326 result.translate(-vb[0] - (vb[2] - w * vb[3] / h) , -vb[1]); 327 } 328 } else { 329 float sf = w / vb[2]; 330 result.scale(sf, sf); 331 switch (align) { 332 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMIN: 333 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN: 334 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMIN: 335 result.translate(-vb[0], -vb[1]); 336 break; 337 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMID: 338 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID: 339 case SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMID: 340 result.translate(-vb[0], -vb[1] - (vb[3] - h * vb[2] / w) / 2); 341 break; 342 default: 343 result.translate(-vb[0], -vb[1] - (vb[3] - h * vb[2] / w)); 344 } 345 } 346 return result; 347 } 348 349 354 protected static class ViewHandler extends AWTTransformProducer 355 implements FragmentIdentifierHandler { 356 357 358 361 protected ViewHandler() { } 362 363 367 public boolean hasTransform; 368 369 public void endTransformList() throws ParseException { 370 super.endTransformList(); 371 hasTransform = true; 372 } 373 374 378 public boolean hasId; 379 public boolean hasViewBox; 380 public boolean hasViewTargetParams; 381 public boolean hasZoomAndPanParams; 382 383 public String id; 384 public float [] viewBox; 385 public String viewTargetParams; 386 public boolean isMagnify; 387 388 393 public void startFragmentIdentifier() throws ParseException { } 394 395 401 public void idReference(String s) throws ParseException { 402 id = s; 403 hasId = true; 404 } 405 406 415 public void viewBox(float x, float y, float width, float height) 416 throws ParseException { 417 418 hasViewBox = true; 419 viewBox = new float[4]; 420 viewBox[0] = x; 421 viewBox[1] = y; 422 viewBox[2] = width; 423 viewBox[3] = height; 424 } 425 426 431 public void startViewTarget() throws ParseException { } 432 433 440 public void viewTarget(String name) throws ParseException { 441 viewTargetParams = name; 442 hasViewTargetParams = true; 443 } 444 445 450 public void endViewTarget() throws ParseException { } 451 452 458 public void zoomAndPan(boolean magnify) { 459 isMagnify = magnify; 460 hasZoomAndPanParams = true; 461 } 462 463 468 public void endFragmentIdentifier() throws ParseException { } 469 470 474 public boolean hasPreserveAspectRatio; 475 476 public short align; 477 public boolean meet = true; 478 479 484 public void startPreserveAspectRatio() throws ParseException { } 485 486 491 public void none() throws ParseException { 492 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE; 493 } 494 495 500 public void xMaxYMax() throws ParseException { 501 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMAX; 502 } 503 504 509 public void xMaxYMid() throws ParseException { 510 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMID; 511 } 512 513 518 public void xMaxYMin() throws ParseException { 519 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMIN; 520 } 521 522 527 public void xMidYMax() throws ParseException { 528 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX; 529 } 530 531 536 public void xMidYMid() throws ParseException { 537 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID; 538 } 539 540 545 public void xMidYMin() throws ParseException { 546 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN; 547 } 548 549 554 public void xMinYMax() throws ParseException { 555 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMAX; 556 } 557 558 563 public void xMinYMid() throws ParseException { 564 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMID; 565 } 566 567 572 public void xMinYMin() throws ParseException { 573 align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMIN; 574 } 575 576 581 public void meet() throws ParseException { 582 meet = true; 583 } 584 585 590 public void slice() throws ParseException { 591 meet = false; 592 } 593 594 599 public void endPreserveAspectRatio() throws ParseException { 600 hasPreserveAspectRatio = true; 601 } 602 } 603 } 604 | Popular Tags |