Source Code Cross Referenced for ModelNode.java in  » 6.0-JDK-Modules » j2me » com » sun » perseus » model » 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 » 6.0 JDK Modules » j2me » com.sun.perseus.model 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         */
0026:
0027:        package com.sun.perseus.model;
0028:
0029:        import com.sun.perseus.j2d.Box;
0030:        import com.sun.perseus.j2d.Path;
0031:        import com.sun.perseus.j2d.RenderGraphics;
0032:        import com.sun.perseus.j2d.Tile;
0033:        import com.sun.perseus.j2d.Transform;
0034:
0035:        import org.w3c.dom.DOMException;
0036:
0037:        import org.w3c.dom.svg.SVGRect;
0038:        import org.w3c.dom.svg.SVGMatrix;
0039:
0040:        import org.w3c.dom.events.EventListener;
0041:        import org.w3c.dom.events.EventTarget;
0042:
0043:        /**
0044:         * The central structure manipulated in Perseus is called the <em>Model</em>. It
0045:         * is used for the in-memory representation of an SVG Tiny document structure.
0046:         * 
0047:         * <p>The <code>ModelNode</code> abstraction represents an atomic node in the
0048:         * <b><code>Model</code></b>'s tree structure. </p>
0049:         * 
0050:         * <p>A <code>ModelNode</code> may have regular children (which can be added on
0051:         * <code>CompositeNode</code> implementations, for example), and expanded
0052:         * children (which are automatically computed by the node, for example on
0053:         * <code>Text</code> or on <code>Use</code>). In rendering order, expanded
0054:         * content comes second.</p>
0055:         *
0056:         * <p>A <code>ModelNode</code> can have a parent, which may be null, but it
0057:         * always belongs to a <code>DocumentNode</code> instance which is guaranteed to
0058:         * no be null.</p>
0059:         * 
0060:         * <p>A <code>ModelNode</code> can be painted into a 
0061:         * @link {com.sun.perseus.j2d.RenderGraphics RenderGraphics}. 
0062:         *
0063:         * <p>A <code>ModelNode</code> is subjet to interactivity and its
0064:         * @link {#nodeHitAt nodeHitAt} method can be used to perform hit detection.</p>
0065:         *
0066:         * @version $Id: ModelNode.java,v 1.24 2006/06/29 10:47:33 ln156897 Exp $
0067:         */
0068:        public abstract class ModelNode implements  EventTarget {
0069:            /**
0070:             * Used in cases the parent node is null.
0071:             */
0072:            protected final Transform IDENTITY = new Transform(null);
0073:
0074:            /**
0075:             * The parent node
0076:             */
0077:            protected ModelNode parent;
0078:
0079:            /**
0080:             * The next sibling
0081:             */
0082:            protected ModelNode nextSibling;
0083:
0084:            /**
0085:             * The next sibling
0086:             */
0087:            protected ModelNode prevSibling;
0088:
0089:            /**
0090:             * Mask for the renderable bit.
0091:             */
0092:            public static final int CAN_RENDER_RENDERABLE_MASK = ~0x1;
0093:
0094:            /**
0095:             * Mask for the required features bit
0096:             */
0097:            public static final int CAN_RENDER_REQUIRED_FEATURES_MASK = ~(1 << 1);
0098:
0099:            /**
0100:             * Mask for the required extensions bit
0101:             */
0102:            public static final int CAN_RENDER_REQUIRED_EXTENSIONS_MASK = ~(1 << 2);
0103:
0104:            /**
0105:             * Mask for the required languages bit
0106:             */
0107:            public static final int CAN_RENDER_SYSTEM_LANGUAGE_MASK = ~(1 << 3);
0108:
0109:            /**
0110:             * Mask for conditions met, i.e., requiredFeatures, requiredExtensions,
0111:             * and systemLanguage.
0112:             */
0113:            public static final int CAN_RENDER_CONDITIONS_MET_MASK = CAN_RENDER_REQUIRED_FEATURES_MASK
0114:                    & CAN_RENDER_REQUIRED_EXTENSIONS_MASK
0115:                    & CAN_RENDER_SYSTEM_LANGUAGE_MASK;
0116:
0117:            /**
0118:             * Mask defining which bits from the canRenderState value are copied over
0119:             * to newly created proxies. See the description of the canRenderState
0120:             * bits below.
0121:             */
0122:            public static final int CAN_RENDER_PROXY_BITS_MASK = 0x7EE;
0123:            /**
0124:             * Mask for the non-invertible transform bit
0125:             */
0126:            public static final int CAN_RENDER_NON_INVERTIBLE_TXF_MASK = ~(1 << 4);
0127:
0128:            /**
0129:             * Mask for the display bit
0130:             */
0131:            public static final int CAN_RENDER_DISPLAY_MASK = ~(1 << 5);
0132:
0133:            /**
0134:             * Mask for the zero-width bit
0135:             */
0136:            public static final int CAN_RENDER_ZERO_WIDTH_MASK = ~(1 << 6);
0137:
0138:            /**
0139:             * Mask for the zero-height bit
0140:             */
0141:            public static final int CAN_RENDER_ZERO_HEIGHT_MASK = ~(1 << 7);
0142:
0143:            /**
0144:             * Mask for the empty viewbox bit
0145:             */
0146:            public static final int CAN_RENDER_EMPTY_VIEWBOX_MASK = ~(1 << 8);
0147:
0148:            /**
0149:             * Mask for the empty path bit
0150:             */
0151:            public static final int CAN_RENDER_EMPTY_PATH_MASK = ~(1 << 9);
0152:
0153:            /**
0154:             * Mask for the zero font-size bit
0155:             */
0156:            public static final int CAN_RENDER_ZERO_FONT_SIZE_MASK = ~(1 << 10);
0157:
0158:            /**
0159:             * Mask for the in-document-tree bit
0160:             */
0161:            public static final int CAN_RENDER_IN_DOCUMENT_TREE_MASK = ~(1 << 11);
0162:
0163:            /**
0164:             * Mask for the paren canRenderState bit
0165:             */
0166:            public static final int CAN_RENDER_PARENT_STATE_MASK = ~(1 << 12);
0167:
0168:            /**
0169:             * Mask for the renderable bit.
0170:             */
0171:            public static final int CAN_RENDER_RENDERABLE_BIT = ~CAN_RENDER_RENDERABLE_MASK;
0172:
0173:            /**
0174:             * Mask for the required features bit
0175:             */
0176:            public static final int CAN_RENDER_REQUIRED_FEATURES_BIT = ~CAN_RENDER_REQUIRED_FEATURES_MASK;
0177:
0178:            /**
0179:             * Mask for the required extensions bit
0180:             */
0181:            public static final int CAN_RENDER_REQUIRED_EXTENSIONS_BIT = ~CAN_RENDER_REQUIRED_EXTENSIONS_MASK;
0182:
0183:            /**
0184:             * Mask for the system language bit
0185:             */
0186:            public static final int CAN_RENDER_SYSTEM_LANGUAGE_BIT = ~CAN_RENDER_SYSTEM_LANGUAGE_MASK;
0187:
0188:            /**
0189:             * Mask for the conditionsMet bits
0190:             */
0191:            public static final int CAN_RENDER_CONDITIONS_MET_BITS = ~CAN_RENDER_CONDITIONS_MET_MASK;
0192:
0193:            /**
0194:             * Mask for the non-invertible transform bit
0195:             */
0196:            public static final int CAN_RENDER_NON_INVERTIBLE_TXF_BIT = ~CAN_RENDER_NON_INVERTIBLE_TXF_MASK;
0197:
0198:            /**
0199:             * Mask for the display bit
0200:             */
0201:            public static final int CAN_RENDER_DISPLAY_BIT = ~CAN_RENDER_DISPLAY_MASK;
0202:
0203:            /**
0204:             * Mask for the zero-width bit
0205:             */
0206:            public static final int CAN_RENDER_ZERO_WIDTH_BIT = ~CAN_RENDER_ZERO_WIDTH_MASK;
0207:
0208:            /**
0209:             * Mask for the zero-height bit
0210:             */
0211:            public static final int CAN_RENDER_ZERO_HEIGHT_BIT = ~CAN_RENDER_ZERO_HEIGHT_MASK;
0212:
0213:            /**
0214:             * Mask for the empty viewbox bit
0215:             */
0216:            public static final int CAN_RENDER_EMPTY_VIEWBOX_BIT = ~CAN_RENDER_EMPTY_VIEWBOX_MASK;
0217:
0218:            /**
0219:             * Mask for the empty path bit
0220:             */
0221:            public static final int CAN_RENDER_EMPTY_PATH_BIT = ~CAN_RENDER_EMPTY_PATH_MASK;
0222:
0223:            /**
0224:             * Mask for the zero font-size bit
0225:             */
0226:            public static final int CAN_RENDER_ZERO_FONT_SIZE_BIT = ~CAN_RENDER_ZERO_FONT_SIZE_MASK;
0227:
0228:            /**
0229:             * Mask for the in document tree bit
0230:             */
0231:            public static final int CAN_RENDER_IN_DOCUMENT_TREE_BIT = ~CAN_RENDER_IN_DOCUMENT_TREE_MASK;
0232:
0233:            /**
0234:             * Mask for the parent cansRenderState bit
0235:             */
0236:            public static final int CAN_RENDER_PARENT_STATE_BIT = ~CAN_RENDER_PARENT_STATE_MASK;
0237:
0238:            /**
0239:             * Pre-computes whether or not this node can render. This is a bit-mask.
0240:             *
0241:             * 0  : renderable (i.e., initialized in the class constructor). All 
0242:             *      classes.
0243:             * 1  : required features. ElementNode
0244:             * 2  : required extensions. ElementNode
0245:             * 3  : required languages. ElementNode.
0246:             * 4  : non-invertible transform. StructureNode, AbstractRenderingNode.
0247:             * 5  : display. CompositeGraphicsNode.
0248:             * 6  : width is zero. Ellipse, ImageNode, Rect, SVG, Viewport
0249:             * 7  : height is zero. Ellipse, ImageNode, Rect, SVG, Viewport
0250:             * 8  : viewBox width or height is zero or negative.
0251:             * 9  : path is null or has no segments. ShapeNode.
0252:             * 10 : font-size is negative or zero. Text.
0253:             * 11 : node in document tree.
0254:             * 12 : parent canRenderState. This 1 bit value is set if any of the bits
0255:             *      in the parent node's canRenderState is set.
0256:             *
0257:             * Only bits 1/2/3 are special in that they need to be applied from a node
0258:             * to its proxies. Other bits (e.g., bit 5 (display)) do not need to be
0259:             * propagated because they are set when the property changes on the node and
0260:             * there is already propagation of property changes to the proxies.
0261:             *
0262:             * By default, ModelNodes are not renderable and are not in the document 
0263:             * tree.
0264:             */
0265:            protected int canRenderState = CAN_RENDER_RENDERABLE_BIT
0266:                    | CAN_RENDER_IN_DOCUMENT_TREE_BIT;
0267:
0268:            /**
0269:             * Used to track if this node is loaded or not. A node becomes loaded after
0270:             * its <code>markLoaded</code> method is called.  Note: the default is
0271:             * <b>true</b> because when used through scripting, nodes are considered
0272:             * fully loaded and operational.  When used by the builder module or a
0273:             * parser, the flag needs to be first turned off (see the
0274:             * <code>setLoaded</code> method to control the progressive rendering
0275:             * behavior (see the <code>CanvasManager</code> class).
0276:             */
0277:            protected boolean loaded = true;
0278:
0279:            /**
0280:             * The owner <code>DocumentNode</code>
0281:             */
0282:            protected DocumentNode ownerDocument;
0283:
0284:            /**
0285:             * By default, a node's bounding box is not accounted for. This is 
0286:             * overridden by children classes to specify when and under which condition
0287:             * their bounding box should be accounted for.
0288:             *
0289:             * @return true if the node's bounding box should be accounted for.
0290:             */
0291:            protected boolean contributeBBox() {
0292:                return false;
0293:            }
0294:
0295:            /**
0296:             * @return the <code>UpdateListener</code> associated with the nearest
0297:             *         <code>DocumentNode</code> ancestor or null if there is no
0298:             *         <code>Viewporpt</code> ancestor
0299:             */
0300:            protected UpdateListener getUpdateListener() {
0301:                //
0302:                // It is important to _not_ use ownerDocument.getUpdateListener
0303:                // because we do not report changes to elements which are not 
0304:                // hooked into the document tree.
0305:                //
0306:                // May be that should be changed in the future: we could also
0307:                // always report updates to the listener and let it figure out
0308:                // whether or not the reporting node is in the Document tree
0309:                // or not yet.
0310:                //
0311:                if (parent == null) {
0312:                    return null;
0313:                } else {
0314:                    return parent.getUpdateListener();
0315:                }
0316:            }
0317:
0318:            /**
0319:             * Returns the next sibling object of this object, or
0320:             * <code>null</code> if this is the last sibling.
0321:             *
0322:             * @return the next sibling object.
0323:             */
0324:            public ModelNode getNextSiblingNode() {
0325:                return nextSibling;
0326:            }
0327:
0328:            /**
0329:             * Returns the previous sibling object of this object, or
0330:             * <code>null</code> if this is the first child node and there
0331:             * is no previous sibling.
0332:             *
0333:             * @return the next sibling object.
0334:             */
0335:            public ModelNode getPreviousSiblingNode() {
0336:                return prevSibling;
0337:            }
0338:
0339:            /**
0340:             * @return a reference to the parent <code>ModelNode</code>
0341:             */
0342:            public ModelNode getParent() {
0343:                return parent;
0344:            }
0345:
0346:            /**
0347:             * @param newParent this node's new parent
0348:             */
0349:            protected void setParent(final ModelNode newParent) {
0350:                modifyingNode();
0351:                setParentQuiet(newParent);
0352:                nodeInserted(this );
0353:            }
0354:
0355:            /**
0356:             * Sets this node's parent but does not generate change 
0357:             * events.
0358:             * 
0359:             * @param newParent the node's new parent node.
0360:             */
0361:            protected void setParentQuiet(final ModelNode newParent) {
0362:                if (parent == newParent) {
0363:                    return;
0364:                }
0365:
0366:                // If the new parent is not null, check whether or not 
0367:                // it is in the document tree. In all cases, we need 
0368:                // to unhook and then hook again.
0369:                if (parent != null) {
0370:                    onUnhookedFromDocumentTree();
0371:                }
0372:
0373:                parent = newParent;
0374:
0375:                // If the parent is not null and in the document tree,
0376:                // we process that condition again.
0377:                if (parent != null) {
0378:                    if (parent.isInDocumentTree()) {
0379:                        onHookedInDocumentTree();
0380:                    }
0381:                }
0382:            }
0383:
0384:            /**
0385:             * Utility method. Unhooks a node and all its following siblings, 
0386:             * quietly setting the parent and or proxy to null.
0387:             *
0388:             * @param node the root of the branch to unhook.
0389:             */
0390:            protected final void unhookQuiet(ModelNode node) {
0391:                if (node != null) {
0392:                    if (node.prevSibling != null) {
0393:                        node.prevSibling.nextSibling = null;
0394:                    }
0395:                }
0396:
0397:                while (node != null) {
0398:                    node.setParentQuiet(null);
0399:                    if (node instanceof  ElementNodeProxy) {
0400:                        ((ElementNodeProxy) node).setProxied(null);
0401:                    }
0402:                    node.unhookChildrenQuiet();
0403:                    node.unhookExpandedQuiet();
0404:                    node = node.nextSibling;
0405:                }
0406:            }
0407:
0408:            /**
0409:             * Utilitty method. Returns true if the input node is part of the 
0410:             * Document tree, i.e., if its top most ancestor is equal to its
0411:             * ownerDocument.
0412:             *
0413:             * @return true if this node is a <code>DocumentNode</code> or if 
0414:             *         one of its ancestors is a <code>DocumentNode</code>
0415:             */
0416:            protected boolean isInDocumentTree() {
0417:                return ((canRenderState & CAN_RENDER_IN_DOCUMENT_TREE_BIT) == 0);
0418:            }
0419:
0420:            /**
0421:             * Returns the <code>DocumentNode</code> this node is attached
0422:             * to.
0423:             *
0424:             * @return the <code>DocumentNode</code> this node belongs to. The return
0425:             *         value should never be null.
0426:             */
0427:            public DocumentNode getOwnerDocument() {
0428:                return ownerDocument;
0429:            }
0430:
0431:            /**
0432:             * By default, this node returns true if there are no children.
0433:             * <code>ModelNode</code> implementations with expanded content
0434:             * should override this method.
0435:             *
0436:             * @return true if this node has, or may have children or expanded
0437:             *         children. A node may not know in advance if it has expanded
0438:             *         children because in some cases, the computation of expanded
0439:             *         content is done lazily. So this returns false if the node
0440:             *         does not have children and will never have expanded content.
0441:             */
0442:            public boolean hasDescendants() {
0443:                return getFirstChildNode() != null;
0444:            }
0445:
0446:            /**
0447:             * Paints the input node and all its siblings into the  
0448:             * <code>RenderGraphics</code>
0449:             *
0450:             * @param node the <code>ModelNode</code> to paint.
0451:             * @param rg the <code>RenderGraphics</code> where the nodes should 
0452:             *           be painted
0453:             */
0454:            static void paint(ModelNode node, final RenderGraphics rg) {
0455:                while (node != null) {
0456:                    node.paint(rg);
0457:                    node = node.nextSibling;
0458:                }
0459:            }
0460:
0461:            /**
0462:             * @return the inherited value for the requested property.
0463:             */
0464:            protected final Object getInheritedPropertyState(
0465:                    final int propertyIndex) {
0466:                if (parent == null) {
0467:                    return ownerDocument.getInitialPropertyState(propertyIndex);
0468:                }
0469:
0470:                return parent.getPropertyState(propertyIndex);
0471:            }
0472:
0473:            /**
0474:             * @return the inherited value for the requested float property.
0475:             */
0476:            protected final float getInheritedFloatPropertyState(
0477:                    final int propertyIndex) {
0478:                if (parent == null) {
0479:                    return ownerDocument
0480:                            .getInitialFloatPropertyState(propertyIndex);
0481:                }
0482:
0483:                return parent.getFloatPropertyState(propertyIndex);
0484:            }
0485:
0486:            /**
0487:             * @return the inherited value for the requested packed property.
0488:             */
0489:            protected final int getInheritedPackedPropertyState(
0490:                    final int propertyIndex) {
0491:                if (parent == null) {
0492:                    return ownerDocument
0493:                            .getInitialPackedPropertyState(propertyIndex);
0494:                }
0495:
0496:                return parent.getPackedPropertyState(propertyIndex);
0497:            }
0498:
0499:            /**
0500:             * Returns the value for the given property.
0501:             *
0502:             * @return the value for the given property, null if the property is 
0503:             *         unknown.
0504:             */
0505:            protected Object getPropertyState(final int propertyIndex) {
0506:                return ownerDocument.getInitialPropertyState(propertyIndex);
0507:            }
0508:
0509:            /**
0510:             * Returns the value for the given packed property.
0511:             *
0512:             * @return the value of the given property.
0513:             */
0514:            protected int getPackedPropertyState(final int propertyIndex) {
0515:                return ownerDocument
0516:                        .getInitialPackedPropertyState(propertyIndex);
0517:            }
0518:
0519:            /**
0520:             * Returns the value for the given float property.
0521:             *
0522:             * @return the value of the given property.
0523:             */
0524:            protected float getFloatPropertyState(final int propertyIndex) {
0525:                return ownerDocument
0526:                        .getInitialFloatPropertyState(propertyIndex);
0527:            }
0528:
0529:            /**
0530:             * Sets the computed value for the given property.
0531:             *
0532:             * @param propertyIndex the property index
0533:             * @param propertyValue the computed value for the property.
0534:             */
0535:            protected void setPropertyState(final int propertyIndex,
0536:                    final Object propertyValue) {
0537:            }
0538:
0539:            /**
0540:             * Sets the computed value for the given float property.
0541:             *
0542:             * @param propertyIndex the property index
0543:             * @param propertyValue the computed value for the property.
0544:             */
0545:            protected void setFloatPropertyState(final int propertyIndex,
0546:                    final float propertyValue) {
0547:            }
0548:
0549:            /**
0550:             * Sets the computed value for the given packed property.
0551:             *
0552:             * @param propertyIndex the property index
0553:             * @param propertyValue the computed value for the property.
0554:             */
0555:            protected void setPackedPropertyState(final int propertyIndex,
0556:                    final int propertyValue) {
0557:            }
0558:
0559:            /**
0560:             * Checks the state of the property value.
0561:             *
0562:             * @param propertyIndex the property index
0563:             * @param propertyValue the computed value for the property.
0564:             */
0565:            protected boolean isPropertyState(final int propertyIndex,
0566:                    final Object propertyValue) {
0567:                // By default, return true so that we don't bother setting an unknown 
0568:                // property.
0569:                return true;
0570:            }
0571:
0572:            /**
0573:             * Checks the state of the float property value.
0574:             *
0575:             * @param propertyIndex the property index
0576:             * @param propertyValue the computed value for the property.
0577:             */
0578:            protected boolean isFloatPropertyState(final int propertyIndex,
0579:                    final float propertyValue) {
0580:                // By default, return true so that we don't bother setting an unknown 
0581:                // property.
0582:                return true;
0583:            }
0584:
0585:            /**
0586:             * Checks the state of the packed property value.
0587:             *
0588:             * @param propertyIndex the property index
0589:             * @param propertyValue the computed value for the property.
0590:             */
0591:            protected boolean isPackedPropertyState(final int propertyIndex,
0592:                    final int propertyValue) {
0593:                // By default, return true so that we don't bother setting an unknown 
0594:                // property.
0595:                return true;
0596:            }
0597:
0598:            /**
0599:             * Recomputes the given property's state given the new parent property.
0600:             * By default, this simply propagates to children.
0601:             *
0602:             * @param propertyIndex index for the property whose value is changing.
0603:             * @param parentPropertyValue the value that children of this node should 
0604:             *        now inherit.
0605:             * 
0606:             */
0607:            protected void recomputePropertyState(final int propertyIndex,
0608:                    final Object parentPropertyValue) {
0609:                propagatePropertyState(propertyIndex, parentPropertyValue);
0610:            }
0611:
0612:            /**
0613:             * Recomputes the given float property's state given the new parent
0614:             * property. By default, this simply propagates to children.
0615:             *
0616:             * @param propertyIndex index for the property whose value is changing.
0617:             * @param parentPropertyValue the value that children of this node should 
0618:             *        now inherit.
0619:             * 
0620:             */
0621:            protected void recomputeFloatPropertyState(final int propertyIndex,
0622:                    final float parentPropertyValue) {
0623:                propagateFloatPropertyState(propertyIndex, parentPropertyValue);
0624:            }
0625:
0626:            /**
0627:             * Recomputes the given packed property's state given the new parent 
0628:             * property. By default, this simply propagates to children.
0629:             *
0630:             * @param propertyIndex index for the property whose value is changing.
0631:             * @param parentPropertyValue the value that children of this node should 
0632:             *        now inherit.
0633:             * 
0634:             */
0635:            protected void recomputePackedPropertyState(
0636:                    final int propertyIndex, final int parentPropertyValue) {
0637:                propagatePackedPropertyState(propertyIndex, parentPropertyValue);
0638:            }
0639:
0640:            /**
0641:             * Recomputes all inherited properties and propages the recomputation to 
0642:             * children.
0643:             */
0644:            void recomputeInheritedProperties() {
0645:                ModelNode c = getFirstChildNode();
0646:                while (c != null) {
0647:                    c.recomputeInheritedProperties();
0648:                    c = c.nextSibling;
0649:                }
0650:            }
0651:
0652:            /**
0653:             * Called when the canRenderState changes. If both values are zero, or
0654:             * if both values are non zero, then children need to recompute their
0655:             * canRenderState and propagate if need be.
0656:             *
0657:             * @param oldCanRenderState the old value for canRenderState.
0658:             * @param newCanRenderState the new value for canRenderState
0659:             */
0660:            protected void propagateCanRenderState(final int oldCanRenderState,
0661:                    final int newCanRenderState) {
0662:                if (oldCanRenderState != newCanRenderState
0663:                        && ((oldCanRenderState == 0) || (newCanRenderState == 0))) {
0664:                    if (newCanRenderState == 0) {
0665:                        // Clear the parent can render state bit and propagate.
0666:                        // Propagate to regular children.
0667:                        ModelNode node = getFirstChildNode();
0668:                        boolean nodeDisplay = false;
0669:                        int nodeOldState = 0;
0670:                        while (node != null) {
0671:                            nodeOldState = node.canRenderState;
0672:                            node.canRenderState &= CAN_RENDER_PARENT_STATE_MASK;
0673:                            node.propagateCanRenderState(nodeOldState,
0674:                                    node.canRenderState);
0675:                            node = node.nextSibling;
0676:                        }
0677:
0678:                        // Propagate to expanded children.
0679:                        node = getFirstComputedExpandedChild();
0680:                        while (node != null) {
0681:                            nodeOldState = node.canRenderState;
0682:                            node.canRenderState &= CAN_RENDER_PARENT_STATE_MASK;
0683:                            node.propagateCanRenderState(nodeOldState,
0684:                                    node.canRenderState);
0685:                            node = node.nextSibling;
0686:                        }
0687:
0688:                    } else {
0689:                        // Set the parent can render state bit and propagate.
0690:                        // Propagate to regular children.
0691:                        ModelNode node = getFirstChildNode();
0692:                        boolean nodeDisplay = false;
0693:                        int nodeOldState = 0;
0694:                        while (node != null) {
0695:                            nodeOldState = node.canRenderState;
0696:                            node.canRenderState |= CAN_RENDER_PARENT_STATE_BIT;
0697:                            node.propagateCanRenderState(nodeOldState,
0698:                                    node.canRenderState);
0699:                            node = node.nextSibling;
0700:                        }
0701:
0702:                        // Propagate to expanded children.
0703:                        node = getFirstComputedExpandedChild();
0704:                        while (node != null) {
0705:                            nodeOldState = node.canRenderState;
0706:                            node.canRenderState |= CAN_RENDER_PARENT_STATE_BIT;
0707:                            node.propagateCanRenderState(nodeOldState,
0708:                                    node.canRenderState);
0709:                            node = node.nextSibling;
0710:                        }
0711:
0712:                    }
0713:                }
0714:            }
0715:
0716:            /**
0717:             * Called when the computed value of the given property has changed.
0718:             * By default, propagate both to regular content and expanded content.
0719:             *
0720:             * @param propertyIndex index for the property whose value has changed.
0721:             * @param parentPropertyValue the value that children of this node should 
0722:             *        now inherit.
0723:             */
0724:            protected void propagatePropertyState(final int propertyIndex,
0725:                    final Object parentPropertyValue) {
0726:                // Propagate to regular children.
0727:                ModelNode node = getFirstChildNode();
0728:                while (node != null) {
0729:                    node.recomputePropertyState(propertyIndex,
0730:                            parentPropertyValue);
0731:                    node = node.nextSibling;
0732:                }
0733:
0734:                // Propagate to expanded children.
0735:                node = getFirstExpandedChild();
0736:                while (node != null) {
0737:                    node.recomputePropertyState(propertyIndex,
0738:                            parentPropertyValue);
0739:                    node = node.nextSibling;
0740:                }
0741:            }
0742:
0743:            /**
0744:             * Called when the computed value of the given float property has changed.
0745:             * By default, propagate both to regular content and expanded content.
0746:             *
0747:             * @param propertyIndex index for the property whose value has changed.
0748:             * @param parentPropertyValue the value that children of this node should 
0749:             *        now inherit.
0750:             */
0751:            protected void propagateFloatPropertyState(final int propertyIndex,
0752:                    final float parentPropertyValue) {
0753:                // Propagate to regular children.
0754:                ModelNode node = getFirstChildNode();
0755:                while (node != null) {
0756:                    node.recomputeFloatPropertyState(propertyIndex,
0757:                            parentPropertyValue);
0758:                    node = node.nextSibling;
0759:                }
0760:
0761:                // Propagate to expanded children.
0762:                node = getFirstExpandedChild();
0763:                while (node != null) {
0764:                    node.recomputeFloatPropertyState(propertyIndex,
0765:                            parentPropertyValue);
0766:                    node = node.nextSibling;
0767:                }
0768:            }
0769:
0770:            /**
0771:             * Called when the computed value of the given packed property has changed.
0772:             * By default, propagate both to regular content and expanded content.
0773:             *
0774:             * @param propertyIndex index for the property whose value has changed.
0775:             * @param parentPropertyValue the value that children of this node should 
0776:             *        now inherit.
0777:             */
0778:            protected void propagatePackedPropertyState(
0779:                    final int propertyIndex, final int parentPropertyValue) {
0780:                // Propagate to regular children.
0781:                ModelNode node = getFirstChildNode();
0782:                while (node != null) {
0783:                    node.recomputePackedPropertyState(propertyIndex,
0784:                            parentPropertyValue);
0785:                    node = node.nextSibling;
0786:                }
0787:
0788:                // Propagate to expanded children.
0789:                node = getFirstExpandedChild();
0790:                while (node != null) {
0791:                    node.recomputePackedPropertyState(propertyIndex,
0792:                            parentPropertyValue);
0793:                    node = node.nextSibling;
0794:                }
0795:            }
0796:
0797:            /**
0798:             * @return this node's cached transform. 
0799:             */
0800:            public Transform getTransformState() {
0801:                // By default, a ModelNode does not add any new transform, so its
0802:                // cached transform state is the same as its parent node.
0803:                if (parent != null) {
0804:                    return parent.getTransformState();
0805:                }
0806:
0807:                return IDENTITY;
0808:            }
0809:
0810:            /**
0811:             * @return this node's cached inverse transform. 
0812:             */
0813:            Transform getInverseTransformState() {
0814:                // By default, a ModelNode does not add any new transform, so its
0815:                // cached inverse transform state is the same as its parent node.
0816:                if (parent != null) {
0817:                    return parent.getInverseTransformState();
0818:                }
0819:
0820:                return IDENTITY;
0821:            }
0822:
0823:            /**
0824:             * Recomputes the transform cache, if one exists. This should recursively
0825:             * call recomputeTransformState on children node or expanded content, if
0826:             * any.
0827:             *
0828:             * By default, because a ModelNode has no transform and no cached transform,
0829:             * this only does a pass down.
0830:             */
0831:            protected void recomputeTransformState() {
0832:                if (parent == null) {
0833:                    recomputeTransformState(new Transform(null));
0834:                } else {
0835:                    recomputeTransformState(parent.getTransformState());
0836:                }
0837:            }
0838:
0839:            /**
0840:             * Recomputes the transform cache, if one exists. This should recursively
0841:             * call recomputeTransformState on children node or expanded content, if
0842:             * any.
0843:             *
0844:             * By default, because a ModelNode has no transform and no cached transform,
0845:             * this only does a pass down.
0846:             *
0847:             * @param parentTransform the Transform applied to this node's parent.
0848:             */
0849:            protected void recomputeTransformState(
0850:                    final Transform parentTransform) {
0851:                recomputeTransformState(getTransformState(),
0852:                        getFirstChildNode());
0853:                recomputeTransformState(getTransformState(),
0854:                        getFirstExpandedChild());
0855:                computeCanRenderTransformBit(getTransformState());
0856:            }
0857:
0858:            /**
0859:             * Recomputes the transform cache of the input <code>ModelNode</code>
0860:             * and all its siblings. Implementation helper.
0861:             *
0862:             * @param parentTransform the parent transform.
0863:             * @param node first node whose transform cache should be 
0864:             *        cleared.
0865:             */
0866:            void recomputeTransformState(final Transform parentTransform,
0867:                    ModelNode node) {
0868:                while (node != null) {
0869:                    node.recomputeTransformState(parentTransform);
0870:                    node = node.nextSibling;
0871:                }
0872:            }
0873:
0874:            /**
0875:             * @return true if this node is hooked to the document tree, i.e., if it top
0876:             * most ancestor is the DocumentNode.
0877:             */
0878:            boolean inDocumentTree() {
0879:                return parent != null && parent.inDocumentTree();
0880:            }
0881:
0882:            // JAVADOC COMMENT ELIDED
0883:            public SVGMatrix getScreenCTM() {
0884:                // The CTM is null if the element is not in the document tree.
0885:                if (!inDocumentTree()) {
0886:                    return null;
0887:                }
0888:
0889:                return new Transform(getTransformState());
0890:            }
0891:
0892:            /**
0893:             * Computes this node's rendering tile.
0894:             *
0895:             * @param tile the Tile instance whose bounds should be set.
0896:             * @return the device space rendering tile.
0897:             */
0898:            protected void computeRenderingTile(final Tile tile) {
0899:                // By default, there is no rendering and the tile is set to reflect
0900:                // 'no rendering'
0901:                tile.x = Integer.MIN_VALUE;
0902:                tile.y = Integer.MIN_VALUE;
0903:                tile.maxX = Integer.MIN_VALUE;
0904:                tile.maxY = Integer.MIN_VALUE;
0905:            }
0906:
0907:            /**
0908:             * @return the bounding box, in screen coordinate, which encompasses the
0909:             * node's rendering. If this node's hasRendering method returns false, then
0910:             * this method should return null. By default, this method returns null
0911:             * because hasNodeRendering returns null by default.
0912:             */
0913:            protected Tile getRenderingTile() {
0914:                return null;
0915:            }
0916:
0917:            /**
0918:             * @return the tile which encompasses the node's last actual rendering. If
0919:             * this node's hasRendering method returns false, then this method should
0920:             * return null. By default, this method returns null because
0921:             * hasNodeRendering returns null by default.
0922:             */
0923:            protected Tile getLastRenderedTile() {
0924:                return null;
0925:            }
0926:
0927:            /**
0928:             * After calling this method, getLastRenderedTile should always return null.
0929:             */
0930:            protected void clearLastRenderedTile() {
0931:            }
0932:
0933:            /**
0934:             * Utility method to recycle a <code>Transform</code> instance when 
0935:             * possible.
0936:             *
0937:             * @param tx the <code>Transform</code> to use to initialize the returned
0938:             *        value.
0939:             * @param workTx the candidate <code>Transform</code> instance which may be
0940:             *        re-cycled. The instance can be recycled if it is different 
0941:             *        (i.e., a different reference) from the input base transform 
0942:             *        <code>tx</code>.
0943:             */
0944:            protected final Transform recycleTransform(final Transform tx,
0945:                    final Transform workTx) {
0946:                if (workTx != null && workTx != tx) {
0947:                    // We recycle workTx
0948:                    workTx.setTransform(tx);
0949:                    return workTx;
0950:                } else {
0951:                    // System.err.println(">>>>>>> creating new Transform instance...");
0952:                    // We cannot use workTx because it is null or 
0953:                    // it is the same as tx.
0954:                    return new Transform(tx);
0955:                }
0956:            }
0957:
0958:            /**
0959:             * Should be overridden by derived classes to apply any node specific 
0960:             * transform to the input transform.
0961:             *
0962:             * If the input transform is null and this node does not add any 
0963:             * transform, the return value should be null.
0964:             *
0965:             * If the input transform is null and this node adds a transform, the
0966:             * return value should be an object equal to this node's transform,
0967:             * but not be the same instance.
0968:             *
0969:             * If the input transform is not null and this node does not add any
0970:             * transform, the return value should be the same as the input transform.
0971:             *
0972:             * If the input transform is not null and this node adds a transform,
0973:             * the return value should be a new (different) transform.
0974:             *
0975:             * The second parameter, workTxf can be re-used to hold the result 
0976:             * only if it is different from tx. If it is referencing the same instance
0977:             * as tx and a new Transform needs to be created, then it should not
0978:             * be reused. 
0979:             * IMPL NOTE : This is a coding style to recycle <code>Transform</code>
0980:             * instances in animation loops.
0981:             *
0982:             * @param tx the <code>Transform</code> to apply additional node 
0983:             *        transforms to. This may be null.
0984:             * @param workTx a <code>Transform</code> which can be re-used if a 
0985:             *        new <code>Transform</code> needs to be created and workTx
0986:             *        is not the same instance as tx.
0987:             * @return a transform with this node's transform added.
0988:             */
0989:            protected Transform appendTransform(final Transform tx,
0990:                    final Transform workTx) {
0991:                // Does nothing by default. See derived classes.
0992:                return tx;
0993:            }
0994:
0995:            /**
0996:             * @param bbox the bounding box to which this node's bounding box should be
0997:             *        appended. That bounding box is in the target coordinate space. It 
0998:             *        may be null, in which case this node should create a new one.
0999:             * @param t the transform to apply from the node's coordinate space to the
1000:             *        target coordinate space. May be null for the identity 
1001:             *        transform.
1002:             * @return the node's bounding box in the target coordinate space.
1003:             */
1004:            Box addBBox(Box bbox, final Transform t) {
1005:                return bbox;
1006:            }
1007:
1008:            /**
1009:             * Implementation helper. Adds the input shape's bounding box to the
1010:             * input bounding box rect. If the shape is null, nothing is added.
1011:             *
1012:             * @param path the shape whose bounds, transformed through t, should be
1013:             *        added to bbox.
1014:             * @param t the transform to the target bounds space.
1015:             * @param bbox the bounding box to which the shape's bounds should be
1016:             *        added.
1017:             * @return a rectangle that encompasses bbox and the path's bounding box,
1018:             *         after transformation to the target coordinate space.
1019:             */
1020:            static Box addShapeBBox(Box bbox, final Path path, final Transform t) {
1021:                if (path == null || path.getNumberOfSegments() == 0) {
1022:                    return bbox;
1023:                }
1024:
1025:                Box b = null;
1026:                if (t == null) {
1027:                    b = path.getBounds();
1028:                } else {
1029:                    b = path.getTransformedBounds(t);
1030:                }
1031:
1032:                return addBBox(bbox, b.getX(), b.getY(), b.getWidth(), b
1033:                        .getHeight());
1034:            }
1035:
1036:            /**
1037:             * Implementation helper. Adds the input rectangle to the input bounding box
1038:             * rect.
1039:             *
1040:             * @param bbox the rectangle to which the new box should be added.
1041:             * @param x the x-axis origin of the new rect to add
1042:             * @param y the y-axis origin of the new rect to add
1043:             * @param width the width of the rect to add
1044:             * @param height the height of the rect to add
1045:             * @return a bounding box that encompasses bbox and the (x, y, width, 
1046:             *         height) rectangle.
1047:             */
1048:            static Box addBBox(Box bbox, final float x, final float y,
1049:                    final float width, final float height) {
1050:                if (bbox == null) {
1051:                    bbox = new Box(x, y, width, height);
1052:                    return bbox;
1053:                }
1054:
1055:                bbox.width = bbox.x + bbox.width;
1056:                bbox.height = bbox.y + bbox.height;
1057:
1058:                if (bbox.x > x) {
1059:                    bbox.x = x;
1060:                }
1061:
1062:                if (bbox.y > y) {
1063:                    bbox.y = y;
1064:                }
1065:
1066:                if (bbox.width < x + width) {
1067:                    bbox.width = x + width;
1068:                }
1069:
1070:                if (bbox.height < y + height) {
1071:                    bbox.height = y + height;
1072:                }
1073:
1074:                bbox.width -= bbox.x;
1075:                bbox.height -= bbox.y;
1076:
1077:                return bbox;
1078:            }
1079:
1080:            /**
1081:             * Implementation helper. Computes the bounding box of the rectangle
1082:             * transformed by the input matrix.
1083:             *
1084:             * @param bbox the bounding box to which this node's bounds should be 
1085:             *        added.
1086:             * @param x the rectangle's x-axis origin
1087:             * @param y the rectangle's y-axis origin
1088:             * @param width the rectangle's width
1089:             * @param height the rectangle's height
1090:             * @param m the matrix transforming to the target coordinate space
1091:             *        into which the returned rectangle should be.
1092:             * @return the matrix from the input rectangle's coordinate space to 
1093:             *         the target coordinate space.
1094:             */
1095:            static Box addTransformedBBox(Box bbox, final float x,
1096:                    final float y, final float width, final float height,
1097:                    final Transform m) {
1098:
1099:                if (m == null) {
1100:                    return addBBox(bbox, x, y, width, height);
1101:                }
1102:
1103:                float tx = (float) (m.getComponent(0) * x + m.getComponent(2)
1104:                        * y + m.getComponent(4));
1105:                float ty = (float) (m.getComponent(1) * x + m.getComponent(3)
1106:                        * y + m.getComponent(5));
1107:
1108:                float dx1 = (float) (m.getComponent(0) * width);
1109:                float dy1 = (float) (m.getComponent(1) * width);
1110:
1111:                float dx2 = (float) (m.getComponent(2) * height);
1112:                float dy2 = (float) (m.getComponent(3) * height);
1113:
1114:                if (dx1 < 0) {
1115:                    tx += dx1;
1116:                    dx1 = -dx1;
1117:                }
1118:
1119:                if (dx2 > 0) {
1120:                    dx1 += dx2;
1121:                } else {
1122:                    dx1 -= dx2;
1123:                    tx += dx2;
1124:                }
1125:
1126:                if (dy1 < 0) {
1127:                    ty += dy1;
1128:                    dy1 = -dy1;
1129:                }
1130:
1131:                if (dy2 > 0) {
1132:                    dy1 += dy2;
1133:                } else {
1134:                    dy1 -= dy2;
1135:                    ty += dy2;
1136:                }
1137:
1138:                return addBBox(bbox, tx, ty, dx1, dy1);
1139:            }
1140:
1141:            /**
1142:             * @param bbox the bounding box to which this node's bounding box should be
1143:             *        appended. That bounding box is in the target coordinate space. It 
1144:             *        may be null, in which case this node should create a new one.
1145:             * @param t the transform from the node coordinate system to the coordinate
1146:             *        system into which the bounds should be computed.
1147:             * @return the bounding box of this node, in the target coordinate space, 
1148:             */
1149:            Box addNodeBBox(final Box bbox, final Transform t) {
1150:                return bbox;
1151:            }
1152:
1153:            /**
1154:             * Returns the <code>ModelNode</code>, if any, hit by the
1155:             * point at coordinate x/y. 
1156:             * 
1157:             * @param pt the x/y coordinate. Should never be null and be
1158:             *        of size two. If not, the behavior is unspecified.
1159:             *        The coordinates are in viewport space.
1160:             * @return the <tt>ModelNode</tt> hit at the given point or null
1161:             *         if none was hit.
1162:             */
1163:            public ModelNode nodeHitAt(final float[] pt) {
1164:                return null;
1165:            }
1166:
1167:            /**
1168:             * Returns the <code>ModelNode</code>, if any, hit by the
1169:             * point at coordinate x/y, in viewport space. The input 
1170:             * node, and all its siblings, are tested.
1171:             *
1172:             * @param node the first node on the set of nodes to test.
1173:             * @param pt the point which is hit
1174:             * @return the node hit at the given coordinate, or null if
1175:             *         no node was hit.
1176:             */
1177:            protected final ModelNode nodeHitAt(ModelNode node, final float[] pt) {
1178:                ModelNode hit = null;
1179:                while (node != null) {
1180:                    hit = node.nodeHitAt(pt);
1181:                    if (hit != null) {
1182:                        return hit;
1183:                    }
1184:                    node = node.prevSibling;
1185:                }
1186:                return null;
1187:            }
1188:
1189:            /**
1190:             * The node's URI base to use to resolve URI references
1191:             * If a URI base value was set on this node, then that value
1192:             * is returned. Otherwise, this method returns the parent's 
1193:             * URI base. If there is not URI base on this node and if there
1194:             * is not parent, then this method returns null.
1195:             *
1196:             * @return the node's URI base to use to resolve relative URI references.
1197:             */
1198:            protected String getURIBase() {
1199:                if (parent != null) {
1200:                    return parent.getURIBase();
1201:                }
1202:                return null;
1203:            }
1204:
1205:            /**
1206:             * Recomputes the requiredFeatures bit in the canRenderState bit mask.
1207:             *
1208:             * @param requiredFeatures if ConditionalProcessing.checkFeatures returns
1209:             * true, the bit is cleared. Otherwise, the bit is set.
1210:             */
1211:            final void computeCanRenderRequiredFeaturesBit(
1212:                    final String[] requiredFeatures) {
1213:                int oldCanRenderState = canRenderState;
1214:                if (requiredFeatures == null
1215:                        || ConditionalProcessing
1216:                                .checkFeatures(requiredFeatures)) {
1217:                    canRenderState &= CAN_RENDER_REQUIRED_FEATURES_MASK;
1218:                } else {
1219:                    canRenderState |= CAN_RENDER_REQUIRED_FEATURES_BIT;
1220:                }
1221:
1222:                propagateCanRenderState(oldCanRenderState, canRenderState);
1223:            }
1224:
1225:            /**
1226:             * Recomputes the requiredExtensions bit in the canRenderState bit mask.
1227:             *
1228:             * @param requiredExtensions if ConditionalProcessing.checkExtensions 
1229:             *        returns true, the bit is cleared. Otherwise, the bit is set.
1230:             */
1231:            final void computeCanRenderRequiredExtensionsBit(
1232:                    final String[] requiredExtensions) {
1233:                int oldCanRenderState = canRenderState;
1234:                if (requiredExtensions == null
1235:                        || ConditionalProcessing
1236:                                .checkExtensions(requiredExtensions)) {
1237:                    canRenderState &= CAN_RENDER_REQUIRED_EXTENSIONS_MASK;
1238:                } else {
1239:                    canRenderState |= CAN_RENDER_REQUIRED_EXTENSIONS_BIT;
1240:                }
1241:
1242:                propagateCanRenderState(oldCanRenderState, canRenderState);
1243:            }
1244:
1245:            /**
1246:             * Recomputes the systemLanguage bit in the canRenderState bit mask.
1247:             *
1248:             * @param systemLanguage if ConditionalProcessing.checkLanguage returns
1249:             * true, the bit is cleared. Otherwise, the bit is set.
1250:             */
1251:            final void computeCanRenderSystemLanguageBit(
1252:                    final String[] systemLanguage) {
1253:                int oldCanRenderState = canRenderState;
1254:                if (systemLanguage == null
1255:                        || ConditionalProcessing.checkLanguage(systemLanguage)) {
1256:                    canRenderState &= CAN_RENDER_SYSTEM_LANGUAGE_MASK;
1257:                } else {
1258:                    canRenderState |= CAN_RENDER_SYSTEM_LANGUAGE_BIT;
1259:                }
1260:
1261:                propagateCanRenderState(oldCanRenderState, canRenderState);
1262:            }
1263:
1264:            /**
1265:             * Recomputes the non-invertible transform bit in the canRenderState 
1266:             * bit mask.
1267:             *
1268:             * @param transform the transform which drives the non-invertible 
1269:             * transform bit. If non invertible, the bit is set. Otherwise, the 
1270:             * bit is cleared.
1271:             */
1272:            final void computeCanRenderTransformBit(final Transform transform) {
1273:                int oldCanRenderState = canRenderState;
1274:                if (transform == null || transform.isInvertible()) {
1275:                    canRenderState &= CAN_RENDER_NON_INVERTIBLE_TXF_MASK;
1276:                } else {
1277:                    canRenderState |= CAN_RENDER_NON_INVERTIBLE_TXF_BIT;
1278:                }
1279:
1280:                propagateCanRenderState(oldCanRenderState, canRenderState);
1281:            }
1282:
1283:            /**
1284:             * Recomputes the empty viewBox bit in the canRenderState 
1285:             * bit mask.
1286:             *
1287:             * @param viewBox the viewBox value which drives the empty viewBox
1288:             * bit. If null or if positive width/height, the bit is cleared. 
1289:             * Otherwise, the bit is set.
1290:             */
1291:            final void computeCanRenderEmptyViewBoxBit(final float[][] viewBox) {
1292:                int oldCanRenderState = canRenderState;
1293:                if (viewBox == null || (viewBox[1][0] > 0 && viewBox[2][0] > 0)) {
1294:                    canRenderState &= CAN_RENDER_EMPTY_VIEWBOX_MASK;
1295:                } else {
1296:                    canRenderState |= CAN_RENDER_EMPTY_VIEWBOX_BIT;
1297:                }
1298:
1299:                propagateCanRenderState(oldCanRenderState, canRenderState);
1300:            }
1301:
1302:            /**
1303:             * Recomputes the display bit in the canRenderState bit mask.
1304:             *
1305:             * @param display the display value. If true, the bit is cleared. If
1306:             * false, the bit is set.
1307:             */
1308:            final void computeCanRenderDisplayBit(final boolean display) {
1309:                int oldCanRenderState = canRenderState;
1310:                if (display) {
1311:                    canRenderState &= CAN_RENDER_DISPLAY_MASK;
1312:                } else {
1313:                    canRenderState |= CAN_RENDER_DISPLAY_BIT;
1314:                }
1315:
1316:                propagateCanRenderState(oldCanRenderState, canRenderState);
1317:            }
1318:
1319:            /**
1320:             * Recomputes the zero-width bit in the canRenderState bit mask.
1321:             *
1322:             * @param width the new width value. If zero or negative, the bit
1323:             * is set. Otherwise, the bit is cleared.
1324:             */
1325:            final void computeCanRenderWidthBit(final float width) {
1326:                int oldCanRenderState = canRenderState;
1327:                if (width > 0) {
1328:                    canRenderState &= CAN_RENDER_ZERO_WIDTH_MASK;
1329:                } else {
1330:                    canRenderState |= CAN_RENDER_ZERO_WIDTH_BIT;
1331:                }
1332:
1333:                propagateCanRenderState(oldCanRenderState, canRenderState);
1334:            }
1335:
1336:            /**
1337:             * Recomputes the zero-height bit in the canRenderState bit mask.
1338:             *
1339:             * @param height the new height value. If zero or negative, the bit
1340:             * is set. Otherwise, the bit is cleared.
1341:             */
1342:            final void computeCanRenderHeightBit(final float height) {
1343:                int oldCanRenderState = canRenderState;
1344:                if (height > 0) {
1345:                    canRenderState &= CAN_RENDER_ZERO_HEIGHT_MASK;
1346:                } else {
1347:                    canRenderState |= CAN_RENDER_ZERO_HEIGHT_BIT;
1348:                }
1349:
1350:                propagateCanRenderState(oldCanRenderState, canRenderState);
1351:            }
1352:
1353:            /**
1354:             * Recomputes the zero-fontSize bit in the canRenderState bit mask.
1355:             *
1356:             * @param fontSize the new fontSize value. If zero or negative, the bit
1357:             * is set. Otherwise, the bit is cleared.
1358:             */
1359:            final void computeCanRenderFontSizeBit(final float fontSize) {
1360:                int oldCanRenderState = canRenderState;
1361:                if (fontSize > 0) {
1362:                    canRenderState &= CAN_RENDER_ZERO_FONT_SIZE_MASK;
1363:                } else {
1364:                    canRenderState |= CAN_RENDER_ZERO_FONT_SIZE_BIT;
1365:                }
1366:
1367:                propagateCanRenderState(oldCanRenderState, canRenderState);
1368:            }
1369:
1370:            /**
1371:             * Recomputes the empty path bit in the canRenderStaet bit mask.
1372:             *
1373:             * @param path the value that determines the bit state. If null or
1374:             * if no segments, the bit is set. Otherwise, the bit is cleared.
1375:             */
1376:            final void computeCanRenderEmptyPathBit(final Path path) {
1377:                int oldCanRenderState = canRenderState;
1378:                if (path == null || path.getNumberOfSegments() == 0) {
1379:                    canRenderState |= CAN_RENDER_EMPTY_PATH_BIT;
1380:                } else {
1381:                    canRenderState &= CAN_RENDER_EMPTY_PATH_MASK;
1382:                }
1383:
1384:                propagateCanRenderState(oldCanRenderState, canRenderState);
1385:            }
1386:
1387:            /**
1388:             * By default, there is no node rendering.
1389:             *
1390:             * @return true if the node has some rendering of its own,
1391:             *         i.e., rendering beyond what its children or
1392:             *         expanded content render.
1393:             */
1394:            protected boolean hasNodeRendering() {
1395:                return false;
1396:            }
1397:
1398:            /**
1399:             * Clears the text layouts, if any exist. This is typically
1400:             * called when the font selection has changed and nodes such
1401:             * as <code>Text</code> should recompute their layouts.
1402:             * This should recursively call clearLayouts on children 
1403:             * node or expanded content, if any.
1404:             */
1405:            protected abstract void clearLayouts();
1406:
1407:            /**
1408:             * Clears the text layouts in the input node and all its
1409:             * siblings. Implementation helper.
1410:             *
1411:             * @param node the first node whose text layouts should be cleared.
1412:             */
1413:            void clearLayouts(ModelNode node) {
1414:                while (node != null) {
1415:                    node.clearLayouts();
1416:                    node = node.nextSibling;
1417:                }
1418:            }
1419:
1420:            /**
1421:             * @return true if this node is considered loaded. This is used
1422:             *         in support of progressive rendering.
1423:             */
1424:            public final boolean isLoaded() {
1425:                return loaded;
1426:            }
1427:
1428:            /**
1429:             * @param isLoaded the new loaded state
1430:             */
1431:            public void setLoaded(final boolean isLoaded) {
1432:                loaded = isLoaded;
1433:            }
1434:
1435:            /**
1436:             * @return true if the node needs to be fully loaded before it
1437:             *         can be painted
1438:             */
1439:            boolean getPaintNeedsLoad() {
1440:                return false;
1441:            }
1442:
1443:            /**
1444:             * Used to notify the <code>UpdateListener</code>, if any, of
1445:             * an upcoming node modification
1446:             *
1447:             */
1448:            protected void modifyingNode() {
1449:                UpdateListener updateListener = getUpdateListener();
1450:                if (updateListener != null) {
1451:                    updateListener.modifyingNode(this );
1452:                }
1453:            }
1454:
1455:            /**
1456:             * Used to notify the <code>UpdateListener</code>, if any, of
1457:             * an  change in a node's rendering
1458:             *
1459:             */
1460:            protected void modifyingNodeRendering() {
1461:                UpdateListener updateListener = getUpdateListener();
1462:                if (updateListener != null) {
1463:                    updateListener.modifyingNodeRendering(this );
1464:                }
1465:            }
1466:
1467:            /**
1468:             * Used to notify the <code>UpdateListener</code>, if any, of
1469:             * a completed node modification
1470:             *
1471:             */
1472:            protected void modifiedNode() {
1473:                UpdateListener updateListener = getUpdateListener();
1474:                if (updateListener != null) {
1475:                    updateListener.modifiedNode(this );
1476:                }
1477:            }
1478:
1479:            /**
1480:             * Used to notify the <code>UpdateListener</code>, if any, of
1481:             * a node insertion
1482:             *
1483:             * @param node the node which was just inserted
1484:             */
1485:            protected static void nodeInserted(final ModelNode node) {
1486:                UpdateListener updateListener = node.getUpdateListener();
1487:                if (updateListener != null) {
1488:                    updateListener.nodeInserted(node);
1489:                }
1490:            }
1491:
1492:            // JAVADOC COMMENT ELIDED
1493:            public void addEventListener(final String type,
1494:                    final EventListener listener, final boolean useCapture)
1495:                    throws DOMException {
1496:                ownerDocument.eventSupport.addEventListener(this , type,
1497:                        useCapture ? EventSupport.CAPTURE_PHASE
1498:                                : EventSupport.BUBBLE_PHASE, listener);
1499:
1500:            }
1501:
1502:            // JAVADOC COMMENT ELIDED
1503:            public void removeEventListener(final String type,
1504:                    final EventListener listener, final boolean useCapture)
1505:                    throws DOMException {
1506:                ownerDocument.eventSupport.removeEventListener(this , type,
1507:                        useCapture ? EventSupport.CAPTURE_PHASE
1508:                                : EventSupport.BUBBLE_PHASE, listener);
1509:            }
1510:
1511:            /**
1512:             * Delegates to the associated <code>EventSupport</code> class.
1513:             *
1514:             * @param evt the event to dispatch
1515:             */
1516:            public void dispatchEvent(final ModelEvent evt) {
1517:                ownerDocument.eventSupport.dispatchEvent(evt);
1518:            }
1519:
1520:            // =========================================================================
1521:            // Methods with default implementations which are typically overridden in
1522:            // extension.
1523:            // =========================================================================
1524:
1525:            /**
1526:             * To be overriddent by derived classes, such as TimedElementNode,
1527:             * if they need to perform special operations when hooked into the 
1528:             * document tree.
1529:             */
1530:            void onHookedInDocumentTree() {
1531:                // Clear the 'in document tree' can render bit
1532:                int oldCanRenderState = canRenderState;
1533:                canRenderState &= CAN_RENDER_IN_DOCUMENT_TREE_MASK;
1534:
1535:                // Set the parent's canRenderState bit
1536:                if (parent.canRenderState == 0) {
1537:                    canRenderState &= CAN_RENDER_PARENT_STATE_MASK;
1538:                } else {
1539:                    canRenderState |= CAN_RENDER_PARENT_STATE_BIT;
1540:                }
1541:                propagateCanRenderState(oldCanRenderState, canRenderState);
1542:
1543:                recomputeTransformState();
1544:                recomputeInheritedProperties();
1545:            }
1546:
1547:            /**
1548:             * To be overriddent by derived classes, such as TimedElementNode,
1549:             * if they need to perform special operations when unhooked from the 
1550:             * document tree.
1551:             */
1552:            void onUnhookedFromDocumentTree() {
1553:                // Set the 'in document tree' can render bit
1554:                int oldCanRenderState = canRenderState;
1555:                canRenderState |= CAN_RENDER_IN_DOCUMENT_TREE_BIT;
1556:
1557:                // Clear the parent's canRenderState bit
1558:                canRenderState &= CAN_RENDER_PARENT_STATE_MASK;
1559:
1560:                propagateCanRenderState(oldCanRenderState, canRenderState);
1561:
1562:                recomputeTransformState();
1563:                recomputeInheritedProperties();
1564:            }
1565:
1566:            /**
1567:             * Paints this node into the input <code>RenderGraphics</code>.
1568:             *
1569:             * @param rg the <tt>RenderGraphics</tt> where the node should paint itself
1570:             */
1571:            public void paint(final RenderGraphics rg) {
1572:                // By default, do not paint anything.
1573:            }
1574:
1575:            /**
1576:             * To be overridden by nodes which may have a rendering if they need
1577:             * to do something specific (e.g., notify their RenderingManager) when
1578:             * they have been rendered.
1579:             */
1580:            protected void nodeRendered() {
1581:                // By default, do nothing.
1582:            }
1583:
1584:            // =========================================================================
1585:            // Abstract method to override in extensions.
1586:            // =========================================================================
1587:
1588:            /**
1589:             * Utility method. Unhooks the children.
1590:             */
1591:            protected abstract void unhookChildrenQuiet();
1592:
1593:            /**
1594:             * Utility method. Unhooks the expanded content.
1595:             */
1596:            protected abstract void unhookExpandedQuiet();
1597:
1598:            /**
1599:             * @return a reference to the node's first child, or null if there
1600:             *         are no children.
1601:             */
1602:            public abstract ModelNode getFirstChildNode();
1603:
1604:            /**
1605:             * @return a reference to the node's last child, or null if there
1606:             *         are no children.
1607:             */
1608:            public abstract ModelNode getLastChildNode();
1609:
1610:            /**
1611:             * Some node types (such as <code>ElementNodeProxy</code>) have
1612:             * expanded children that they compute in some specific
1613:             * way depending on the implementation.     
1614:             *
1615:             * @return a reference to the node's first expanded child, or null if there
1616:             *         are no expanded children. This forces the computation of expanded
1617:             *         content if needed.
1618:             */
1619:            abstract ModelNode getFirstExpandedChild();
1620:
1621:            /**
1622:             * Some node types (such as <code>ElementNodeProxy</code>) have
1623:             * expanded children that they compute in some specific
1624:             * way depending on the implementation.     
1625:             *
1626:             * @return a reference to the node's first expanded child, or null if there
1627:             *         are no expanded children. This forces the computation of expanded
1628:             *         content if needed.
1629:             */
1630:            abstract ModelNode getFirstComputedExpandedChild();
1631:
1632:            /**
1633:             * Some node types (such as <code>ElementNodeProxy</code>) have
1634:             * expanded children that they compute in some specific
1635:             * way depending on the implementation.     
1636:             *
1637:             * @return a reference to the node's last expanded child, or null if there
1638:             *         are no expanded children. This forces the computation of expanded
1639:             *         content if needed.
1640:             */
1641:            abstract ModelNode getLastExpandedChild();
1642:
1643:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.