Source Code Cross Referenced for SVGUtilities.java in  » Graphic-Library » batik » org » apache » batik » bridge » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Graphic Library » batik » org.apache.batik.bridge 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Licensed to the Apache Software Foundation (ASF) under one or more
0004:           contributor license agreements.  See the NOTICE file distributed with
0005:           this work for additional information regarding copyright ownership.
0006:           The ASF licenses this file to You under the Apache License, Version 2.0
0007:           (the "License"); you may not use this file except in compliance with
0008:           the License.  You may obtain a copy of the License at
0009:
0010:               http://www.apache.org/licenses/LICENSE-2.0
0011:
0012:           Unless required by applicable law or agreed to in writing, software
0013:           distributed under the License is distributed on an "AS IS" BASIS,
0014:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015:           See the License for the specific language governing permissions and
0016:           limitations under the License.
0017:
0018:         */
0019:        package org.apache.batik.bridge;
0020:
0021:        import java.awt.geom.AffineTransform;
0022:        import java.awt.geom.Point2D;
0023:        import java.awt.geom.Rectangle2D;
0024:        import java.io.IOException;
0025:        import java.util.Iterator;
0026:        import java.util.LinkedList;
0027:        import java.util.List;
0028:        import java.util.StringTokenizer;
0029:
0030:        import org.apache.batik.css.engine.CSSEngine;
0031:        import org.apache.batik.dom.AbstractNode;
0032:        import org.apache.batik.dom.util.XLinkSupport;
0033:        import org.apache.batik.dom.util.XMLSupport;
0034:        import org.apache.batik.gvt.GraphicsNode;
0035:        import org.apache.batik.parser.AWTTransformProducer;
0036:        import org.apache.batik.parser.ClockHandler;
0037:        import org.apache.batik.parser.ClockParser;
0038:        import org.apache.batik.parser.ParseException;
0039:        import org.apache.batik.util.ParsedURL;
0040:        import org.apache.batik.util.SVG12Constants;
0041:        import org.apache.batik.util.SVGConstants;
0042:        import org.w3c.dom.Element;
0043:        import org.w3c.dom.Node;
0044:        import org.w3c.dom.svg.SVGDocument;
0045:        import org.w3c.dom.svg.SVGElement;
0046:        import org.w3c.dom.svg.SVGLangSpace;
0047:        import org.w3c.dom.svg.SVGNumberList;
0048:
0049:        /**
0050:         * A collection of utility methods for SVG.
0051:         *
0052:         * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
0053:         * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
0054:         * @version $Id: SVGUtilities.java 504084 2007-02-06 11:24:46Z dvholten $
0055:         */
0056:        public abstract class SVGUtilities implements  SVGConstants,
0057:                ErrorConstants {
0058:
0059:            /**
0060:             * No instance of this class is required.
0061:             */
0062:            protected SVGUtilities() {
0063:            }
0064:
0065:            ////////////////////////////////////////////////////////////////////////
0066:            // common methods
0067:            ////////////////////////////////////////////////////////////////////////
0068:
0069:            /**
0070:             * Returns the logical parent element of the given element.
0071:             * The parent element of a used element is the &lt;use> element
0072:             * which reference it.
0073:             */
0074:            public static Element getParentElement(Element elt) {
0075:                Node n = CSSEngine.getCSSParentNode(elt);
0076:                while (n != null && n.getNodeType() != Node.ELEMENT_NODE) {
0077:                    n = CSSEngine.getCSSParentNode(n);
0078:                }
0079:                return (Element) n;
0080:            }
0081:
0082:            /**
0083:             * Converts an SVGNumberList into a float array.
0084:             * @param l the list to convert
0085:             */
0086:            public static float[] convertSVGNumberList(SVGNumberList l) {
0087:                int n = l.getNumberOfItems();
0088:                if (n == 0) {
0089:                    return null;
0090:                }
0091:                float[] fl = new float[n];
0092:                for (int i = 0; i < n; i++) {
0093:                    fl[i] = l.getItem(i).getValue();
0094:                }
0095:                return fl;
0096:            }
0097:
0098:            /**
0099:             * Converts a string into a float.
0100:             * @param s the float representation to convert
0101:             */
0102:            public static float convertSVGNumber(String s) {
0103:                return Float.parseFloat(s);
0104:            }
0105:
0106:            /**
0107:             * Converts a string into an integer.
0108:             * @param s the integer representation to convert
0109:             */
0110:            public static int convertSVGInteger(String s) {
0111:                return Integer.parseInt(s);
0112:            }
0113:
0114:            /**
0115:             * Converts the specified ratio to float number.
0116:             * @param v the ratio value to convert
0117:             * @exception NumberFormatException if the ratio is not a valid
0118:             * number or percentage
0119:             */
0120:            public static float convertRatio(String v) {
0121:                float d = 1;
0122:                if (v.endsWith("%")) {
0123:                    v = v.substring(0, v.length() - 1);
0124:                    d = 100;
0125:                }
0126:                float r = Float.parseFloat(v) / d;
0127:                if (r < 0) {
0128:                    r = 0;
0129:                } else if (r > 1) {
0130:                    r = 1;
0131:                }
0132:                return r;
0133:            }
0134:
0135:            /**
0136:             * Returns the content of the 'desc' child of the given element.
0137:             */
0138:            public static String getDescription(SVGElement elt) {
0139:                String result = "";
0140:                boolean preserve = false;
0141:                Node n = elt.getFirstChild();
0142:                if (n != null && n.getNodeType() == Node.ELEMENT_NODE) {
0143:                    String name = (n.getPrefix() == null) ? n.getNodeName() : n
0144:                            .getLocalName();
0145:                    if (name.equals(SVG_DESC_TAG)) {
0146:                        preserve = ((SVGLangSpace) n).getXMLspace().equals(
0147:                                SVG_PRESERVE_VALUE);
0148:                        for (n = n.getFirstChild(); n != null; n = n
0149:                                .getNextSibling()) {
0150:                            if (n.getNodeType() == Node.TEXT_NODE) {
0151:                                result += n.getNodeValue();
0152:                            }
0153:                        }
0154:                    }
0155:                }
0156:                return (preserve) ? XMLSupport.preserveXMLSpace(result)
0157:                        : XMLSupport.defaultXMLSpace(result);
0158:            }
0159:
0160:            /**
0161:             * Tests whether or not the given element match a specified user agent.
0162:             *
0163:             * @param elt the element to check
0164:             * @param ua the user agent
0165:             */
0166:            public static boolean matchUserAgent(Element elt, UserAgent ua) {
0167:                test: if (elt.hasAttributeNS(null,
0168:                        SVG_SYSTEM_LANGUAGE_ATTRIBUTE)) {
0169:                    // Tests the system languages.
0170:                    String sl = elt.getAttributeNS(null,
0171:                            SVG_SYSTEM_LANGUAGE_ATTRIBUTE);
0172:                    if (sl.length() == 0) // SVG spec says empty returns false
0173:                        return false;
0174:                    StringTokenizer st = new StringTokenizer(sl, ", ");
0175:                    while (st.hasMoreTokens()) {
0176:                        String s = st.nextToken();
0177:                        if (matchUserLanguage(s, ua.getLanguages())) {
0178:                            break test;
0179:                        }
0180:                    }
0181:                    return false;
0182:                }
0183:                if (elt.hasAttributeNS(null, SVG_REQUIRED_FEATURES_ATTRIBUTE)) {
0184:                    // Tests the system features.
0185:                    String rf = elt.getAttributeNS(null,
0186:                            SVG_REQUIRED_FEATURES_ATTRIBUTE);
0187:                    if (rf.length() == 0) // SVG spec says empty returns false
0188:                        return false;
0189:                    StringTokenizer st = new StringTokenizer(rf, " ");
0190:                    while (st.hasMoreTokens()) {
0191:                        String s = st.nextToken();
0192:                        if (!ua.hasFeature(s)) {
0193:                            return false;
0194:                        }
0195:                    }
0196:                }
0197:                if (elt.hasAttributeNS(null, SVG_REQUIRED_EXTENSIONS_ATTRIBUTE)) {
0198:                    // Tests the system features.
0199:                    String re = elt.getAttributeNS(null,
0200:                            SVG_REQUIRED_EXTENSIONS_ATTRIBUTE);
0201:                    if (re.length() == 0) // SVG spec says empty returns false
0202:                        return false;
0203:                    StringTokenizer st = new StringTokenizer(re, " ");
0204:                    while (st.hasMoreTokens()) {
0205:                        String s = st.nextToken();
0206:                        if (!ua.supportExtension(s)) {
0207:                            return false;
0208:                        }
0209:                    }
0210:                }
0211:                return true;
0212:            }
0213:
0214:            /**
0215:             * Tests whether or not the specified language specification matches
0216:             * the user preferences.
0217:             *
0218:             * @param s the langage to check
0219:             * @param userLanguages the user langages
0220:             */
0221:            protected static boolean matchUserLanguage(String s,
0222:                    String userLanguages) {
0223:                StringTokenizer st = new StringTokenizer(userLanguages, ", ");
0224:                while (st.hasMoreTokens()) {
0225:                    String t = st.nextToken();
0226:                    if (s.startsWith(t)) {
0227:                        if (s.length() > t.length()) {
0228:                            return (s.charAt(t.length()) == '-');
0229:                        }
0230:                        return true;
0231:                    }
0232:                }
0233:                return false;
0234:            }
0235:
0236:            /**
0237:             * Returns the value of the specified attribute specified on the
0238:             * specified element or one of its ancestor. Ancestors are found
0239:             * using the xlink:href attribute.
0240:             *
0241:             * @param element the element to start with
0242:             * @param namespaceURI the namespace URI of the attribute to return
0243:             * @param attrName the name of the attribute to search
0244:             * @param ctx the bridge context
0245:             * @return the value of the attribute or an empty string if not defined
0246:             */
0247:            public static String getChainableAttributeNS(Element element,
0248:                    String namespaceURI, String attrName, BridgeContext ctx) {
0249:
0250:                DocumentLoader loader = ctx.getDocumentLoader();
0251:                Element e = element;
0252:                List refs = new LinkedList();
0253:                for (;;) {
0254:                    String v = e.getAttributeNS(namespaceURI, attrName);
0255:                    if (v.length() > 0) { // exit if attribute defined
0256:                        return v;
0257:                    }
0258:                    String uriStr = XLinkSupport.getXLinkHref(e);
0259:                    if (uriStr.length() == 0) { // exit if no more xlink:href
0260:                        return "";
0261:                    }
0262:                    String baseURI = ((AbstractNode) e).getBaseURI();
0263:                    ParsedURL purl = new ParsedURL(baseURI, uriStr);
0264:
0265:                    Iterator iter = refs.iterator();
0266:                    while (iter.hasNext()) {
0267:                        if (purl.equals(iter.next()))
0268:                            throw new BridgeException(ctx, e,
0269:                                    ERR_XLINK_HREF_CIRCULAR_DEPENDENCIES,
0270:                                    new Object[] { uriStr });
0271:                    }
0272:
0273:                    try {
0274:                        SVGDocument svgDoc = (SVGDocument) e.getOwnerDocument();
0275:                        URIResolver resolver = ctx.createURIResolver(svgDoc,
0276:                                loader);
0277:                        e = resolver.getElement(purl.toString(), e);
0278:                        refs.add(purl);
0279:                    } catch (IOException ioEx) {
0280:                        throw new BridgeException(ctx, e, ioEx, ERR_URI_IO,
0281:                                new Object[] { uriStr });
0282:                    } catch (SecurityException secEx) {
0283:                        throw new BridgeException(ctx, e, secEx,
0284:                                ERR_URI_UNSECURE, new Object[] { uriStr });
0285:                    }
0286:                }
0287:            }
0288:
0289:            /////////////////////////////////////////////////////////////////////////
0290:            // <linearGradient> and <radialGradient>
0291:            /////////////////////////////////////////////////////////////////////////
0292:
0293:            /**
0294:             * Returns a Point2D in user units according to the specified parameters.
0295:             *
0296:             * @param xStr the x coordinate
0297:             * @param xAttr the name of the attribute that represents the x coordinate
0298:             * @param yStr the y coordinate
0299:             * @param yAttr the name of the attribute that represents the y coordinate
0300:             * @param unitsType the coordinate system (OBJECT_BOUNDING_BOX |
0301:             * USER_SPACE_ON_USE)
0302:             * @param uctx the unit processor context
0303:             */
0304:            public static Point2D convertPoint(String xStr, String xAttr,
0305:                    String yStr, String yAttr, short unitsType,
0306:                    UnitProcessor.Context uctx) {
0307:                float x, y;
0308:                switch (unitsType) {
0309:                case OBJECT_BOUNDING_BOX:
0310:                    x = UnitProcessor
0311:                            .svgHorizontalCoordinateToObjectBoundingBox(xStr,
0312:                                    xAttr, uctx);
0313:                    y = UnitProcessor.svgVerticalCoordinateToObjectBoundingBox(
0314:                            yStr, yAttr, uctx);
0315:                    break;
0316:                case USER_SPACE_ON_USE:
0317:                    x = UnitProcessor.svgHorizontalCoordinateToUserSpace(xStr,
0318:                            xAttr, uctx);
0319:                    y = UnitProcessor.svgVerticalCoordinateToUserSpace(yStr,
0320:                            yAttr, uctx);
0321:                    break;
0322:                default:
0323:                    throw new IllegalArgumentException("Invalid unit type");
0324:                }
0325:                return new Point2D.Float(x, y);
0326:            }
0327:
0328:            /**
0329:             * Returns a float in user units according to the specified parameters.
0330:             *
0331:             * @param length the length
0332:             * @param attr the name of the attribute that represents the length
0333:             * @param unitsType the coordinate system (OBJECT_BOUNDING_BOX |
0334:             * USER_SPACE_ON_USE)
0335:             * @param uctx the unit processor context
0336:             */
0337:            public static float convertLength(String length, String attr,
0338:                    short unitsType, UnitProcessor.Context uctx) {
0339:                switch (unitsType) {
0340:                case OBJECT_BOUNDING_BOX:
0341:                    return UnitProcessor.svgOtherLengthToObjectBoundingBox(
0342:                            length, attr, uctx);
0343:                case USER_SPACE_ON_USE:
0344:                    return UnitProcessor.svgOtherLengthToUserSpace(length,
0345:                            attr, uctx);
0346:                default:
0347:                    throw new IllegalArgumentException("Invalid unit type");
0348:                }
0349:            }
0350:
0351:            /////////////////////////////////////////////////////////////////////////
0352:            // <mask> region
0353:            /////////////////////////////////////////////////////////////////////////
0354:
0355:            /**
0356:             * Returns the mask region according to the x, y, width, height,
0357:             * and maskUnits attributes.
0358:             *
0359:             * @param maskElement the mask element that defines the various attributes
0360:             * @param maskedElement the element referencing the mask
0361:             * @param maskedNode the graphics node to mask (objectBoundingBox)
0362:             * @param ctx the bridge context
0363:             */
0364:            public static Rectangle2D convertMaskRegion(Element maskElement,
0365:                    Element maskedElement, GraphicsNode maskedNode,
0366:                    BridgeContext ctx) {
0367:
0368:                // 'x' attribute - default is -10%
0369:                String xStr = maskElement.getAttributeNS(null, SVG_X_ATTRIBUTE);
0370:                if (xStr.length() == 0) {
0371:                    xStr = SVG_MASK_X_DEFAULT_VALUE;
0372:                }
0373:                // 'y' attribute - default is -10%
0374:                String yStr = maskElement.getAttributeNS(null, SVG_Y_ATTRIBUTE);
0375:                if (yStr.length() == 0) {
0376:                    yStr = SVG_MASK_Y_DEFAULT_VALUE;
0377:                }
0378:                // 'width' attribute - default is 120%
0379:                String wStr = maskElement.getAttributeNS(null,
0380:                        SVG_WIDTH_ATTRIBUTE);
0381:                if (wStr.length() == 0) {
0382:                    wStr = SVG_MASK_WIDTH_DEFAULT_VALUE;
0383:                }
0384:                // 'height' attribute - default is 120%
0385:                String hStr = maskElement.getAttributeNS(null,
0386:                        SVG_HEIGHT_ATTRIBUTE);
0387:                if (hStr.length() == 0) {
0388:                    hStr = SVG_MASK_HEIGHT_DEFAULT_VALUE;
0389:                }
0390:                // 'maskUnits' attribute - default is 'objectBoundingBox'
0391:                short unitsType;
0392:                String units = maskElement.getAttributeNS(null,
0393:                        SVG_MASK_UNITS_ATTRIBUTE);
0394:                if (units.length() == 0) {
0395:                    unitsType = OBJECT_BOUNDING_BOX;
0396:                } else {
0397:                    unitsType = parseCoordinateSystem(maskElement,
0398:                            SVG_MASK_UNITS_ATTRIBUTE, units, ctx);
0399:                }
0400:
0401:                // resolve units in the (referenced) maskedElement's coordinate system
0402:                UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
0403:                        maskedElement);
0404:
0405:                return convertRegion(xStr, yStr, wStr, hStr, unitsType,
0406:                        maskedNode, uctx);
0407:            }
0408:
0409:            /////////////////////////////////////////////////////////////////////////
0410:            // <pattern> region
0411:            /////////////////////////////////////////////////////////////////////////
0412:
0413:            /**
0414:             * Returns the pattern region according to the x, y, width, height,
0415:             * and patternUnits attributes.
0416:             *
0417:             * @param patternElement the pattern element that defines the attributes
0418:             * @param paintedElement the element referencing the pattern
0419:             * @param paintedNode the graphics node to paint (objectBoundingBox)
0420:             * @param ctx the bridge context
0421:             */
0422:            public static Rectangle2D convertPatternRegion(
0423:                    Element patternElement, Element paintedElement,
0424:                    GraphicsNode paintedNode, BridgeContext ctx) {
0425:
0426:                // 'x' attribute - default is 0%
0427:                String xStr = getChainableAttributeNS(patternElement, null,
0428:                        SVG_X_ATTRIBUTE, ctx);
0429:                if (xStr.length() == 0) {
0430:                    xStr = SVG_PATTERN_X_DEFAULT_VALUE;
0431:                }
0432:                // 'y' attribute - default is 0%
0433:                String yStr = getChainableAttributeNS(patternElement, null,
0434:                        SVG_Y_ATTRIBUTE, ctx);
0435:                if (yStr.length() == 0) {
0436:                    yStr = SVG_PATTERN_Y_DEFAULT_VALUE;
0437:                }
0438:                // 'width' attribute - required
0439:                String wStr = getChainableAttributeNS(patternElement, null,
0440:                        SVG_WIDTH_ATTRIBUTE, ctx);
0441:                if (wStr.length() == 0) {
0442:                    throw new BridgeException(ctx, patternElement,
0443:                            ERR_ATTRIBUTE_MISSING,
0444:                            new Object[] { SVG_WIDTH_ATTRIBUTE });
0445:                }
0446:                // 'height' attribute - required
0447:                String hStr = getChainableAttributeNS(patternElement, null,
0448:                        SVG_HEIGHT_ATTRIBUTE, ctx);
0449:                if (hStr.length() == 0) {
0450:                    throw new BridgeException(ctx, patternElement,
0451:                            ERR_ATTRIBUTE_MISSING,
0452:                            new Object[] { SVG_HEIGHT_ATTRIBUTE });
0453:                }
0454:                // 'patternUnits' attribute - default is 'objectBoundingBox'
0455:                short unitsType;
0456:                String units = getChainableAttributeNS(patternElement, null,
0457:                        SVG_PATTERN_UNITS_ATTRIBUTE, ctx);
0458:                if (units.length() == 0) {
0459:                    unitsType = OBJECT_BOUNDING_BOX;
0460:                } else {
0461:                    unitsType = parseCoordinateSystem(patternElement,
0462:                            SVG_PATTERN_UNITS_ATTRIBUTE, units, ctx);
0463:                }
0464:
0465:                // resolve units in the (referenced) paintedElement's coordinate system
0466:                UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
0467:                        paintedElement);
0468:
0469:                return convertRegion(xStr, yStr, wStr, hStr, unitsType,
0470:                        paintedNode, uctx);
0471:            }
0472:
0473:            /////////////////////////////////////////////////////////////////////////
0474:            // <filter> and filter primitive
0475:            /////////////////////////////////////////////////////////////////////////
0476:
0477:            /**
0478:             * Returns an array of 2 float numbers that describes the filter
0479:             * resolution of the specified filter element.
0480:             *
0481:             * @param filterElement the filter element
0482:             * @param ctx the bridge context
0483:             */
0484:            public static float[] convertFilterRes(Element filterElement,
0485:                    BridgeContext ctx) {
0486:
0487:                float[] filterRes = new float[2];
0488:                String s = getChainableAttributeNS(filterElement, null,
0489:                        SVG_FILTER_RES_ATTRIBUTE, ctx);
0490:                Float[] vals = convertSVGNumberOptionalNumber(filterElement,
0491:                        SVG_FILTER_RES_ATTRIBUTE, s, ctx);
0492:
0493:                if (filterRes[0] < 0 || filterRes[1] < 0) {
0494:                    throw new BridgeException(ctx, filterElement,
0495:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
0496:                                    SVG_FILTER_RES_ATTRIBUTE, s });
0497:                }
0498:
0499:                if (vals[0] == null)
0500:                    filterRes[0] = -1;
0501:                else {
0502:                    filterRes[0] = vals[0].floatValue();
0503:                    if (filterRes[0] < 0)
0504:                        throw new BridgeException(ctx, filterElement,
0505:                                ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
0506:                                        SVG_FILTER_RES_ATTRIBUTE, s });
0507:                }
0508:
0509:                if (vals[1] == null)
0510:                    filterRes[1] = filterRes[0];
0511:                else {
0512:                    filterRes[1] = vals[1].floatValue();
0513:                    if (filterRes[1] < 0)
0514:                        throw new BridgeException(ctx, filterElement,
0515:                                ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
0516:                                        SVG_FILTER_RES_ATTRIBUTE, s });
0517:                }
0518:                return filterRes;
0519:            }
0520:
0521:            /**
0522:             * This function parses attrValue for a number followed by an optional
0523:             * second Number. It always returns an array of two Floats.  If either
0524:             * or both values are not provided the entries are set to null
0525:             */
0526:            public static Float[] convertSVGNumberOptionalNumber(Element elem,
0527:                    String attrName, String attrValue, BridgeContext ctx) {
0528:
0529:                Float[] ret = new Float[2];
0530:                if (attrValue.length() == 0)
0531:                    return ret;
0532:
0533:                try {
0534:                    StringTokenizer tokens = new StringTokenizer(attrValue, " ");
0535:                    ret[0] = new Float(Float.parseFloat(tokens.nextToken()));
0536:                    if (tokens.hasMoreTokens()) {
0537:                        ret[1] = new Float(Float.parseFloat(tokens.nextToken()));
0538:                    }
0539:
0540:                    if (tokens.hasMoreTokens()) {
0541:                        throw new BridgeException(ctx, elem,
0542:                                ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
0543:                                        attrName, attrValue });
0544:                    }
0545:                } catch (NumberFormatException nfEx) {
0546:                    throw new BridgeException(ctx, elem, nfEx,
0547:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
0548:                                    attrName, attrValue, nfEx });
0549:                }
0550:                return ret;
0551:            }
0552:
0553:            /**
0554:             * Returns the filter region according to the x, y, width, height,
0555:             * dx, dy, dw, dh and filterUnits attributes.
0556:             *
0557:             * @param filterElement the filter element that defines the attributes
0558:             * @param filteredElement the element referencing the filter
0559:             * @param filteredNode the graphics node to filter (objectBoundingBox)
0560:             * @param ctx the bridge context
0561:             */
0562:            public static Rectangle2D convertFilterChainRegion(
0563:                    Element filterElement, Element filteredElement,
0564:                    GraphicsNode filteredNode, BridgeContext ctx) {
0565:
0566:                // 'x' attribute - default is -10%
0567:                String xStr = getChainableAttributeNS(filterElement, null,
0568:                        SVG_X_ATTRIBUTE, ctx);
0569:                if (xStr.length() == 0) {
0570:                    xStr = SVG_FILTER_X_DEFAULT_VALUE;
0571:                }
0572:                // 'y' attribute - default is -10%
0573:                String yStr = getChainableAttributeNS(filterElement, null,
0574:                        SVG_Y_ATTRIBUTE, ctx);
0575:                if (yStr.length() == 0) {
0576:                    yStr = SVG_FILTER_Y_DEFAULT_VALUE;
0577:                }
0578:                // 'width' attribute - default is 120%
0579:                String wStr = getChainableAttributeNS(filterElement, null,
0580:                        SVG_WIDTH_ATTRIBUTE, ctx);
0581:                if (wStr.length() == 0) {
0582:                    wStr = SVG_FILTER_WIDTH_DEFAULT_VALUE;
0583:                }
0584:                // 'height' attribute - default is 120%
0585:                String hStr = getChainableAttributeNS(filterElement, null,
0586:                        SVG_HEIGHT_ATTRIBUTE, ctx);
0587:                if (hStr.length() == 0) {
0588:                    hStr = SVG_FILTER_HEIGHT_DEFAULT_VALUE;
0589:                }
0590:                // 'filterUnits' attribute - default is 'objectBoundingBox'
0591:                short unitsType;
0592:                String units = getChainableAttributeNS(filterElement, null,
0593:                        SVG_FILTER_UNITS_ATTRIBUTE, ctx);
0594:                if (units.length() == 0) {
0595:                    unitsType = OBJECT_BOUNDING_BOX;
0596:                } else {
0597:                    unitsType = parseCoordinateSystem(filterElement,
0598:                            SVG_FILTER_UNITS_ATTRIBUTE, units, ctx);
0599:                }
0600:
0601:                // resolve units in the (referenced) filteredElement's
0602:                // coordinate system
0603:                UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
0604:                        filteredElement);
0605:
0606:                Rectangle2D region = convertRegion(xStr, yStr, wStr, hStr,
0607:                        unitsType, filteredNode, uctx);
0608:                //
0609:                // Account for region padding
0610:                //
0611:                units = getChainableAttributeNS(filterElement, null,
0612:                        SVG12Constants.SVG_FILTER_MARGINS_UNITS_ATTRIBUTE, ctx);
0613:                if (units.length() == 0) {
0614:                    // Default to user space on use for margins, not objectBoundingBox
0615:                    unitsType = USER_SPACE_ON_USE;
0616:                } else {
0617:                    unitsType = parseCoordinateSystem(filterElement,
0618:                            SVG12Constants.SVG_FILTER_MARGINS_UNITS_ATTRIBUTE,
0619:                            units, ctx);
0620:                }
0621:
0622:                // 'batik:dx' attribute - default is 0
0623:                String dxStr = filterElement.getAttributeNS(null,
0624:                        SVG12Constants.SVG_MX_ATRIBUTE);
0625:                if (dxStr.length() == 0) {
0626:                    dxStr = SVG12Constants.SVG_FILTER_MX_DEFAULT_VALUE;
0627:                }
0628:                // 'batik:dy' attribute - default is 0
0629:                String dyStr = filterElement.getAttributeNS(null,
0630:                        SVG12Constants.SVG_MY_ATRIBUTE);
0631:                if (dyStr.length() == 0) {
0632:                    dyStr = SVG12Constants.SVG_FILTER_MY_DEFAULT_VALUE;
0633:                }
0634:                // 'batik:dw' attribute - default is 0
0635:                String dwStr = filterElement.getAttributeNS(null,
0636:                        SVG12Constants.SVG_MW_ATRIBUTE);
0637:                if (dwStr.length() == 0) {
0638:                    dwStr = SVG12Constants.SVG_FILTER_MW_DEFAULT_VALUE;
0639:                }
0640:                // 'batik:dh' attribute - default is 0
0641:                String dhStr = filterElement.getAttributeNS(null,
0642:                        SVG12Constants.SVG_MH_ATRIBUTE);
0643:                if (dhStr.length() == 0) {
0644:                    dhStr = SVG12Constants.SVG_FILTER_MH_DEFAULT_VALUE;
0645:                }
0646:
0647:                return extendRegion(dxStr, dyStr, dwStr, dhStr, unitsType,
0648:                        filteredNode, region, uctx);
0649:            }
0650:
0651:            /**
0652:             * Returns a rectangle that represents the region extended by the
0653:             * specified differential coordinates.
0654:             *
0655:             * @param dxStr the differential x coordinate of the region
0656:             * @param dyStr the differential y coordinate of the region
0657:             * @param dwStr the differential width of the region
0658:             * @param dhStr the differential height of the region
0659:             * @param unitsType specifies whether the values are in userSpaceOnUse
0660:             *        or objectBoundingBox space
0661:             * @param region the region to extend
0662:             * @param uctx the unit processor context (needed for userSpaceOnUse)
0663:             */
0664:            protected static Rectangle2D extendRegion(String dxStr,
0665:                    String dyStr, String dwStr, String dhStr, short unitsType,
0666:                    GraphicsNode filteredNode, Rectangle2D region,
0667:                    UnitProcessor.Context uctx) {
0668:
0669:                float dx, dy, dw, dh;
0670:                switch (unitsType) {
0671:                case USER_SPACE_ON_USE:
0672:                    dx = UnitProcessor.svgHorizontalCoordinateToUserSpace(
0673:                            dxStr, SVG12Constants.SVG_MX_ATRIBUTE, uctx);
0674:                    dy = UnitProcessor.svgVerticalCoordinateToUserSpace(dyStr,
0675:                            SVG12Constants.SVG_MY_ATRIBUTE, uctx);
0676:                    dw = UnitProcessor.svgHorizontalCoordinateToUserSpace(
0677:                            dwStr, SVG12Constants.SVG_MW_ATRIBUTE, uctx);
0678:                    dh = UnitProcessor.svgVerticalCoordinateToUserSpace(dhStr,
0679:                            SVG12Constants.SVG_MH_ATRIBUTE, uctx);
0680:                    break;
0681:                case OBJECT_BOUNDING_BOX:
0682:                    Rectangle2D bounds = filteredNode.getGeometryBounds();
0683:                    if (bounds == null) {
0684:                        dx = dy = dw = dh = 0;
0685:                    } else {
0686:                        dx = UnitProcessor
0687:                                .svgHorizontalCoordinateToObjectBoundingBox(
0688:                                        dxStr, SVG12Constants.SVG_MX_ATRIBUTE,
0689:                                        uctx);
0690:                        dx *= bounds.getWidth();
0691:
0692:                        dy = UnitProcessor
0693:                                .svgVerticalCoordinateToObjectBoundingBox(
0694:                                        dyStr, SVG12Constants.SVG_MY_ATRIBUTE,
0695:                                        uctx);
0696:                        dy *= bounds.getHeight();
0697:
0698:                        dw = UnitProcessor
0699:                                .svgHorizontalCoordinateToObjectBoundingBox(
0700:                                        dwStr, SVG12Constants.SVG_MW_ATRIBUTE,
0701:                                        uctx);
0702:                        dw *= bounds.getWidth();
0703:
0704:                        dh = UnitProcessor
0705:                                .svgVerticalCoordinateToObjectBoundingBox(
0706:                                        dhStr, SVG12Constants.SVG_MH_ATRIBUTE,
0707:                                        uctx);
0708:                        dh *= bounds.getHeight();
0709:                    }
0710:                    break;
0711:                default:
0712:                    throw new IllegalArgumentException("Invalid unit type");
0713:                }
0714:
0715:                region.setRect(region.getX() + dx, region.getY() + dy, region
0716:                        .getWidth()
0717:                        + dw, region.getHeight() + dh);
0718:
0719:                return region;
0720:            }
0721:
0722:            public static Rectangle2D getBaseFilterPrimitiveRegion(
0723:                    Element filterPrimitiveElement, Element filteredElement,
0724:                    GraphicsNode filteredNode, Rectangle2D defaultRegion,
0725:                    BridgeContext ctx) {
0726:                String s;
0727:
0728:                // resolve units in the (referenced) filteredElement's
0729:                // coordinate system
0730:                UnitProcessor.Context uctx;
0731:                uctx = UnitProcessor.createContext(ctx, filteredElement);
0732:
0733:                // 'x' attribute - default is defaultRegion.getX()
0734:                double x = defaultRegion.getX();
0735:                s = filterPrimitiveElement
0736:                        .getAttributeNS(null, SVG_X_ATTRIBUTE);
0737:                if (s.length() != 0) {
0738:                    x = UnitProcessor.svgHorizontalCoordinateToUserSpace(s,
0739:                            SVG_X_ATTRIBUTE, uctx);
0740:                }
0741:
0742:                // 'y' attribute - default is defaultRegion.getY()
0743:                double y = defaultRegion.getY();
0744:                s = filterPrimitiveElement
0745:                        .getAttributeNS(null, SVG_Y_ATTRIBUTE);
0746:                if (s.length() != 0) {
0747:                    y = UnitProcessor.svgVerticalCoordinateToUserSpace(s,
0748:                            SVG_Y_ATTRIBUTE, uctx);
0749:                }
0750:
0751:                // 'width' attribute - default is defaultRegion.getWidth()
0752:                double w = defaultRegion.getWidth();
0753:                s = filterPrimitiveElement.getAttributeNS(null,
0754:                        SVG_WIDTH_ATTRIBUTE);
0755:                if (s.length() != 0) {
0756:                    w = UnitProcessor.svgHorizontalLengthToUserSpace(s,
0757:                            SVG_WIDTH_ATTRIBUTE, uctx);
0758:                }
0759:
0760:                // 'height' attribute - default is defaultRegion.getHeight()
0761:                double h = defaultRegion.getHeight();
0762:                s = filterPrimitiveElement.getAttributeNS(null,
0763:                        SVG_HEIGHT_ATTRIBUTE);
0764:                if (s.length() != 0) {
0765:                    h = UnitProcessor.svgVerticalLengthToUserSpace(s,
0766:                            SVG_HEIGHT_ATTRIBUTE, uctx);
0767:                }
0768:
0769:                // NOTE: it may be that dx/dy/dw/dh should be applied here
0770:                //       but since this is mostly aimed at feImage I am
0771:                //       unsure that it is really needed.
0772:                return new Rectangle2D.Double(x, y, w, h);
0773:            }
0774:
0775:            /**
0776:             * Returns the filter primitive region according to the x, y,
0777:             * width, height, and filterUnits attributes. Processing the
0778:             * element as the top one in the filter chain.
0779:             *
0780:             * @param filterPrimitiveElement the filter primitive element
0781:             * @param filteredElement the element referencing the filter
0782:             * @param filteredNode the graphics node to use (objectBoundingBox)
0783:             * @param defaultRegion the default region to filter
0784:             * @param filterRegion the filter chain region
0785:             * @param ctx the bridge context
0786:             */
0787:            public static Rectangle2D convertFilterPrimitiveRegion(
0788:                    Element filterPrimitiveElement, Element filteredElement,
0789:                    GraphicsNode filteredNode, Rectangle2D defaultRegion,
0790:                    Rectangle2D filterRegion, BridgeContext ctx) {
0791:
0792:                // 'primitiveUnits' - default is userSpaceOnUse
0793:                Node parentNode = filterPrimitiveElement.getParentNode();
0794:                String units = "";
0795:                if ((parentNode != null)
0796:                        && (parentNode.getNodeType() == Node.ELEMENT_NODE)) {
0797:                    Element parent = (Element) parentNode;
0798:                    units = getChainableAttributeNS(parent, null,
0799:                            SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx);
0800:                }
0801:                short unitsType;
0802:                if (units.length() == 0) {
0803:                    unitsType = USER_SPACE_ON_USE;
0804:                } else {
0805:                    unitsType = parseCoordinateSystem(filterPrimitiveElement,
0806:                            SVG_FILTER_UNITS_ATTRIBUTE, units, ctx);
0807:                }
0808:
0809:                // 'x' attribute - default is defaultRegion.getX()
0810:                String xStr = filterPrimitiveElement.getAttributeNS(null,
0811:                        SVG_X_ATTRIBUTE);
0812:
0813:                // 'y' attribute - default is defaultRegion.getY()
0814:                String yStr = filterPrimitiveElement.getAttributeNS(null,
0815:                        SVG_Y_ATTRIBUTE);
0816:
0817:                // 'width' attribute - default is defaultRegion.getWidth()
0818:                String wStr = filterPrimitiveElement.getAttributeNS(null,
0819:                        SVG_WIDTH_ATTRIBUTE);
0820:
0821:                // 'height' attribute - default is defaultRegion.getHeight()
0822:                String hStr = filterPrimitiveElement.getAttributeNS(null,
0823:                        SVG_HEIGHT_ATTRIBUTE);
0824:
0825:                double x = defaultRegion.getX();
0826:                double y = defaultRegion.getY();
0827:                double w = defaultRegion.getWidth();
0828:                double h = defaultRegion.getHeight();
0829:
0830:                // resolve units in the (referenced) filteredElement's coordinate system
0831:                UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
0832:                        filteredElement);
0833:
0834:                switch (unitsType) {
0835:                case OBJECT_BOUNDING_BOX:
0836:                    Rectangle2D bounds = filteredNode.getGeometryBounds();
0837:                    if (bounds != null) {
0838:                        if (xStr.length() != 0) {
0839:                            x = UnitProcessor
0840:                                    .svgHorizontalCoordinateToObjectBoundingBox(
0841:                                            xStr, SVG_X_ATTRIBUTE, uctx);
0842:                            x = bounds.getX() + x * bounds.getWidth();
0843:                        }
0844:                        if (yStr.length() != 0) {
0845:                            y = UnitProcessor
0846:                                    .svgVerticalCoordinateToObjectBoundingBox(
0847:                                            yStr, SVG_Y_ATTRIBUTE, uctx);
0848:                            y = bounds.getY() + y * bounds.getHeight();
0849:                        }
0850:                        if (wStr.length() != 0) {
0851:                            w = UnitProcessor
0852:                                    .svgHorizontalLengthToObjectBoundingBox(
0853:                                            wStr, SVG_WIDTH_ATTRIBUTE, uctx);
0854:                            w *= bounds.getWidth();
0855:                        }
0856:                        if (hStr.length() != 0) {
0857:                            h = UnitProcessor
0858:                                    .svgVerticalLengthToObjectBoundingBox(hStr,
0859:                                            SVG_HEIGHT_ATTRIBUTE, uctx);
0860:                            h *= bounds.getHeight();
0861:                        }
0862:                    }
0863:                    break;
0864:                case USER_SPACE_ON_USE:
0865:                    if (xStr.length() != 0) {
0866:                        x = UnitProcessor.svgHorizontalCoordinateToUserSpace(
0867:                                xStr, SVG_X_ATTRIBUTE, uctx);
0868:                    }
0869:                    if (yStr.length() != 0) {
0870:                        y = UnitProcessor.svgVerticalCoordinateToUserSpace(
0871:                                yStr, SVG_Y_ATTRIBUTE, uctx);
0872:                    }
0873:                    if (wStr.length() != 0) {
0874:                        w = UnitProcessor.svgHorizontalLengthToUserSpace(wStr,
0875:                                SVG_WIDTH_ATTRIBUTE, uctx);
0876:                    }
0877:                    if (hStr.length() != 0) {
0878:                        h = UnitProcessor.svgVerticalLengthToUserSpace(hStr,
0879:                                SVG_HEIGHT_ATTRIBUTE, uctx);
0880:                    }
0881:                    break;
0882:                default:
0883:                    throw new Error("invalid unitsType:" + unitsType); // can't be reached
0884:                }
0885:
0886:                Rectangle2D region = new Rectangle2D.Double(x, y, w, h);
0887:
0888:                // Now, extend filter primitive region with dx/dy/dw/dh
0889:                // settings (Batik extension). The dx/dy/dw/dh padding is
0890:                // *always* in userSpaceOnUse space.
0891:
0892:                units = "";
0893:                if ((parentNode != null)
0894:                        && (parentNode.getNodeType() == Node.ELEMENT_NODE)) {
0895:                    Element parent = (Element) parentNode;
0896:                    units = getChainableAttributeNS(
0897:                            parent,
0898:                            null,
0899:                            SVG12Constants.SVG_FILTER_PRIMITIVE_MARGINS_UNITS_ATTRIBUTE,
0900:                            ctx);
0901:                }
0902:
0903:                if (units.length() == 0) {
0904:                    unitsType = USER_SPACE_ON_USE;
0905:                } else {
0906:                    unitsType = parseCoordinateSystem(
0907:                            filterPrimitiveElement,
0908:                            SVG12Constants.SVG_FILTER_PRIMITIVE_MARGINS_UNITS_ATTRIBUTE,
0909:                            units, ctx);
0910:                }
0911:
0912:                // 'batik:dx' attribute - default is 0
0913:                String dxStr = filterPrimitiveElement.getAttributeNS(null,
0914:                        SVG12Constants.SVG_MX_ATRIBUTE);
0915:                if (dxStr.length() == 0) {
0916:                    dxStr = SVG12Constants.SVG_FILTER_MX_DEFAULT_VALUE;
0917:                }
0918:
0919:                // 'batik:dy' attribute - default is 0
0920:                String dyStr = filterPrimitiveElement.getAttributeNS(null,
0921:                        SVG12Constants.SVG_MY_ATRIBUTE);
0922:                if (dyStr.length() == 0) {
0923:                    dyStr = SVG12Constants.SVG_FILTER_MY_DEFAULT_VALUE;
0924:                }
0925:
0926:                // 'batik:dw' attribute - default is 0
0927:                String dwStr = filterPrimitiveElement.getAttributeNS(null,
0928:                        SVG12Constants.SVG_MW_ATRIBUTE);
0929:                if (dwStr.length() == 0) {
0930:                    dwStr = SVG12Constants.SVG_FILTER_MW_DEFAULT_VALUE;
0931:                }
0932:
0933:                // 'batik:dh' attribute - default is 0
0934:                String dhStr = filterPrimitiveElement.getAttributeNS(null,
0935:                        SVG12Constants.SVG_MH_ATRIBUTE);
0936:                if (dhStr.length() == 0) {
0937:                    dhStr = SVG12Constants.SVG_FILTER_MH_DEFAULT_VALUE;
0938:                }
0939:
0940:                region = extendRegion(dxStr, dyStr, dwStr, dhStr, unitsType,
0941:                        filteredNode, region, uctx);
0942:
0943:                Rectangle2D.intersect(region, filterRegion, region);
0944:
0945:                return region;
0946:            }
0947:
0948:            /////////////////////////////////////////////////////////////////////////
0949:            // region convenient methods
0950:            /////////////////////////////////////////////////////////////////////////
0951:
0952:            /** The userSpaceOnUse coordinate system constants. */
0953:            public static final short USER_SPACE_ON_USE = 1;
0954:
0955:            /** The objectBoundingBox coordinate system constants. */
0956:            public static final short OBJECT_BOUNDING_BOX = 2;
0957:
0958:            /** The strokeWidth coordinate system constants. */
0959:            public static final short STROKE_WIDTH = 3;
0960:
0961:            /**
0962:             * Parses the specified coordinate system defined by the specified element.
0963:             *
0964:             * @param e the element that defines the coordinate system
0965:             * @param attr the attribute which contains the coordinate system
0966:             * @param coordinateSystem the coordinate system to parse
0967:             * @param ctx the BridgeContext to use for error information
0968:             * @return OBJECT_BOUNDING_BOX | USER_SPACE_ON_USE
0969:             */
0970:            public static short parseCoordinateSystem(Element e, String attr,
0971:                    String coordinateSystem, BridgeContext ctx) {
0972:                if (SVG_USER_SPACE_ON_USE_VALUE.equals(coordinateSystem)) {
0973:                    return USER_SPACE_ON_USE;
0974:                } else if (SVG_OBJECT_BOUNDING_BOX_VALUE
0975:                        .equals(coordinateSystem)) {
0976:                    return OBJECT_BOUNDING_BOX;
0977:                } else {
0978:                    throw new BridgeException(ctx, e,
0979:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] { attr,
0980:                                    coordinateSystem });
0981:                }
0982:            }
0983:
0984:            /**
0985:             * Parses the specified coordinate system defined by the specified
0986:             * marker element.
0987:             *
0988:             * @param e the element that defines the coordinate system
0989:             * @param attr the attribute which contains the coordinate system
0990:             * @param coordinateSystem the coordinate system to parse
0991:             * @param ctx the BridgeContext to use for error information
0992:             * @return STROKE_WIDTH | USER_SPACE_ON_USE
0993:             */
0994:            public static short parseMarkerCoordinateSystem(Element e,
0995:                    String attr, String coordinateSystem, BridgeContext ctx) {
0996:                if (SVG_USER_SPACE_ON_USE_VALUE.equals(coordinateSystem)) {
0997:                    return USER_SPACE_ON_USE;
0998:                } else if (SVG_STROKE_WIDTH_VALUE.equals(coordinateSystem)) {
0999:                    return STROKE_WIDTH;
1000:                } else {
1001:                    throw new BridgeException(ctx, e,
1002:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] { attr,
1003:                                    coordinateSystem });
1004:                }
1005:            }
1006:
1007:            /**
1008:             * Returns a rectangle that represents the region defined by the
1009:             * specified coordinates.
1010:             *
1011:             * @param xStr the x coordinate of the region
1012:             * @param yStr the y coordinate of the region
1013:             * @param wStr the width of the region
1014:             * @param hStr the height of the region
1015:             * @param targetNode the graphics node (needed for objectBoundingBox)
1016:             * @param uctx the unit processor context (needed for userSpaceOnUse)
1017:             */
1018:            protected static Rectangle2D convertRegion(String xStr,
1019:                    String yStr, String wStr, String hStr, short unitsType,
1020:                    GraphicsNode targetNode, UnitProcessor.Context uctx) {
1021:
1022:                // construct the mask region in the appropriate coordinate system
1023:                double x, y, w, h;
1024:                switch (unitsType) {
1025:                case OBJECT_BOUNDING_BOX:
1026:                    x = UnitProcessor
1027:                            .svgHorizontalCoordinateToObjectBoundingBox(xStr,
1028:                                    SVG_X_ATTRIBUTE, uctx);
1029:                    y = UnitProcessor.svgVerticalCoordinateToObjectBoundingBox(
1030:                            yStr, SVG_Y_ATTRIBUTE, uctx);
1031:                    w = UnitProcessor.svgHorizontalLengthToObjectBoundingBox(
1032:                            wStr, SVG_WIDTH_ATTRIBUTE, uctx);
1033:                    h = UnitProcessor.svgVerticalLengthToObjectBoundingBox(
1034:                            hStr, SVG_HEIGHT_ATTRIBUTE, uctx);
1035:
1036:                    Rectangle2D bounds = targetNode.getGeometryBounds();
1037:                    if (bounds != null) {
1038:                        x = bounds.getX() + x * bounds.getWidth();
1039:                        y = bounds.getY() + y * bounds.getHeight();
1040:                        w *= bounds.getWidth();
1041:                        h *= bounds.getHeight();
1042:                    } else {
1043:                        x = y = w = h = 0;
1044:                    }
1045:                    break;
1046:                case USER_SPACE_ON_USE:
1047:                    x = UnitProcessor.svgHorizontalCoordinateToUserSpace(xStr,
1048:                            SVG_X_ATTRIBUTE, uctx);
1049:                    y = UnitProcessor.svgVerticalCoordinateToUserSpace(yStr,
1050:                            SVG_Y_ATTRIBUTE, uctx);
1051:                    w = UnitProcessor.svgHorizontalLengthToUserSpace(wStr,
1052:                            SVG_WIDTH_ATTRIBUTE, uctx);
1053:                    h = UnitProcessor.svgVerticalLengthToUserSpace(hStr,
1054:                            SVG_HEIGHT_ATTRIBUTE, uctx);
1055:                    break;
1056:                default:
1057:                    throw new Error("invalid unitsType:" + unitsType); // can't be reached
1058:                }
1059:                return new Rectangle2D.Double(x, y, w, h);
1060:            }
1061:
1062:            /////////////////////////////////////////////////////////////////////////
1063:            // coordinate system and transformation support methods
1064:            /////////////////////////////////////////////////////////////////////////
1065:
1066:            /**
1067:             * Returns an AffineTransform according to the specified parameters.
1068:             *
1069:             * @param e the element that defines the transform
1070:             * @param attr the name of the attribute that represents the transform
1071:             * @param transform the transform to parse
1072:             * @param ctx the BridgeContext to use for error information
1073:             */
1074:            public static AffineTransform convertTransform(Element e,
1075:                    String attr, String transform, BridgeContext ctx) {
1076:                try {
1077:                    return AWTTransformProducer
1078:                            .createAffineTransform(transform);
1079:                } catch (ParseException pEx) {
1080:                    throw new BridgeException(ctx, e, pEx,
1081:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] { attr,
1082:                                    transform, pEx });
1083:                }
1084:            }
1085:
1086:            /**
1087:             * Returns an AffineTransform to move to the objectBoundingBox
1088:             * coordinate system.
1089:             *
1090:             * @param Tx the original transformation
1091:             * @param node the graphics node that defines the coordinate
1092:             *             system to move into
1093:             */
1094:            public static AffineTransform toObjectBBox(AffineTransform Tx,
1095:                    GraphicsNode node) {
1096:
1097:                AffineTransform Mx = new AffineTransform();
1098:                Rectangle2D bounds = node.getGeometryBounds();
1099:                if (bounds != null) {
1100:                    Mx.translate(bounds.getX(), bounds.getY());
1101:                    Mx.scale(bounds.getWidth(), bounds.getHeight());
1102:                }
1103:                Mx.concatenate(Tx);
1104:                return Mx;
1105:            }
1106:
1107:            /**
1108:             * Returns the specified a Rectangle2D move to the objectBoundingBox
1109:             * coordinate system of the specified graphics node.
1110:             *
1111:             * @param r the original Rectangle2D
1112:             * @param node the graphics node that defines the coordinate
1113:             *             system to move into
1114:             */
1115:            public static Rectangle2D toObjectBBox(Rectangle2D r,
1116:                    GraphicsNode node) {
1117:
1118:                Rectangle2D bounds = node.getGeometryBounds();
1119:                if (bounds != null) {
1120:                    return new Rectangle2D.Double(bounds.getX() + r.getX()
1121:                            * bounds.getWidth(), bounds.getY() + r.getY()
1122:                            * bounds.getHeight(), r.getWidth()
1123:                            * bounds.getWidth(), r.getHeight()
1124:                            * bounds.getHeight());
1125:                } else {
1126:                    return new Rectangle2D.Double();
1127:                }
1128:            }
1129:
1130:            /**
1131:             * Returns the value of the 'snapshotTime' attribute on the specified
1132:             * element as a float, or <code>0f</code> if the attribute is missing
1133:             * or given as <code>"none"</code>.
1134:             *
1135:             * @param e the element from which to retrieve the 'snapshotTime' attribute
1136:             * @param ctx the BridgeContext to use for error information
1137:             */
1138:            public static float convertSnapshotTime(Element e, BridgeContext ctx) {
1139:                if (!e.hasAttributeNS(null, SVG_SNAPSHOT_TIME_ATTRIBUTE)) {
1140:                    return 0f;
1141:                }
1142:                String t = e.getAttributeNS(null, SVG_SNAPSHOT_TIME_ATTRIBUTE);
1143:                if (t.equals(SVG_NONE_VALUE)) {
1144:                    return 0f;
1145:                }
1146:
1147:                class Handler implements  ClockHandler {
1148:                    float time;
1149:
1150:                    public void clockValue(float t) {
1151:                        time = t;
1152:                    }
1153:                }
1154:                ClockParser p = new ClockParser(false);
1155:                Handler h = new Handler();
1156:                p.setClockHandler(h);
1157:                try {
1158:                    p.parse(t);
1159:                } catch (ParseException pEx) {
1160:                    throw new BridgeException(null, e, pEx,
1161:                            ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
1162:                                    SVG_SNAPSHOT_TIME_ATTRIBUTE, t, pEx });
1163:                }
1164:                return h.time;
1165:            }
1166:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.