1 18 package org.apache.batik.bridge; 19 20 import java.awt.AlphaComposite ; 21 import java.awt.Color ; 22 import java.awt.Composite ; 23 import java.awt.Cursor ; 24 import java.awt.RenderingHints ; 25 import java.awt.geom.GeneralPath ; 26 import java.awt.geom.Rectangle2D ; 27 28 import org.apache.batik.css.engine.CSSEngine; 29 import org.apache.batik.css.engine.CSSStylableElement; 30 import org.apache.batik.css.engine.SVGCSSEngine; 31 import org.apache.batik.css.engine.value.ListValue; 32 import org.apache.batik.css.engine.value.Value; 33 import org.apache.batik.css.engine.value.svg.ICCColor; 34 import org.apache.batik.dom.svg.SVGOMDocument; 35 import org.apache.batik.ext.awt.MultipleGradientPaint; 36 import org.apache.batik.ext.awt.image.renderable.ClipRable; 37 import org.apache.batik.ext.awt.image.renderable.Filter; 38 import org.apache.batik.gvt.CompositeGraphicsNode; 39 import org.apache.batik.gvt.GraphicsNode; 40 import org.apache.batik.gvt.filter.Mask; 41 import org.apache.batik.util.CSSConstants; 42 import org.apache.batik.util.XMLConstants; 43 import org.w3c.dom.Element ; 44 import org.w3c.dom.css.CSSPrimitiveValue; 45 import org.w3c.dom.css.CSSValue; 46 47 55 public abstract class CSSUtilities 56 implements CSSConstants, ErrorConstants, XMLConstants { 57 58 61 protected CSSUtilities() {} 62 63 67 71 public static CSSEngine getCSSEngine(Element e) { 72 return ((SVGOMDocument)e.getOwnerDocument()).getCSSEngine(); 73 } 74 75 78 public static Value getComputedStyle(Element e, int property) { 79 CSSEngine engine = getCSSEngine(e); 80 if (engine == null) return null; 81 return engine.getComputedStyle((CSSStylableElement)e, 82 null, property); 83 } 84 85 89 102 public static int convertPointerEvents(Element e) { 103 Value v = getComputedStyle(e, SVGCSSEngine.POINTER_EVENTS_INDEX); 104 String s = v.getStringValue(); 105 switch(s.charAt(0)) { 106 case 'v': 107 if (s.length() == 7) { 108 return GraphicsNode.VISIBLE; 109 } else { 110 switch(s.charAt(7)) { 111 case 'p': 112 return GraphicsNode.VISIBLE_PAINTED; 113 case 'f': 114 return GraphicsNode.VISIBLE_FILL; 115 case 's': 116 return GraphicsNode.VISIBLE_STROKE; 117 default: 118 throw new Error (); } 120 } 121 case 'p': 122 return GraphicsNode.PAINTED; 123 case 'f': 124 return GraphicsNode.FILL; 125 case 's': 126 return GraphicsNode.STROKE; 127 case 'a': 128 return GraphicsNode.ALL; 129 case 'n': 130 return GraphicsNode.NONE; 131 default: 132 throw new Error (); } 134 } 135 136 140 146 public static Rectangle2D convertEnableBackground(Element e ) { 148 Value v = getComputedStyle(e, SVGCSSEngine.ENABLE_BACKGROUND_INDEX); 149 if (v.getCssValueType() != CSSValue.CSS_VALUE_LIST) { 150 return null; } 152 ListValue lv = (ListValue)v; 153 int length = lv.getLength(); 154 switch (length) { 155 case 1: 156 return CompositeGraphicsNode.VIEWPORT; case 5: float x = lv.item(1).getFloatValue(); 159 float y = lv.item(2).getFloatValue(); 160 float w = lv.item(3).getFloatValue(); 161 float h = lv.item(4).getFloatValue(); 162 return new Rectangle2D.Float (x, y, w, h); 163 164 default: 165 throw new InternalError (); } 167 } 168 169 173 180 public static boolean convertColorInterpolationFilters(Element e) { 181 Value v = getComputedStyle(e, 182 SVGCSSEngine.COLOR_INTERPOLATION_FILTERS_INDEX); 183 return CSS_LINEARRGB_VALUE == v.getStringValue(); 184 } 185 186 190 196 public static MultipleGradientPaint.ColorSpaceEnum 197 convertColorInterpolation(Element e) { 198 Value v = getComputedStyle(e, SVGCSSEngine.COLOR_INTERPOLATION_INDEX); 199 return (CSS_LINEARRGB_VALUE == v.getStringValue()) 200 ? MultipleGradientPaint.LINEAR_RGB 201 : MultipleGradientPaint.SRGB; 202 } 203 204 208 211 public static boolean isAutoCursor(Element e) { 212 Value cursorValue = 213 CSSUtilities.getComputedStyle(e, 214 SVGCSSEngine.CURSOR_INDEX); 215 216 boolean isAuto = false; 217 if (cursorValue != null){ 218 if( 219 cursorValue.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE 220 && 221 cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT 222 && 223 cursorValue.getStringValue().charAt(0) == 'a' 224 ) { 225 isAuto = true; 226 } else if ( 227 cursorValue.getCssValueType() == CSSValue.CSS_VALUE_LIST 228 && 229 cursorValue.getLength() == 1) { 230 Value lValue = cursorValue.item(0); 231 if (lValue != null 232 && 233 lValue.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE 234 && 235 lValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT 236 && 237 lValue.getStringValue().charAt(0) == 'a') { 238 isAuto = true; 239 } 240 } 241 } 242 243 return isAuto; 244 } 245 246 252 public static Cursor 253 convertCursor(Element e, BridgeContext ctx) { 254 return ctx.getCursorManager().convertCursor(e); 255 } 256 257 262 298 public static RenderingHints convertShapeRendering(Element e, 299 RenderingHints hints) { 300 Value v = getComputedStyle(e, SVGCSSEngine.SHAPE_RENDERING_INDEX); 301 String s = v.getStringValue(); 302 int len = s.length(); 303 if ((len == 4) && (s.charAt(0) == 'a')) return hints; 305 if (len < 10) return hints; 307 if (hints == null) 308 hints = new RenderingHints (null); 309 310 switch(s.charAt(0)) { 311 case 'o': hints.put(RenderingHints.KEY_RENDERING, 313 RenderingHints.VALUE_RENDER_SPEED); 314 hints.put(RenderingHints.KEY_ANTIALIASING, 315 RenderingHints.VALUE_ANTIALIAS_OFF); 316 break; 317 case 'c': hints.put(RenderingHints.KEY_RENDERING, 319 RenderingHints.VALUE_RENDER_DEFAULT); 320 hints.put(RenderingHints.KEY_ANTIALIASING, 321 RenderingHints.VALUE_ANTIALIAS_OFF); 322 break; 323 case 'g': hints.put(RenderingHints.KEY_RENDERING, 325 RenderingHints.VALUE_RENDER_QUALITY); 326 hints.put(RenderingHints.KEY_ANTIALIASING, 327 RenderingHints.VALUE_ANTIALIAS_ON); 328 hints.put(RenderingHints.KEY_STROKE_CONTROL, 329 RenderingHints.VALUE_STROKE_PURE); 330 break; 331 } 332 return hints; 333 } 334 335 382 public static RenderingHints convertTextRendering(Element e, 383 RenderingHints hints) { 384 Value v = getComputedStyle(e, SVGCSSEngine.TEXT_RENDERING_INDEX); 385 String s = v.getStringValue(); 386 int len = s.length(); 387 if ((len == 4) && (s.charAt(0) == 'a')) return hints; 389 if (len < 13) return hints; 391 if (hints == null) 392 hints = new RenderingHints (null); 393 394 switch(s.charAt(8)) { 395 case 's': hints.put(RenderingHints.KEY_RENDERING, 397 RenderingHints.VALUE_RENDER_SPEED); 398 hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, 399 RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); 400 hints.put(RenderingHints.KEY_ANTIALIASING, 401 RenderingHints.VALUE_ANTIALIAS_OFF); 402 break; 405 case 'l': hints.put(RenderingHints.KEY_RENDERING, 407 RenderingHints.VALUE_RENDER_QUALITY); 408 hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, 409 RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); 410 hints.put(RenderingHints.KEY_ANTIALIASING, 411 RenderingHints.VALUE_ANTIALIAS_ON); 412 break; 415 case 'c': hints.put(RenderingHints.KEY_RENDERING, 417 RenderingHints.VALUE_RENDER_QUALITY); 418 hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, 419 RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 420 hints.put(RenderingHints.KEY_ANTIALIASING, 421 RenderingHints.VALUE_ANTIALIAS_ON); 422 hints.put(RenderingHints.KEY_FRACTIONALMETRICS, 423 RenderingHints.VALUE_FRACTIONALMETRICS_ON); 424 hints.put(RenderingHints.KEY_STROKE_CONTROL, 425 RenderingHints.VALUE_STROKE_PURE); 426 break; 427 } 428 return hints; 429 } 430 431 460 public static RenderingHints convertImageRendering(Element e, 461 RenderingHints hints) { 462 Value v = getComputedStyle(e, SVGCSSEngine.IMAGE_RENDERING_INDEX); 463 String s = v.getStringValue(); 464 int len = s.length(); 465 if ((len == 4) && (s.charAt(0) == 'a')) return hints; 467 if (len < 13) return hints; 469 if (hints == null) 470 hints = new RenderingHints (null); 471 472 switch(s.charAt(8)) { 473 case 's': hints.put(RenderingHints.KEY_RENDERING, 475 RenderingHints.VALUE_RENDER_SPEED); 476 hints.put(RenderingHints.KEY_INTERPOLATION, 477 RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); 478 break; 479 case 'q': hints.put(RenderingHints.KEY_RENDERING, 481 RenderingHints.VALUE_RENDER_QUALITY); 482 hints.put(RenderingHints.KEY_INTERPOLATION, 483 RenderingHints.VALUE_INTERPOLATION_BICUBIC); 484 break; 485 } 486 return hints; 487 } 488 489 518 public static RenderingHints convertColorRendering(Element e, 519 RenderingHints hints) { 520 Value v = getComputedStyle(e, SVGCSSEngine.COLOR_RENDERING_INDEX); 521 String s = v.getStringValue(); 522 int len = s.length(); 523 if ((len == 4) && (s.charAt(0) == 'a')) return hints; 525 if (len < 13) return hints; 527 if (hints == null) 528 hints = new RenderingHints (null); 529 530 switch(s.charAt(8)) { 531 case 's': hints.put(RenderingHints.KEY_COLOR_RENDERING, 533 RenderingHints.VALUE_COLOR_RENDER_SPEED); 534 hints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, 535 RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED); 536 break; 537 case 'q': hints.put(RenderingHints.KEY_COLOR_RENDERING, 539 RenderingHints.VALUE_COLOR_RENDER_QUALITY); 540 hints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, 541 RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 542 break; 543 } 544 return hints; 545 } 546 547 551 557 public static boolean convertDisplay(Element e) { 558 Value v = getComputedStyle(e, SVGCSSEngine.DISPLAY_INDEX); 559 return v.getStringValue().charAt(0) != 'n'; 560 } 561 562 566 572 public static boolean convertVisibility(Element e) { 573 Value v = getComputedStyle(e, SVGCSSEngine.VISIBILITY_INDEX); 574 return v.getStringValue().charAt(0) == 'v'; 575 } 576 577 581 public final static Composite TRANSPARENT = 582 AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0); 583 584 590 public static Composite convertOpacity(Element e) { 591 Value v = getComputedStyle(e, SVGCSSEngine.OPACITY_INDEX); 592 float f = v.getFloatValue(); 593 if (f <= 0f) { 594 return TRANSPARENT; 595 } else if (f >= 1f) { 596 return AlphaComposite.SrcOver; 597 } else { 598 return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, f); 599 } 600 } 601 602 606 614 public static boolean convertOverflow(Element e) { 615 Value v = getComputedStyle(e, SVGCSSEngine.OVERFLOW_INDEX); 616 String s = v.getStringValue(); 617 return (s.charAt(0) == 'h') || (s.charAt(0) == 's'); 618 } 619 620 627 public static float[] convertClip(Element e) { 628 Value v = getComputedStyle(e, SVGCSSEngine.CLIP_INDEX); 629 switch (v.getPrimitiveType()) { 630 case CSSPrimitiveValue.CSS_RECT: 631 float [] off = new float[4]; 632 off[0] = v.getTop().getFloatValue(); 633 off[1] = v.getRight().getFloatValue(); 634 off[2] = v.getBottom().getFloatValue(); 635 off[3] = v.getLeft().getFloatValue(); 636 return off; 637 case CSSPrimitiveValue.CSS_IDENT: 638 return null; default: 640 throw new Error (); } 642 } 643 644 648 658 public static Filter convertFilter(Element filteredElement, 659 GraphicsNode filteredNode, 660 BridgeContext ctx) { 661 Value v = getComputedStyle(filteredElement, SVGCSSEngine.FILTER_INDEX); 662 switch (v.getPrimitiveType()) { 663 case CSSPrimitiveValue.CSS_IDENT: 664 return null; 666 case CSSPrimitiveValue.CSS_URI: 667 String uri = v.getStringValue(); 668 Element filter = ctx.getReferencedElement(filteredElement, uri); 669 Bridge bridge = ctx.getBridge(filter); 670 if (bridge == null || !(bridge instanceof FilterBridge)) { 671 throw new BridgeException(filteredElement, 672 ERR_CSS_URI_BAD_TARGET, 673 new Object [] {uri}); 674 } 675 return ((FilterBridge)bridge).createFilter(ctx, 676 filter, 677 filteredElement, 678 filteredNode); 679 default: 680 throw new InternalError (); 682 } 683 } 684 685 689 698 public static ClipRable convertClipPath(Element clippedElement, 699 GraphicsNode clippedNode, 700 BridgeContext ctx) { 701 Value v = getComputedStyle(clippedElement, 702 SVGCSSEngine.CLIP_PATH_INDEX); 703 switch (v.getPrimitiveType()) { 704 case CSSPrimitiveValue.CSS_IDENT: 705 return null; 707 case CSSPrimitiveValue.CSS_URI: 708 String uri = v.getStringValue(); 709 Element cp = ctx.getReferencedElement(clippedElement, uri); 710 Bridge bridge = ctx.getBridge(cp); 711 if (bridge == null || !(bridge instanceof ClipBridge)) { 712 throw new BridgeException(clippedElement, 713 ERR_CSS_URI_BAD_TARGET, 714 new Object [] {uri}); 715 } 716 return ((ClipBridge)bridge).createClip(ctx, 717 cp, 718 clippedElement, 719 clippedNode); 720 default: 721 throw new InternalError (); 723 } 724 } 725 726 732 public static int convertClipRule(Element e) { 733 Value v = getComputedStyle(e, SVGCSSEngine.CLIP_RULE_INDEX); 734 return (v.getStringValue().charAt(0) == 'n') 735 ? GeneralPath.WIND_NON_ZERO 736 : GeneralPath.WIND_EVEN_ODD; 737 } 738 739 743 752 public static Mask convertMask(Element maskedElement, 753 GraphicsNode maskedNode, 754 BridgeContext ctx) { 755 Value v = getComputedStyle(maskedElement, SVGCSSEngine.MASK_INDEX); 756 switch (v.getPrimitiveType()) { 757 case CSSPrimitiveValue.CSS_IDENT: 758 return null; 760 case CSSPrimitiveValue.CSS_URI: 761 String uri = v.getStringValue(); 762 Element m = ctx.getReferencedElement(maskedElement, uri); 763 Bridge bridge = ctx.getBridge(m); 764 if (bridge == null || !(bridge instanceof MaskBridge)) { 765 throw new BridgeException(maskedElement, 766 ERR_CSS_URI_BAD_TARGET, 767 new Object [] {uri}); 768 } 769 return ((MaskBridge)bridge).createMask(ctx, 770 m, 771 maskedElement, 772 maskedNode); 773 default: 774 throw new InternalError (); 776 } 777 } 778 779 785 public static int convertFillRule(Element e) { 786 Value v = getComputedStyle(e, SVGCSSEngine.FILL_RULE_INDEX); 787 return (v.getStringValue().charAt(0) == 'n') 788 ? GeneralPath.WIND_NON_ZERO 789 : GeneralPath.WIND_EVEN_ODD; 790 } 791 792 796 803 public static Color convertLightingColor(Element e, BridgeContext ctx) { 804 Value v = getComputedStyle(e, SVGCSSEngine.LIGHTING_COLOR_INDEX); 805 if (v.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) { 806 return PaintServer.convertColor(v, 1); 807 } else { 808 return PaintServer.convertRGBICCColor 809 (e, v.item(0), (ICCColor)v.item(1), 1, ctx); 810 } 811 } 812 813 817 824 public static Color convertFloodColor(Element e, BridgeContext ctx) { 825 Value v = getComputedStyle(e, SVGCSSEngine.FLOOD_COLOR_INDEX); 826 Value o = getComputedStyle(e, SVGCSSEngine.FLOOD_OPACITY_INDEX); 827 float f = PaintServer.convertOpacity(o); 828 if (v.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) { 829 return PaintServer.convertColor(v, f); 830 } else { 831 return PaintServer.convertRGBICCColor 832 (e, v.item(0), (ICCColor)v.item(1), f, ctx); 833 } 834 } 835 836 840 848 public static Color convertStopColor(Element e, 849 float opacity, 850 BridgeContext ctx) { 851 Value v = getComputedStyle(e, SVGCSSEngine.STOP_COLOR_INDEX); 852 Value o = getComputedStyle(e, SVGCSSEngine.STOP_OPACITY_INDEX); 853 opacity *= PaintServer.convertOpacity(o); 854 if (v.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) { 855 return PaintServer.convertColor(v, opacity); 856 } else { 857 return PaintServer.convertRGBICCColor 858 (e, v.item(0), (ICCColor)v.item(1), opacity, ctx); 859 } 860 } 861 862 866 875 public static void computeStyleAndURIs(Element refElement, 876 Element localRefElement, 877 String uri) { 878 int idx = uri.indexOf('#'); 880 if (idx != -1) 881 uri = uri.substring(0,idx); 882 883 if (uri.length() != 0) 885 localRefElement.setAttributeNS(XML_NAMESPACE_URI, 886 "base", 887 uri); 888 889 CSSEngine engine = CSSUtilities.getCSSEngine(localRefElement); 890 CSSEngine refEngine = CSSUtilities.getCSSEngine(refElement); 891 892 engine.importCascadedStyleMaps(refElement, refEngine, localRefElement); 893 } 894 895 899 905 protected static int rule(CSSValue v) { 906 return (((CSSPrimitiveValue)v).getStringValue().charAt(0) == 'n') 907 ? GeneralPath.WIND_NON_ZERO 908 : GeneralPath.WIND_EVEN_ODD; 909 } 910 } 911 | Popular Tags |