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: package com.sun.perseus.model;
0027:
0028: import org.w3c.dom.DOMException;
0029:
0030: import org.w3c.dom.svg.SVGRect;
0031: import org.w3c.dom.svg.SVGRGBColor;
0032: import org.w3c.dom.svg.SVGLocatableElement;
0033:
0034: import com.sun.perseus.j2d.GraphicsProperties;
0035: import com.sun.perseus.j2d.Transform;
0036:
0037: import com.sun.perseus.util.SVGConstants;
0038:
0039: import com.sun.perseus.j2d.RGB;
0040: import com.sun.perseus.j2d.PaintDef;
0041: import com.sun.perseus.j2d.PaintTarget;
0042: import com.sun.perseus.j2d.PaintServer;
0043:
0044: /**
0045: * <code>CompositeGraphicsNode</code> is the base class for all nodes which are
0046: * both composites (i.e., they can have children) and have graphic properties
0047: * (such as <code>fill</code> or <code>stroke</code>).
0048: *
0049: * @version $Id: CompositeGraphicsNode.java,v 1.16 2006/06/29 10:47:29 ln156897 Exp $
0050: */
0051: public abstract class CompositeGraphicsNode extends ElementNode
0052: implements GraphicsNode, PaintTarget, SVGLocatableElement {
0053: // =======================================================================
0054: // Constants used for packing and unpacking data in the pack member
0055: // =======================================================================
0056: protected static final int FONT_STYLE_MASK = 0x60000000; /* 30-29 */
0057: protected static final int FONT_WEIGHT_MASK = 0x1E000000; /* 28-27-26-25 */
0058: protected static final int TEXT_ANCHOR_MASK = 0x01800000; /* 24-23 */
0059: protected static final int STROKE_OPACITY_MASK = 0x007F8000; /* 22-21-20-19-18-17-16-15 */
0060: protected static final int FILL_OPACITY_MASK = 0x00007F80; /* 14-13-12-11-10-09-08-07 */
0061: protected static final int FILL_RULE_MASK = 0x00000040; /* 06 */
0062: protected static final int STROKE_LINE_CAP_MASK = 0x00000030; /* 05-04 */
0063: protected static final int STROKE_LINE_JOIN_MASK = 0x0000000C; /* 03-02 */
0064: protected static final int VISIBILITY_MASK = 0x00000002; /* 01 */
0065: protected static final int DISPLAY_MASK = 0x00000001; /* 00 */
0066:
0067: // =======================================================================
0068: // Constants used for packing and unpacking data in the pack2 member
0069: // =======================================================================
0070: protected static final int OPACITY_MASK = 0x000000FF; /* 7-6-5-4-3-2-1-0 */
0071:
0072: protected static final int FONT_STYLE_NORMAL_IMPL = 0x00000000;
0073: protected static final int FONT_STYLE_ITALIC_IMPL = 0x40000000;
0074: protected static final int FONT_STYLE_OBLIQUE_IMPL = 0x60000000;
0075:
0076: protected static final int FONT_WEIGHT_100_IMPL = 0x00000000;
0077: protected static final int FONT_WEIGHT_200_IMPL = 0x02000000;
0078: protected static final int FONT_WEIGHT_300_IMPL = 0x04000000;
0079: protected static final int FONT_WEIGHT_400_IMPL = 0x06000000;
0080: protected static final int FONT_WEIGHT_500_IMPL = 0x08000000;
0081: protected static final int FONT_WEIGHT_600_IMPL = 0x0A000000;
0082: protected static final int FONT_WEIGHT_700_IMPL = 0x0C000000;
0083: protected static final int FONT_WEIGHT_800_IMPL = 0x0E000000;
0084: protected static final int FONT_WEIGHT_900_IMPL = 0x10000000;
0085: protected static final int FONT_WEIGHT_LIGHTER_IMPL = 0x12000000;
0086: protected static final int FONT_WEIGHT_BOLDER_IMPL = 0x14000000;
0087:
0088: protected static final int TEXT_ANCHOR_MIDDLE_IMPL = 0x00000000;
0089: protected static final int TEXT_ANCHOR_START_IMPL = 0x00800000;
0090: protected static final int TEXT_ANCHOR_END_IMPL = 0x01000000;
0091:
0092: protected static final int CAP_BUTT_IMPL = 0x00000000;
0093: protected static final int CAP_ROUND_IMPL = 0x00000010;
0094: protected static final int CAP_SQUARE_IMPL = 0x00000020;
0095:
0096: protected static final int JOIN_MITER_IMPL = 0x00000000;
0097: protected static final int JOIN_ROUND_IMPL = 0x00000004;
0098: protected static final int JOIN_BEVEL_IMPL = 0x00000008;
0099:
0100: // ====================================================================
0101: // Property values
0102: // ====================================================================
0103: /**
0104: * The current color. The fill and stroke colors may be
0105: * relative to the current color
0106: */
0107: protected RGB color = INITIAL_COLOR;
0108:
0109: /**
0110: * The fill paint used to fill this node
0111: */
0112: protected PaintServer fill = INITIAL_FILL;
0113:
0114: /**
0115: * The stroke paint used to stroke the outline of
0116: * this ShapeNode
0117: */
0118: protected PaintServer stroke = INITIAL_STROKE;
0119:
0120: /**
0121: * The stroke width
0122: */
0123: protected float strokeWidth = INITIAL_STROKE_WIDTH;
0124:
0125: /**
0126: * The stroke miter limit
0127: */
0128: protected float strokeMiterLimit = INITIAL_STROKE_MITER_LIMIT;
0129:
0130: /**
0131: * The stroke dash array
0132: */
0133: protected float[] strokeDashArray = INITIAL_STROKE_DASH_ARRAY;
0134:
0135: /**
0136: * The stroke dash offset
0137: */
0138: protected float strokeDashOffset = INITIAL_STROKE_DASH_OFFSET;
0139:
0140: //
0141: // Property pack
0142: //
0143: // fontStyle: 3 styles, 2 bits
0144: // fontWeight: 9 weights, 4 bits
0145: // textAnchor 3 values, 2 bits
0146: // strokeOpacity: 8 bits [0-255]
0147: // fillOpacity: 8 bits [0-255]
0148: // fillRule: 1 bits
0149: // strokeLineCap: 3 values, 2 bits
0150: // strokeLineJoin 3 values, 2 bits
0151: // visibility: 2 values, 1 bit
0152: // display: 2 values, 1 bit
0153: // Total: 31 bits
0154: //
0155: // Encoding:
0156: //
0157: // fontStyle: 30-29
0158: // fontWeight: 28-27-26-25
0159: // textAnchor: 24-23
0160: // strokeOpacity: 22-21-20-19-18-17-16-15
0161: // fillOpacity: 14-13-12-11-10-09-08-07
0162: // fillRule: 06
0163: // strokeLineCap: 05-04
0164: // strokeLineJoin: 03-02
0165: // visibility: 01
0166: // display: 00
0167: //
0168: protected int pack = INITIAL_PACK;
0169:
0170: protected static final int INITIAL_FONT_STYLE_IMPL = FONT_STYLE_NORMAL_IMPL;
0171: protected static final int INITIAL_FONT_WEIGHT_IMPL = FONT_WEIGHT_400_IMPL;
0172: protected static final int INITIAL_TEXT_ANCHOR_IMPL = TEXT_ANCHOR_START_IMPL;
0173: protected static final int INITIAL_STROKE_OPACITY_IMPL = 200 << 15;
0174: protected static final int INITIAL_FILL_OPACITY_IMPL = 200 << 7;
0175: protected static final int INITIAL_FILL_RULE_IMPL = FILL_RULE_MASK;
0176: protected static final int INITIAL_STROKE_LINE_CAP_IMPL = CAP_BUTT_IMPL;
0177: protected static final int INITIAL_STROKE_LINE_JOIN_IMPL = JOIN_MITER_IMPL;
0178: protected static final int INITIAL_VISIBILITY_IMPL = 0x2;
0179: protected static final int INITIAL_DISPLAY_IMPL = 0x1;
0180: protected static final int INITIAL_PACK = INITIAL_FONT_STYLE_IMPL
0181: | INITIAL_FONT_WEIGHT_IMPL | INITIAL_TEXT_ANCHOR_IMPL
0182: | INITIAL_STROKE_OPACITY_IMPL | INITIAL_FILL_OPACITY_IMPL
0183: | INITIAL_FILL_RULE_IMPL | INITIAL_STROKE_LINE_CAP_IMPL
0184: | INITIAL_STROKE_LINE_JOIN_IMPL | INITIAL_VISIBILITY_IMPL
0185: | INITIAL_DISPLAY_IMPL;
0186:
0187: //
0188: // Property pack2
0189: //
0190: // opacity: 8 bits [0-255]
0191: // Total: 8 bits
0192: //
0193: // Encoding:
0194: //
0195: // opacity: 07-06-05-04-03-02-01-00
0196: //
0197: protected int pack2 = INITIAL_PACK2;
0198:
0199: protected static final int INITIAL_OPACITY_IMPL = 200;
0200: protected static final int INITIAL_PACK2 = INITIAL_OPACITY_IMPL;
0201:
0202: // ====================================================================
0203: // Property value types (inherited, relative, none, specific)
0204: // ====================================================================
0205:
0206: /**
0207: * Markers are used to keep track of inherited properties, color relative
0208: * properties and bolder/lighter font weights.
0209: *
0210: * 0-20 : property inheritance
0211: * 21-22 : color relative
0212: * 23 : is bolder marker
0213: * 24 : is lighter marker
0214: */
0215: protected int markers = DEFAULT_INHERITANCE
0216: | TextNode.DEFAULT_INHERITANCE | DEFAULT_COLOR_RELATIVE;
0217:
0218: // ====================================================================
0219: // ModelNode Implementation
0220: // ====================================================================
0221:
0222: /**
0223: * Cached Transform. May point to the parent transform.
0224: */
0225: protected Transform txf = null;
0226:
0227: /**
0228: * Cached inverse transform. May point to the parent inverse transform.
0229: */
0230: protected Transform inverseTxf = null;
0231:
0232: /**
0233: * Constructor.
0234: *
0235: * @param ownerDocument this element's owner <code>DocumentNode</code>
0236: */
0237: public CompositeGraphicsNode(final DocumentNode ownerDocument) {
0238: super (ownerDocument);
0239:
0240: // By default, a CompositeGraphicsNode is renderable
0241: canRenderState &= CAN_RENDER_RENDERABLE_MASK;
0242: }
0243:
0244: /**
0245: * A <code>CompositeGraphicsNode</code> contributes to its parent bounding
0246: * box only if its display property is turned on.
0247: *
0248: * @return true if the node's bounding box should be accounted for.
0249: */
0250: protected boolean contributeBBox() {
0251: return (pack & DISPLAY_MASK) != 0;
0252: }
0253:
0254: // JAVADOC COMMENT ELIDED
0255: public SVGRect getBBox() {
0256: return null;
0257: }
0258:
0259: // JAVADOC COMMENT ELIDED
0260: public SVGRect getScreenBBox() {
0261: return null;
0262: }
0263:
0264: /**
0265: * Returns the value of the given Object-valued property.
0266: *
0267: * @return the value of the given Object-valued property.
0268: */
0269: protected Object getPropertyState(final int propertyIndex) {
0270: switch (propertyIndex) {
0271: case PROPERTY_FILL:
0272: return fill;
0273: case PROPERTY_STROKE:
0274: return stroke;
0275: case PROPERTY_COLOR:
0276: return color;
0277: case PROPERTY_STROKE_DASH_ARRAY:
0278: return strokeDashArray;
0279: default:
0280: return super .getPropertyState(propertyIndex);
0281: }
0282: }
0283:
0284: /**
0285: * Returns the value of the given float-valued property.
0286: *
0287: * @return the value of the given property.
0288: */
0289: protected float getFloatPropertyState(final int propertyIndex) {
0290: switch (propertyIndex) {
0291: case PROPERTY_STROKE_WIDTH:
0292: return strokeWidth;
0293: case PROPERTY_STROKE_MITER_LIMIT:
0294: return strokeMiterLimit;
0295: case PROPERTY_STROKE_DASH_OFFSET:
0296: return strokeDashOffset;
0297: default:
0298: return super .getFloatPropertyState(propertyIndex);
0299: }
0300: }
0301:
0302: /**
0303: * Returns the value for the given packed property.
0304: *
0305: * @return the value for the given property.
0306: */
0307: protected int getPackedPropertyState(final int propertyIndex) {
0308: switch (propertyIndex) {
0309: case GraphicsNode.PROPERTY_FILL_RULE:
0310: return pack & CompositeGraphicsNode.FILL_RULE_MASK;
0311: case GraphicsNode.PROPERTY_STROKE_LINE_JOIN:
0312: return pack & CompositeGraphicsNode.STROKE_LINE_JOIN_MASK;
0313: case GraphicsNode.PROPERTY_STROKE_LINE_CAP:
0314: return pack & CompositeGraphicsNode.STROKE_LINE_CAP_MASK;
0315: case GraphicsNode.PROPERTY_DISPLAY:
0316: return pack & CompositeGraphicsNode.DISPLAY_MASK;
0317: case GraphicsNode.PROPERTY_VISIBILITY:
0318: return pack & CompositeGraphicsNode.VISIBILITY_MASK;
0319: case GraphicsNode.PROPERTY_FILL_OPACITY:
0320: return pack & CompositeGraphicsNode.FILL_OPACITY_MASK;
0321: case GraphicsNode.PROPERTY_STROKE_OPACITY:
0322: return pack & CompositeGraphicsNode.STROKE_OPACITY_MASK;
0323: case GraphicsNode.PROPERTY_OPACITY:
0324: return pack2 & CompositeGraphicsNode.OPACITY_MASK;
0325: default:
0326: return super .getPackedPropertyState(propertyIndex);
0327: }
0328: }
0329:
0330: /**
0331: * Sets the computed value of the given Object-valued property.
0332: *
0333: * @param propertyIndex the property index
0334: * @param propertyValue the computed value of the property.
0335: */
0336: protected void setPropertyState(final int propertyIndex,
0337: final Object propertyValue) {
0338: switch (propertyIndex) {
0339: case PROPERTY_FILL:
0340: setComputedFill((PaintServer) propertyValue);
0341: break;
0342: case PROPERTY_STROKE:
0343: setComputedStroke((PaintServer) propertyValue);
0344: break;
0345: case PROPERTY_COLOR:
0346: setComputedColor((RGB) propertyValue);
0347: break;
0348: case PROPERTY_STROKE_DASH_ARRAY:
0349: setComputedStrokeDashArray((float[]) propertyValue);
0350: break;
0351: default:
0352: super .setPropertyState(propertyIndex, propertyValue);
0353: break;
0354: }
0355: }
0356:
0357: /**
0358: * Sets the computed value of the given float-valued property.
0359: *
0360: * @param propertyIndex the property index
0361: * @param propertyValue the computed value of the property.
0362: */
0363: protected void setFloatPropertyState(final int propertyIndex,
0364: final float propertyValue) {
0365: switch (propertyIndex) {
0366: case PROPERTY_STROKE_WIDTH:
0367: setComputedStrokeWidth(propertyValue);
0368: break;
0369: case PROPERTY_STROKE_MITER_LIMIT:
0370: setComputedStrokeMiterLimit(propertyValue);
0371: break;
0372: case PROPERTY_STROKE_DASH_OFFSET:
0373: setComputedStrokeDashOffset(propertyValue);
0374: break;
0375: default:
0376: super .setFloatPropertyState(propertyIndex, propertyValue);
0377: break;
0378: }
0379: }
0380:
0381: /**
0382: * Sets the computed value of the given packed property.
0383: *
0384: * @param propertyIndex the property index
0385: * @param propertyValue the computed value of the property.
0386: */
0387: protected void setPackedPropertyState(final int propertyIndex,
0388: final int propertyValue) {
0389: switch (propertyIndex) {
0390: case GraphicsNode.PROPERTY_FILL_RULE:
0391: if (propertyValue == 0) {
0392: setComputedFillRule(WIND_EVEN_ODD);
0393: } else {
0394: setComputedFillRule(WIND_NON_ZERO);
0395: }
0396: break;
0397: case GraphicsNode.PROPERTY_STROKE_LINE_JOIN:
0398: switch (propertyValue) {
0399: case CompositeGraphicsNode.JOIN_MITER_IMPL:
0400: setComputedStrokeLineJoin(JOIN_MITER);
0401: break;
0402: case CompositeGraphicsNode.JOIN_ROUND_IMPL:
0403: setComputedStrokeLineJoin(JOIN_ROUND);
0404: break;
0405: case CompositeGraphicsNode.JOIN_BEVEL_IMPL:
0406: default:
0407: setComputedStrokeLineJoin(JOIN_BEVEL);
0408: break;
0409: }
0410: break;
0411: case GraphicsNode.PROPERTY_STROKE_LINE_CAP:
0412: switch (propertyValue) {
0413: case CompositeGraphicsNode.CAP_BUTT_IMPL:
0414: setComputedStrokeLineCap(CAP_BUTT);
0415: break;
0416: case CompositeGraphicsNode.CAP_ROUND_IMPL:
0417: setComputedStrokeLineCap(CAP_ROUND);
0418: break;
0419: case CompositeGraphicsNode.CAP_SQUARE_IMPL:
0420: default:
0421: setComputedStrokeLineCap(CAP_SQUARE);
0422: break;
0423: }
0424: break;
0425: case GraphicsNode.PROPERTY_DISPLAY:
0426: if (propertyValue != 0) {
0427: setComputedDisplay(true);
0428: } else {
0429: setComputedDisplay(false);
0430: }
0431: break;
0432: case GraphicsNode.PROPERTY_VISIBILITY:
0433: if (propertyValue != 0) {
0434: setComputedVisibility(true);
0435: } else {
0436: setComputedVisibility(false);
0437: }
0438: break;
0439: case GraphicsNode.PROPERTY_FILL_OPACITY:
0440: setComputedFillOpacity((propertyValue >> 7) / 200.0f);
0441: break;
0442: case GraphicsNode.PROPERTY_STROKE_OPACITY:
0443: setComputedStrokeOpacity((propertyValue >> 15) / 200.0f);
0444: break;
0445: case GraphicsNode.PROPERTY_OPACITY:
0446: setComputedOpacity(propertyValue / 200.0f);
0447: break;
0448: default:
0449: super .setPackedPropertyState(propertyIndex, propertyValue);
0450: break;
0451: }
0452: }
0453:
0454: /**
0455: * Checks the state of the Object-valued property.
0456: *
0457: * @param propertyIndex the property index
0458: * @param propertyValue the computed value of the property.
0459: */
0460: protected boolean isPropertyState(final int propertyIndex,
0461: final Object propertyValue) {
0462: switch (propertyIndex) {
0463: case GraphicsNode.PROPERTY_FILL:
0464: return fill == propertyValue;
0465: case GraphicsNode.PROPERTY_STROKE:
0466: return stroke == propertyValue;
0467: case GraphicsNode.PROPERTY_COLOR:
0468: return color == propertyValue;
0469: case GraphicsNode.PROPERTY_STROKE_DASH_ARRAY:
0470: return strokeDashArray == propertyValue;
0471: default:
0472: return super .isPropertyState(propertyIndex, propertyValue);
0473: }
0474: }
0475:
0476: /**
0477: * Checks the state of the float property value.
0478: *
0479: * @param propertyIndex the property index
0480: * @param propertyValue the computed value of the property.
0481: */
0482: protected boolean isFloatPropertyState(final int propertyIndex,
0483: final float propertyValue) {
0484: switch (propertyIndex) {
0485: case GraphicsNode.PROPERTY_STROKE_WIDTH:
0486: return strokeWidth == propertyValue;
0487: case GraphicsNode.PROPERTY_STROKE_MITER_LIMIT:
0488: return strokeMiterLimit == propertyValue;
0489: case GraphicsNode.PROPERTY_STROKE_DASH_OFFSET:
0490: return strokeDashOffset == propertyValue;
0491: default:
0492: return super .isFloatPropertyState(propertyIndex,
0493: propertyValue);
0494: }
0495: }
0496:
0497: /**
0498: * Checks the state of the packed property value.
0499: *
0500: * @param propertyIndex the property index
0501: * @param propertyValue the computed value of the property.
0502: */
0503: protected boolean isPackedPropertyState(final int propertyIndex,
0504: final int propertyValue) {
0505: switch (propertyIndex) {
0506: case GraphicsNode.PROPERTY_FILL_RULE:
0507: return (propertyValue == (pack & CompositeGraphicsNode.FILL_RULE_MASK));
0508: case GraphicsNode.PROPERTY_STROKE_LINE_JOIN:
0509: return (propertyValue == (pack & CompositeGraphicsNode.STROKE_LINE_JOIN_MASK));
0510: case GraphicsNode.PROPERTY_STROKE_LINE_CAP:
0511: return (propertyValue == (pack & CompositeGraphicsNode.STROKE_LINE_CAP_MASK));
0512: case GraphicsNode.PROPERTY_DISPLAY:
0513: return (propertyValue == (pack & CompositeGraphicsNode.DISPLAY_MASK));
0514: case GraphicsNode.PROPERTY_VISIBILITY:
0515: return (propertyValue == (pack & CompositeGraphicsNode.VISIBILITY_MASK));
0516: case GraphicsNode.PROPERTY_FILL_OPACITY:
0517: return (propertyValue == (pack & CompositeGraphicsNode.FILL_OPACITY_MASK));
0518: case GraphicsNode.PROPERTY_STROKE_OPACITY:
0519: return (propertyValue == (pack & CompositeGraphicsNode.STROKE_OPACITY_MASK));
0520: case GraphicsNode.PROPERTY_OPACITY:
0521: return (propertyValue == (pack2 & CompositeGraphicsNode.OPACITY_MASK));
0522: default:
0523: return super .isPackedPropertyState(propertyIndex,
0524: propertyValue);
0525: }
0526: }
0527:
0528: /**
0529: * Recomputes all inherited properties.
0530: */
0531: void recomputeInheritedProperties() {
0532: ModelNode p = ownerDocument;
0533: if (parent != null) {
0534: p = parent;
0535: }
0536: recomputePropertyState(PROPERTY_FILL, p
0537: .getPropertyState(PROPERTY_FILL));
0538: recomputePropertyState(PROPERTY_STROKE, p
0539: .getPropertyState(PROPERTY_STROKE));
0540: recomputePropertyState(PROPERTY_COLOR, p
0541: .getPropertyState(PROPERTY_COLOR));
0542: recomputePackedPropertyState(PROPERTY_FILL_RULE, p
0543: .getPackedPropertyState(PROPERTY_FILL_RULE));
0544: recomputeFloatPropertyState(PROPERTY_STROKE_WIDTH, p
0545: .getFloatPropertyState(PROPERTY_STROKE_WIDTH));
0546: recomputePackedPropertyState(PROPERTY_STROKE_LINE_JOIN, p
0547: .getPackedPropertyState(PROPERTY_STROKE_LINE_JOIN));
0548: recomputePackedPropertyState(PROPERTY_STROKE_LINE_CAP, p
0549: .getPackedPropertyState(PROPERTY_STROKE_LINE_CAP));
0550: recomputeFloatPropertyState(PROPERTY_STROKE_MITER_LIMIT, p
0551: .getFloatPropertyState(PROPERTY_STROKE_MITER_LIMIT));
0552: recomputePropertyState(PROPERTY_STROKE_DASH_ARRAY, p
0553: .getPropertyState(PROPERTY_STROKE_DASH_ARRAY));
0554: recomputeFloatPropertyState(PROPERTY_STROKE_DASH_OFFSET, p
0555: .getFloatPropertyState(PROPERTY_STROKE_DASH_OFFSET));
0556: recomputePackedPropertyState(PROPERTY_DISPLAY, p
0557: .getPackedPropertyState(PROPERTY_DISPLAY));
0558: recomputePackedPropertyState(PROPERTY_VISIBILITY, p
0559: .getPackedPropertyState(PROPERTY_VISIBILITY));
0560: recomputePackedPropertyState(PROPERTY_FILL_OPACITY, p
0561: .getPackedPropertyState(PROPERTY_FILL_OPACITY));
0562: recomputePackedPropertyState(PROPERTY_STROKE_OPACITY, p
0563: .getPackedPropertyState(PROPERTY_STROKE_OPACITY));
0564: recomputePackedPropertyState(PROPERTY_OPACITY, p
0565: .getPackedPropertyState(PROPERTY_OPACITY));
0566: }
0567:
0568: /**
0569: * Recomputes the given Object-valued property's state given the
0570: * new parent property.
0571: *
0572: * @param propertyIndex index for the property whose value is changing.
0573: * @param parentPropertyValue the value that children of this node should
0574: * now inherit.
0575: *
0576: */
0577: protected void recomputePropertyState(final int propertyIndex,
0578: final Object parentPropertyValue) {
0579: // We do not need to recompute the property value if:
0580: // - the property is _not_ inherited
0581: // or
0582: // - the property is inherited by the new parent property computed value
0583: // is the same as the current value.
0584: if (!isInherited(propertyIndex)
0585: || isPropertyState(propertyIndex, parentPropertyValue)) {
0586: // If the property is color relative, the propagation happens
0587: // through the color property changes. This means that with
0588: // currentColor, we inherit the computed value, not the specified
0589: // currentColor indirection.
0590: return;
0591: }
0592:
0593: setPropertyState(propertyIndex, parentPropertyValue);
0594: propagatePropertyState(propertyIndex, parentPropertyValue);
0595: }
0596:
0597: /**
0598: * Recomputes the given float-valued property's state given the new parent
0599: * property.
0600: *
0601: * @param propertyIndex index for the property whose value is changing.
0602: * @param parentPropertyValue the value that children of this node should
0603: * now inherit.
0604: *
0605: */
0606: protected void recomputeFloatPropertyState(final int propertyIndex,
0607: final float parentPropertyValue) {
0608: // We do not need to recompute the property value if:
0609: // - the property is _not_ inherited
0610: // or
0611: // - the property is inherited by the new parent property computed value
0612: // is the same as the current value.
0613: if (!isInherited(propertyIndex)
0614: || isFloatPropertyState(propertyIndex,
0615: parentPropertyValue)) {
0616: // If the property is color relative, the propagation happens
0617: // through the color property changes. This means that with
0618: // currentColor, we inherit the computed value, not the specified
0619: // currentColor indirection.
0620: return;
0621: }
0622:
0623: setFloatPropertyState(propertyIndex, parentPropertyValue);
0624: propagateFloatPropertyState(propertyIndex, parentPropertyValue);
0625: }
0626:
0627: /**
0628: * Recomputes the given packed property's state given the new parent
0629: * property.
0630: *
0631: * @param propertyIndex index for the property whose value is changing.
0632: * @param parentPropertyValue the value that children of this node should
0633: * now inherit.
0634: *
0635: */
0636: protected void recomputePackedPropertyState(
0637: final int propertyIndex, final int parentPropertyValue) {
0638: // We do not need to recompute the property value if:
0639: // - the property is _not_ inherited
0640: // or
0641: // - the property is inherited by the new parent property computed value
0642: // is the same as the current value.
0643: if (!isInherited(propertyIndex)
0644: || isPackedPropertyState(propertyIndex,
0645: parentPropertyValue)) {
0646: // If the property is color relative, the propagation happens
0647: // through the color property changes. This means that with
0648: // currentColor, we inherit the computed value, not the specified
0649: // currentColor indirection.
0650: return;
0651: }
0652:
0653: setPackedPropertyState(propertyIndex, parentPropertyValue);
0654: propagatePackedPropertyState(propertyIndex, parentPropertyValue);
0655: }
0656:
0657: /**
0658: * Called when the computed value of the given Object-valued property
0659: * has changed.
0660: *
0661: * @param propertyIndex index for the property whose value has changed.
0662: * @param parentPropertyValue the value that children of this node should
0663: * now inherit.
0664: *
0665: */
0666: protected void propagatePropertyState(final int propertyIndex,
0667: final Object parentPropertyValue) {
0668: // Propagate to proxies.
0669: if (firstProxy != null) {
0670: ElementNodeProxy proxy = firstProxy;
0671: while (proxy != null) {
0672: ((CompositeGraphicsNodeProxy) proxy)
0673: .proxiedPropertyStateChange(propertyIndex,
0674: parentPropertyValue);
0675: proxy = proxy.nextProxy;
0676: }
0677: }
0678:
0679: // Propagate to regular children.
0680: ModelNode node = getFirstChildNode();
0681: while (node != null) {
0682: node.recomputePropertyState(propertyIndex,
0683: parentPropertyValue);
0684: node = node.nextSibling;
0685: }
0686: }
0687:
0688: /**
0689: * Called when the computed value of the given float-valued property has
0690: * changed.
0691: *
0692: * @param propertyIndex index for the property whose value has changed.
0693: * @param parentPropertyValue the value that children of this node should
0694: * now inherit.
0695: *
0696: */
0697: protected void propagateFloatPropertyState(final int propertyIndex,
0698: final float parentPropertyValue) {
0699: // Propagate to proxies.
0700: if (firstProxy != null) {
0701: ElementNodeProxy proxy = firstProxy;
0702: while (proxy != null) {
0703: ((CompositeGraphicsNodeProxy) proxy)
0704: .proxiedFloatPropertyStateChange(propertyIndex,
0705: parentPropertyValue);
0706: proxy = proxy.nextProxy;
0707: }
0708: }
0709:
0710: // Propagate to regular children.
0711: ModelNode node = getFirstChildNode();
0712: while (node != null) {
0713: node.recomputeFloatPropertyState(propertyIndex,
0714: parentPropertyValue);
0715: node = node.nextSibling;
0716: }
0717: }
0718:
0719: /**
0720: * Called when the computed value of the given packed property has changed.
0721: *
0722: * @param propertyIndex index for the property whose value has changed.
0723: * @param parentPropertyValue the value that children of this node should
0724: * now inherit.
0725: *
0726: */
0727: protected void propagatePackedPropertyState(
0728: final int propertyIndex, final int parentPropertyValue) {
0729: // Propagate to proxies.
0730: if (firstProxy != null) {
0731: ElementNodeProxy proxy = firstProxy;
0732: while (proxy != null) {
0733: ((CompositeGraphicsNodeProxy) proxy)
0734: .proxiedPackedPropertyStateChange(
0735: propertyIndex, parentPropertyValue);
0736: proxy = proxy.nextProxy;
0737: }
0738: }
0739:
0740: // Propagate to regular children.
0741: ModelNode node = getFirstChildNode();
0742: while (node != null) {
0743: node.recomputePackedPropertyState(propertyIndex,
0744: parentPropertyValue);
0745: node = node.nextSibling;
0746: }
0747: }
0748:
0749: /**
0750: * Recomputes the transform cache, if one exists. This should recursively
0751: * call recomputeTransformState on children node or expanded content, if
0752: * any.
0753: *
0754: * By default, because a ModelNode has no transform and no cached transform,
0755: * this only does a pass down.
0756: *
0757: * @param parentTransform the Transform applied to this node's parent.
0758: */
0759: protected void recomputeTransformState(
0760: final Transform parentTransform) {
0761: txf = appendTransform(parentTransform, txf);
0762: computeCanRenderTransformBit(txf);
0763: inverseTxf = null;
0764: // inverseTxf = computeInverseTransform(txf, parentTransform,
0765: // inverseTxf);
0766: recomputeTransformState(txf, getFirstChildNode());
0767: }
0768:
0769: /**
0770: * @return this node's cached transform.
0771: */
0772: public Transform getTransformState() {
0773: return txf;
0774: }
0775:
0776: /**
0777: * @return this node's cached inverse transform.
0778: */
0779: Transform getInverseTransformState() {
0780: if (((canRenderState & CAN_RENDER_NON_INVERTIBLE_TXF_BIT) == 0)) {
0781: if (inverseTxf == null) {
0782: // If there is a parent, check if this node's transform is the
0783: // same as the parent's in which cahse
0784: if (parent != null && txf == parent.getTransformState()) {
0785: inverseTxf = parent.getInverseTransformState();
0786: } else {
0787: inverseTxf = new Transform(null);
0788: try {
0789: inverseTxf = (Transform) txf
0790: .inverse(inverseTxf);
0791: } catch (Exception e) {
0792: // If we get an exception, then we have a real error
0793: // condition, because we just checked that the
0794: // transform was invertible.
0795: throw new Error();
0796: }
0797: }
0798: }
0799: } else {
0800: inverseTxf = null;
0801: }
0802: return inverseTxf;
0803: }
0804:
0805: /**
0806: * Check if the property is inherited.
0807: *
0808: * @param propertyIndex the index of the property for which the
0809: * inherited state should be returned.
0810: * @return true if the input property is inherited. False
0811: * otherwise
0812: */
0813: public final boolean isInherited(final int propertyIndex) {
0814: return isMarkerSet(propertyIndex);
0815: }
0816:
0817: /**
0818: * Sets the given Object-valued property's inheritance status
0819: * @param propertyIndex the index for the property whose inherited state
0820: * is set
0821: * @param inherit the new property's state
0822: */
0823: public void setInherited(final int propertyIndex,
0824: final boolean inherit) {
0825: if (isInherited(propertyIndex) == inherit) {
0826: return;
0827: }
0828: modifyingNode();
0829: setInheritedQuiet(propertyIndex, inherit);
0830:
0831: if (inherit) {
0832: // The property is now inherited. We store the inherited
0833: // value on the node, which means we keep the computed value
0834: // on the node.
0835: Object inheritedValue = getInheritedPropertyState(propertyIndex);
0836: setPropertyState(propertyIndex, inheritedValue);
0837:
0838: // Notify children that the inherited value has changed.
0839: propagatePropertyState(propertyIndex, inheritedValue);
0840: }
0841:
0842: // If the value is not inherited, it means that we are in the middle of
0843: // specifying a value on the node. So we do not notify descendants,
0844: // because this is done in the corresponding methods, e.g., setFill.
0845:
0846: modifiedNode();
0847: }
0848:
0849: /**
0850: * Sets the given float-valued property's inheritance status
0851: * @param propertyIndex the index for the property whose inherited state
0852: * is set
0853: * @param inherit the new property's state
0854: */
0855: public void setFloatInherited(final int propertyIndex,
0856: final boolean inherit) {
0857: if (isInherited(propertyIndex) == inherit) {
0858: return;
0859: }
0860: modifyingNode();
0861: setInheritedQuiet(propertyIndex, inherit);
0862:
0863: if (inherit) {
0864: // The property is now inherited. We store the inherited
0865: // value on the node, which means we keep the computed value
0866: // on the node.
0867: float inheritedValue = getInheritedFloatPropertyState(propertyIndex);
0868: setFloatPropertyState(propertyIndex, inheritedValue);
0869:
0870: // Notify children that the inherited value has changed.
0871: propagateFloatPropertyState(propertyIndex, inheritedValue);
0872: }
0873:
0874: // If the value is not inherited, it means that we are in the middle of
0875: // specifying a value on the node. So we do not notify descendants,
0876: // because this is done in the corresponding methods, e.g., setFill.
0877:
0878: modifiedNode();
0879: }
0880:
0881: /**
0882: * Sets the input packed property's inheritance status
0883: * @param propertyIndex the index for the property whose inherited state
0884: * is set
0885: * @param inherit the new property's state
0886: */
0887: public void setPackedInherited(final int propertyIndex,
0888: final boolean inherit) {
0889: if (isInherited(propertyIndex) == inherit) {
0890: return;
0891: }
0892: modifyingNode();
0893: setInheritedQuiet(propertyIndex, inherit);
0894:
0895: if (inherit) {
0896: // The property is now inherited. We store the inherited
0897: // value on the node, which means we keep the computed value
0898: // on the node.
0899: int inheritedValue = getInheritedPackedPropertyState(propertyIndex);
0900: setPackedPropertyState(propertyIndex, inheritedValue);
0901:
0902: // Notify children that the inherited value has changed.
0903: propagatePackedPropertyState(propertyIndex, inheritedValue);
0904: }
0905:
0906: // If the value is not inherited, it means that we are in the middle of
0907: // specifying a value on the node. So we do not notify descendants,
0908: // because this is done in the corresponding methods, e.g., setFill.
0909:
0910: modifiedNode();
0911: }
0912:
0913: /**
0914: * Implementation. Sets the input property's inheritance status,
0915: * but does not send modification events.
0916: *
0917: * @param propertyIndex the index for the property whose inherited state
0918: * is set
0919: * @param inherit the new property's state
0920: */
0921: protected void setInheritedQuiet(final int propertyIndex,
0922: final boolean inherit) {
0923: if (inherit) {
0924: setMarker(propertyIndex);
0925: } else {
0926: clearMarker(propertyIndex);
0927: }
0928: }
0929:
0930: /**
0931: * Returns true if the input property is color relative. False
0932: * otherwise
0933: * @param propertyIndex index for the property whose color relative
0934: * state should be returned.
0935: * @return true if the property at index propertyIndex is relative to
0936: * the color property.
0937: */
0938: public boolean isColorRelative(final int propertyIndex) {
0939: return isMarkerSet(propertyIndex << 21);
0940: }
0941:
0942: /**
0943: * Returns true if the input property can be color-relative.
0944: *
0945: * @param propertyIndex the index of the property which may be
0946: * color-relative.
0947: * @return true if the input property can be color relative. False
0948: * otherwise.
0949: */
0950: public boolean isColorRelativeProperty(final int propertyIndex) {
0951: switch (propertyIndex) {
0952: case PROPERTY_FILL:
0953: return true;
0954: case PROPERTY_STROKE:
0955: return true;
0956: default:
0957: return false;
0958: }
0959: }
0960:
0961: /**
0962: * Sets the input property as a color-relative property
0963: *
0964: * @param propertyIndex index of the property for which the color relative
0965: * state is set.
0966: * @param isColorRelative the new color relative state for the property
0967: * at propertyIndex.
0968: */
0969: public void setColorRelative(final int propertyIndex,
0970: final boolean isColorRelative) {
0971: if (isColorRelative && !isColorRelativeProperty(propertyIndex)) {
0972: throw new IllegalArgumentException();
0973: }
0974:
0975: if (isColorRelative(propertyIndex) == isColorRelative) {
0976: return;
0977: }
0978:
0979: modifyingNode();
0980: setColorRelativeQuiet(propertyIndex, isColorRelative);
0981:
0982: if (isColorRelative) {
0983: // The property is now color relative. We store the relative
0984: // value in the on the node, i.e., the computed value.
0985: setPropertyState(propertyIndex, color);
0986:
0987: // Notify children that the inherited value has changed.
0988: propagatePropertyState(propertyIndex, color);
0989: }
0990:
0991: modifiedNode();
0992: }
0993:
0994: /**
0995: * Sets the input marker.
0996: *
0997: * @param marker the marker to set.
0998: */
0999: void setMarker(final int marker) {
1000: markers |= marker;
1001: }
1002:
1003: /**
1004: * Clears the input marker.
1005: *
1006: * @param marker the marker to clear.
1007: */
1008: void clearMarker(final int marker) {
1009: markers &= ~marker;
1010: }
1011:
1012: /**
1013: * @return true if the input marker is set.
1014: */
1015: final boolean isMarkerSet(final int marker) {
1016: return (markers & marker) != 0;
1017: }
1018:
1019: /**
1020: * Implementation. Sets the input property as a color-relative property
1021: * but does not generate modification events.
1022: *
1023: * @param propertyIndex index of the property for which the color relative
1024: * state is set.
1025: * @param isColorRelative the new color relative state for the property
1026: * at propertyIndex.
1027: */
1028: protected void setColorRelativeQuiet(final int propertyIndex,
1029: final boolean isColorRelative) {
1030: if (isColorRelative) {
1031: setMarker(propertyIndex << 21);
1032: } else {
1033: clearMarker(propertyIndex << 21);
1034: }
1035: }
1036:
1037: // ====================================================================
1038: // GraphicsNode implementation
1039: // ====================================================================
1040:
1041: /**
1042: * Setting the fill property clears the inherited and color relative
1043: * states (they are set to false).
1044: *
1045: * @param newFill the new fill property
1046: */
1047: public void setFill(final PaintServer newFill) {
1048: if (!isInherited(PROPERTY_FILL) && equal(newFill, fill)) {
1049: return;
1050: }
1051:
1052: modifyingNode();
1053: if (fill != null) {
1054: fill.dispose();
1055: }
1056:
1057: setComputedFill(newFill);
1058: setInheritedQuiet(PROPERTY_FILL, false);
1059: setColorRelativeQuiet(PROPERTY_FILL, false);
1060: propagatePropertyState(PROPERTY_FILL, fill);
1061: modifiedNode();
1062: }
1063:
1064: /**
1065: * @param newFill the new computed fill property.
1066: */
1067: void setComputedFill(final PaintServer newFill) {
1068: this .fill = newFill;
1069: }
1070:
1071: /**
1072: * @return the current fill property. This is not the computed values,
1073: * i.e., it does not account for the inherited or color
1074: * relative states.
1075: */
1076: public PaintServer getFill() {
1077: return fill;
1078: }
1079:
1080: /**
1081: * Setting the fillOpacity property clears the inherited and color relative
1082: * states (they are set to false).
1083: *
1084: * @param newFillOpacity the new fill property
1085: */
1086: public void setFillOpacity(float newFillOpacity) {
1087: if (!isInherited(PROPERTY_FILL_OPACITY)
1088: && newFillOpacity == getFillOpacity()) {
1089: return;
1090: }
1091: modifyingNode();
1092: if (newFillOpacity > 1) {
1093: newFillOpacity = 1;
1094: } else if (newFillOpacity < 0) {
1095: newFillOpacity = 0;
1096: }
1097: setInheritedQuiet(PROPERTY_FILL_OPACITY, false);
1098: setComputedFillOpacity(newFillOpacity);
1099: propagatePackedPropertyState(PROPERTY_FILL_OPACITY, pack
1100: & FILL_OPACITY_MASK);
1101: modifiedNode();
1102: }
1103:
1104: /**
1105: * @param newFillOpacity the new computed value of the fill opacity
1106: * property.
1107: */
1108: void setComputedFillOpacity(final float newFillOpacity) {
1109: pack &= ~FILL_OPACITY_MASK;
1110: pack |= ((((int) (newFillOpacity * 200)) << 7) & FILL_OPACITY_MASK);
1111: }
1112:
1113: /**
1114: * @return the current fillOpacity property.
1115: */
1116: public float getFillOpacity() {
1117: return ((pack & FILL_OPACITY_MASK) >> 7) / 200.0f;
1118: }
1119:
1120: /**
1121: * Setting the stroke clears the inherited and color relative states
1122: * (i.e., they are set to false).
1123: *
1124: * @param newStroke new stroke property.
1125: */
1126: public void setStroke(final PaintServer newStroke) {
1127: if (!isInherited(PROPERTY_STROKE) && equal(newStroke, stroke)) {
1128: return;
1129: }
1130:
1131: modifyingNode();
1132: if (newStroke != stroke) {
1133: if (stroke != null) {
1134: stroke.dispose();
1135: }
1136: }
1137: setInheritedQuiet(PROPERTY_STROKE, false);
1138: setColorRelativeQuiet(PROPERTY_STROKE, false);
1139: setComputedStroke(newStroke);
1140: propagatePropertyState(PROPERTY_STROKE, stroke);
1141: modifiedNode();
1142: }
1143:
1144: /**
1145: * @param newStroke the new computed stroke property.
1146: */
1147: void setComputedStroke(final PaintServer newStroke) {
1148: this .stroke = newStroke;
1149: }
1150:
1151: /**
1152: * @return the stroke property. This is not the computed value as
1153: * it does not account for the inherited and color relative
1154: * states.
1155: */
1156: public PaintServer getStroke() {
1157: return stroke;
1158: }
1159:
1160: /**
1161: * Setting the strokeOpacity property clears the inherited and color
1162: * relative states (they are set to false).
1163: *
1164: * @param newStrokeOpacity the new stroke property
1165: */
1166: public void setStrokeOpacity(float newStrokeOpacity) {
1167: if (!isInherited(PROPERTY_STROKE_OPACITY)
1168: && newStrokeOpacity == getStrokeOpacity()) {
1169: return;
1170: }
1171:
1172: modifyingNode();
1173: if (newStrokeOpacity > 1) {
1174: newStrokeOpacity = 1;
1175: } else if (newStrokeOpacity < 0) {
1176: newStrokeOpacity = 0;
1177: }
1178: setInheritedQuiet(PROPERTY_STROKE_OPACITY, false);
1179: setComputedStrokeOpacity(newStrokeOpacity);
1180: propagatePackedPropertyState(PROPERTY_STROKE_OPACITY, pack
1181: & STROKE_OPACITY_MASK);
1182: modifiedNode();
1183: }
1184:
1185: /**
1186: * @param newStrokeOpacity the new computed stroke-opacity property.
1187: */
1188: void setComputedStrokeOpacity(final float newStrokeOpacity) {
1189: pack &= ~STROKE_OPACITY_MASK;
1190: pack |= ((((int) (newStrokeOpacity * 200)) << 15) & STROKE_OPACITY_MASK);
1191: }
1192:
1193: /**
1194: * @return the current strokeOpacity property.
1195: */
1196: public float getStrokeOpacity() {
1197: return ((pack & STROKE_OPACITY_MASK) >> 15) / 200.0f;
1198: }
1199:
1200: /**
1201: * Setting the color property clears this property's inherited flag.
1202: * @param newColor new color property.
1203: */
1204: public void setColor(final RGB newColor) {
1205: if (!isInherited(PROPERTY_COLOR) && equal(newColor, color)) {
1206: return;
1207: }
1208: modifyingNode();
1209: setComputedColor(newColor);
1210: setInheritedQuiet(PROPERTY_COLOR, false);
1211: propagatePropertyState(PROPERTY_COLOR, color);
1212: modifiedNode();
1213: }
1214:
1215: /**
1216: * @param newColor the new computed color property.
1217: */
1218: void setComputedColor(final RGB newColor) {
1219: color = newColor;
1220:
1221: // We need to recompute the fill and stroke colors if they are
1222: // color-relative.
1223: if (isColorRelative(PROPERTY_FILL)) {
1224: setComputedFill(newColor);
1225: propagatePropertyState(PROPERTY_FILL, fill);
1226: }
1227:
1228: if (isColorRelative(PROPERTY_STROKE)) {
1229: setComputedStroke(newColor);
1230: propagatePropertyState(PROPERTY_STROKE, stroke);
1231: }
1232: }
1233:
1234: /**
1235: * @return the current color property. This is not the computed
1236: * value and does not account for the inherited state.
1237: */
1238: public RGB getColor() {
1239: return color;
1240: }
1241:
1242: /**
1243: * Setting the fillRule property clears its inherited flag
1244: * @param newFillRule new fillRule property
1245: */
1246: public void setFillRule(final int newFillRule) {
1247: if (!isInherited(PROPERTY_FILL_RULE)
1248: && newFillRule == getFillRule()) {
1249: return;
1250: }
1251:
1252: modifyingNode();
1253: setInheritedQuiet(PROPERTY_FILL_RULE, false);
1254: setComputedFillRule(newFillRule);
1255: propagatePackedPropertyState(PROPERTY_FILL_RULE, pack
1256: & FILL_RULE_MASK);
1257: modifiedNode();
1258: }
1259:
1260: /**
1261: * @param newFillRule the new computed fillRule property value.
1262: */
1263: final void setComputedFillRule(final int newFillRule) {
1264: if (newFillRule == WIND_NON_ZERO) {
1265: pack |= FILL_RULE_MASK;
1266: } else {
1267: pack &= ~FILL_RULE_MASK;
1268: }
1269: }
1270:
1271: /**
1272: * @return the current fillRule property, exclusive of
1273: * the inherited flag.
1274: */
1275: public int getFillRule() {
1276: if ((pack & FILL_RULE_MASK) == FILL_RULE_MASK) {
1277: return WIND_NON_ZERO;
1278: }
1279: return WIND_EVEN_ODD;
1280: }
1281:
1282: /**
1283: * Setting the strokeDashArray property clears its inherited flag.
1284: *
1285: * @param newStrokeDashArray new strokeDashArray property.
1286: */
1287: public void setStrokeDashArray(final float[] newStrokeDashArray) {
1288: if (!isInherited(PROPERTY_STROKE_DASH_ARRAY)
1289: && equal(newStrokeDashArray, strokeDashArray)) {
1290: return;
1291: }
1292: modifyingNode();
1293: setComputedStrokeDashArray(newStrokeDashArray);
1294: setInheritedQuiet(PROPERTY_STROKE_DASH_ARRAY, false);
1295: propagatePropertyState(PROPERTY_STROKE_DASH_ARRAY,
1296: newStrokeDashArray);
1297: modifiedNode();
1298: }
1299:
1300: /**
1301: * @param newStrokeDashArray the new computed stroke-dasharray property
1302: * value.
1303: */
1304: void setComputedStrokeDashArray(final float[] newStrokeDashArray) {
1305: strokeDashArray = newStrokeDashArray;
1306: }
1307:
1308: /**
1309: * @return current strokeDashArray, exclusive of the inherited
1310: * state.
1311: */
1312: public float[] getStrokeDashArray() {
1313: return strokeDashArray;
1314: }
1315:
1316: /**
1317: * Setting the strokeLineCap property clears the inherited flag
1318: *
1319: * @param newStrokeLineCap new strokeLineCap property
1320: */
1321: public void setStrokeLineCap(final int newStrokeLineCap) {
1322: if (!isInherited(PROPERTY_STROKE_LINE_CAP)
1323: && newStrokeLineCap == getStrokeLineCap()) {
1324: return;
1325: }
1326: modifyingNode();
1327: setInheritedQuiet(PROPERTY_STROKE_LINE_CAP, false);
1328: setComputedStrokeLineCap(newStrokeLineCap);
1329: propagatePackedPropertyState(PROPERTY_STROKE_LINE_CAP, pack
1330: & STROKE_LINE_CAP_MASK);
1331: modifiedNode();
1332: }
1333:
1334: /**
1335: * @param newStrokeLineCap the new value for the stroke-linecap property.
1336: */
1337: void setComputedStrokeLineCap(final int newStrokeLineCap) {
1338: // Clear stroke-linecap
1339: pack &= ~STROKE_LINE_CAP_MASK;
1340:
1341: switch (newStrokeLineCap) {
1342: case CAP_BUTT:
1343: pack |= CAP_BUTT_IMPL;
1344: break;
1345: case CAP_ROUND:
1346: pack |= CAP_ROUND_IMPL;
1347: break;
1348: default:
1349: pack |= CAP_SQUARE_IMPL;
1350: break;
1351: }
1352: }
1353:
1354: /**
1355: * @return the strokeLineCap property exclusive of its inherited state
1356: */
1357: public int getStrokeLineCap() {
1358: switch (pack & STROKE_LINE_CAP_MASK) {
1359: case CAP_BUTT_IMPL:
1360: return CAP_BUTT;
1361: case CAP_ROUND_IMPL:
1362: return CAP_ROUND;
1363: default:
1364: return CAP_SQUARE;
1365: }
1366: }
1367:
1368: /**
1369: * Setting the strokeLineJoin property clears the inherited flag
1370: *
1371: * @param newStrokeLineJoin new strokeLineJoin property
1372: */
1373: public void setStrokeLineJoin(final int newStrokeLineJoin) {
1374: if (!isInherited(PROPERTY_STROKE_LINE_JOIN)
1375: && newStrokeLineJoin == getStrokeLineJoin()) {
1376: return;
1377: }
1378: modifyingNode();
1379: setInheritedQuiet(PROPERTY_STROKE_LINE_JOIN, false);
1380: setComputedStrokeLineJoin(newStrokeLineJoin);
1381: propagatePackedPropertyState(PROPERTY_STROKE_LINE_JOIN, pack
1382: & STROKE_LINE_JOIN_MASK);
1383: modifiedNode();
1384: }
1385:
1386: /**
1387: * @param newStrokeLineJoin the new computed value of stroke-line-join
1388: */
1389: void setComputedStrokeLineJoin(final int newStrokeLineJoin) {
1390: // Clear stroke-linejoin
1391: pack &= ~STROKE_LINE_JOIN_MASK;
1392:
1393: switch (newStrokeLineJoin) {
1394: case JOIN_MITER:
1395: pack |= JOIN_MITER_IMPL;
1396: break;
1397: case JOIN_ROUND:
1398: pack |= JOIN_ROUND_IMPL;
1399: break;
1400: default:
1401: pack |= JOIN_BEVEL_IMPL;
1402: break;
1403: }
1404: }
1405:
1406: /**
1407: * @return current strokeLineJoin exclusive of the inherited state
1408: */
1409: public int getStrokeLineJoin() {
1410: switch (pack & STROKE_LINE_JOIN_MASK) {
1411: case JOIN_MITER_IMPL:
1412: return JOIN_MITER;
1413: case JOIN_ROUND_IMPL:
1414: return JOIN_ROUND;
1415: default:
1416: return JOIN_BEVEL;
1417: }
1418: }
1419:
1420: /**
1421: * Setting the strokeWidth property clears its inherited flag.
1422: *
1423: * @param newStrokeWidth new strokeWidth property. Should be
1424: * positive or zero.
1425: */
1426: public void setStrokeWidth(final float newStrokeWidth) {
1427: if (newStrokeWidth < 0) {
1428: throw new IllegalArgumentException();
1429: }
1430:
1431: if (!isInherited(PROPERTY_STROKE_WIDTH)
1432: && newStrokeWidth == strokeWidth) {
1433: return;
1434: }
1435:
1436: modifyingNode();
1437: setInheritedQuiet(PROPERTY_STROKE_WIDTH, false);
1438: setComputedStrokeWidth(newStrokeWidth);
1439: propagateFloatPropertyState(PROPERTY_STROKE_WIDTH,
1440: newStrokeWidth);
1441: modifiedNode();
1442: }
1443:
1444: /**
1445: * @param newStrokeWidth the new computed stroke-width property value.
1446: */
1447: void setComputedStrokeWidth(final float newStrokeWidth) {
1448: strokeWidth = newStrokeWidth;
1449: }
1450:
1451: /**
1452: * @return current strokeWidth, exclusive of inheritance
1453: */
1454: public float getStrokeWidth() {
1455: return strokeWidth;
1456: }
1457:
1458: /**
1459: * Setting the strokeMiterLimit clears its inherited flag.
1460: *
1461: * @param newStrokeMiterLimit new strokeMiterLimit property
1462: */
1463: public void setStrokeMiterLimit(final float newStrokeMiterLimit) {
1464: if (newStrokeMiterLimit < 1) {
1465: throw new IllegalArgumentException();
1466: }
1467:
1468: if (!isInherited(PROPERTY_STROKE_MITER_LIMIT)
1469: && newStrokeMiterLimit == strokeMiterLimit) {
1470: return;
1471: }
1472:
1473: modifyingNode();
1474: setComputedStrokeMiterLimit(newStrokeMiterLimit);
1475: setInheritedQuiet(PROPERTY_STROKE_MITER_LIMIT, false);
1476: propagateFloatPropertyState(PROPERTY_STROKE_MITER_LIMIT,
1477: strokeMiterLimit);
1478: modifiedNode();
1479: }
1480:
1481: /**
1482: * @param newStrokeMiterLimit the new computed stroke-miterlimit property.
1483: */
1484: void setComputedStrokeMiterLimit(final float newStrokeMiterLimit) {
1485: strokeMiterLimit = newStrokeMiterLimit;
1486: }
1487:
1488: /**
1489: * @return current strokeMiterLimit, exclusive of the inherited state
1490: */
1491: public float getStrokeMiterLimit() {
1492: return strokeMiterLimit;
1493: }
1494:
1495: /**
1496: * Setting the strokeDashOffset property clears its inherited flag.
1497: *
1498: * @param newStrokeDashOffset new strokeDashOffset value
1499: */
1500: public void setStrokeDashOffset(final float newStrokeDashOffset) {
1501: if (!isInherited(PROPERTY_STROKE_DASH_OFFSET)
1502: && newStrokeDashOffset == strokeDashOffset) {
1503: return;
1504: }
1505:
1506: modifyingNode();
1507: setComputedStrokeDashOffset(newStrokeDashOffset);
1508: setInheritedQuiet(PROPERTY_STROKE_DASH_OFFSET, false);
1509: propagateFloatPropertyState(PROPERTY_STROKE_DASH_OFFSET,
1510: strokeDashOffset);
1511: modifiedNode();
1512: }
1513:
1514: /**
1515: * @param newStrokeDashOffset the new stroke-dashoffset computed property
1516: * value.
1517: */
1518: void setComputedStrokeDashOffset(final float newStrokeDashOffset) {
1519: strokeDashOffset = newStrokeDashOffset;
1520: }
1521:
1522: /**
1523: * @return current strokeDashOffset property value, exclusive of its
1524: * inherited state.
1525: */
1526: public float getStrokeDashOffset() {
1527: return strokeDashOffset;
1528: }
1529:
1530: /**
1531: * Setting the visibility clears its inherited flag.
1532: *
1533: * @param newVisibility the new visibility value
1534: */
1535: public void setVisibility(final boolean newVisibility) {
1536: if (!isInherited(PROPERTY_VISIBILITY)
1537: && newVisibility == getVisibility()) {
1538: return;
1539: }
1540: modifyingNode();
1541: setComputedVisibility(newVisibility);
1542: setInheritedQuiet(PROPERTY_VISIBILITY, false);
1543: propagatePackedPropertyState(PROPERTY_VISIBILITY, pack
1544: & VISIBILITY_MASK);
1545: modifiedNode();
1546: }
1547:
1548: /**
1549: * @param newVisibility the new computed visibility property.
1550: */
1551: void setComputedVisibility(final boolean newVisibility) {
1552: if (newVisibility) {
1553: pack |= VISIBILITY_MASK;
1554: } else {
1555: pack &= ~VISIBILITY_MASK;
1556: }
1557: }
1558:
1559: /**
1560: * @return current visibility property, exclusive of inheritance.
1561: */
1562: public boolean getVisibility() {
1563: return ((pack & VISIBILITY_MASK) == VISIBILITY_MASK);
1564: }
1565:
1566: /**
1567: * Setting the display property clears its inherited flag.
1568: *
1569: * @param newDisplay new display property value
1570: */
1571: public void setDisplay(final boolean newDisplay) {
1572: if (!isInherited(PROPERTY_DISPLAY)
1573: && newDisplay == getDisplay()) {
1574: return;
1575: }
1576: modifyingNode();
1577: setInheritedQuiet(PROPERTY_DISPLAY, false);
1578: setComputedDisplay(newDisplay);
1579: propagatePackedPropertyState(PROPERTY_DISPLAY, pack
1580: & DISPLAY_MASK);
1581: modifiedNode();
1582: }
1583:
1584: /**
1585: * @param newDisplay the new computed display value
1586: */
1587: void setComputedDisplay(final boolean newDisplay) {
1588: if (newDisplay) {
1589: pack |= DISPLAY_MASK;
1590: } else {
1591: pack &= ~DISPLAY_MASK;
1592: }
1593:
1594: computeCanRenderDisplayBit(newDisplay);
1595: }
1596:
1597: /**
1598: * @return current display property value, exclusive of inheritance
1599: */
1600: public boolean getDisplay() {
1601: return ((pack & DISPLAY_MASK) == DISPLAY_MASK);
1602: }
1603:
1604: /**
1605: * Setting the opacity property clears the inherited and color
1606: * relative states (they are set to false).
1607: *
1608: * @param newOpacity the new opacity property
1609: */
1610: public void setOpacity(float newOpacity) {
1611:
1612: if (!isInherited(PROPERTY_OPACITY)
1613: && newOpacity == getOpacity()) {
1614: return;
1615: }
1616:
1617: modifyingNode();
1618: if (newOpacity > 1) {
1619: newOpacity = 1;
1620: } else if (newOpacity < 0) {
1621: newOpacity = 0;
1622: }
1623:
1624: setInheritedQuiet(PROPERTY_OPACITY, false);
1625: setComputedOpacity(newOpacity);
1626: propagatePackedPropertyState(PROPERTY_OPACITY, pack2
1627: & OPACITY_MASK);
1628: modifiedNode();
1629: }
1630:
1631: /**
1632: * @param newOpacity the new computed opacity property.
1633: */
1634: void setComputedOpacity(final float newOpacity) {
1635: pack2 &= ~OPACITY_MASK;
1636: pack2 |= (((int) (newOpacity * 200)) & OPACITY_MASK);
1637: }
1638:
1639: /**
1640: * @return the current opacity property value.
1641: */
1642: public float getOpacity() {
1643: return (pack2 & OPACITY_MASK) / 200.0f;
1644: }
1645:
1646: /**
1647: * Supported traits: stroke-width, stroke-miterlimit, stroke-dashoffset,
1648: * fill-rule, stroke-linejoin, stroke-linecap, display, visibility,
1649: * color, fill, stroke, fill-opacity, stroke-opacity, stroke-dasharray,
1650: * opacity
1651: *
1652: * @param traitName the name of the trait which the element may support.
1653: * @return true if this element supports the given trait in one of the
1654: * trait accessor methods.
1655: */
1656: boolean supportsTrait(final String traitName) {
1657: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == traitName
1658: || SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == traitName
1659: || SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == traitName
1660: || SVGConstants.SVG_FILL_RULE_ATTRIBUTE == traitName
1661: || SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == traitName
1662: || SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == traitName
1663: || SVGConstants.SVG_DISPLAY_ATTRIBUTE == traitName
1664: || SVGConstants.SVG_VISIBILITY_ATTRIBUTE == traitName
1665: || SVGConstants.SVG_COLOR_ATTRIBUTE == traitName
1666: || SVGConstants.SVG_FILL_ATTRIBUTE == traitName
1667: || SVGConstants.SVG_STROKE_ATTRIBUTE == traitName
1668: || SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == traitName
1669: || SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == traitName
1670: || SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE == traitName
1671: || SVGConstants.SVG_OPACITY_ATTRIBUTE == traitName) {
1672: return true;
1673: } else {
1674: return super .supportsTrait(traitName);
1675: }
1676: }
1677:
1678: /**
1679: * Returns the specified trait value as String. In SVG Tiny only certain
1680: * traits can be obtained as a String value. Syntax of the returned String
1681: * matches the syntax of the corresponding attribute. This element is
1682: * exactly equivalent to {@link org.w3c.dom.svg.SVGElement#getTraitNS
1683: * getTraitNS} with namespaceURI set to null.
1684: *
1685: * The method is meant to be overridden by derived classes. The
1686: * implementation pattern is that derived classes will override the method
1687: * and call their super class' implementation. If the ElementNode
1688: * implementation is called, it means that the trait is either not supported
1689: * or that it cannot be seen as a String.
1690: *
1691: * @param name the requested trait name.
1692: * @return the trait value.
1693: *
1694: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1695: * trait is not supported on this element or null.
1696: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1697: * trait's computed value cannot be converted to a String (SVG Tiny only).
1698: */
1699: String getSpecifiedTraitImpl(final String name) throws DOMException {
1700: if ((SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_WIDTH))
1701: || (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_MITER_LIMIT))
1702: || (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_DASH_OFFSET))
1703: || (SVGConstants.SVG_FILL_RULE_ATTRIBUTE == name && isInherited(PROPERTY_FILL_RULE))
1704: || (SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_LINE_JOIN))
1705: || (SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_LINE_CAP))
1706: || (SVGConstants.SVG_DISPLAY_ATTRIBUTE == name && isInherited(PROPERTY_DISPLAY))
1707: || (SVGConstants.SVG_VISIBILITY_ATTRIBUTE == name && isInherited(PROPERTY_VISIBILITY))
1708: || (SVGConstants.SVG_COLOR_ATTRIBUTE == name && isInherited(PROPERTY_COLOR))
1709: || (SVGConstants.SVG_FILL_ATTRIBUTE == name && isInherited(PROPERTY_FILL))
1710: || (SVGConstants.SVG_STROKE_ATTRIBUTE == name && isInherited(PROPERTY_STROKE))
1711: || (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name && isInherited(PROPERTY_FILL_OPACITY))
1712: || (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_OPACITY))
1713: || (SVGConstants.SVG_OPACITY_ATTRIBUTE == name && isInherited(PROPERTY_OPACITY))
1714: || (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE == name && isInherited(PROPERTY_STROKE_DASH_ARRAY))) {
1715: return SVGConstants.CSS_INHERIT_VALUE;
1716: } else if ((SVGConstants.SVG_FILL_ATTRIBUTE == name && isColorRelative(PROPERTY_FILL))
1717: || (SVGConstants.SVG_STROKE_ATTRIBUTE == name && isColorRelative(PROPERTY_STROKE))) {
1718: return SVGConstants.CSS_CURRENTCOLOR_VALUE;
1719: } else if (SVGConstants.SVG_DISPLAY_ATTRIBUTE == name) {
1720: if (getDisplay()) {
1721: return SVGConstants.CSS_INLINE_VALUE;
1722: } else {
1723: return SVGConstants.CSS_NONE_VALUE;
1724: }
1725: } else {
1726: return super .getSpecifiedTraitImpl(name);
1727: }
1728: }
1729:
1730: /**
1731: * Converts the input fill-rule value to a string trait value.
1732: *
1733: * @param fillRule the fill-rule value to convert. In packed form, but
1734: * with mask applied.
1735: * @return the converted value.
1736: */
1737: String fillRuleToStringTrait(final int fillRule) {
1738: if (fillRule == CompositeGraphicsNode.FILL_RULE_MASK) {
1739: return SVGConstants.CSS_NONZERO_VALUE;
1740: }
1741: return SVGConstants.CSS_EVENODD_VALUE;
1742: }
1743:
1744: /**
1745: * @param strokeLineJoin the value to convert. In packed form, but with
1746: * mask applied.
1747: * @return the converted value.
1748: */
1749: String strokeLineJoinToStringTrait(final int strokeLineJoin) {
1750: switch (strokeLineJoin) {
1751: case CompositeGraphicsNode.JOIN_MITER_IMPL:
1752: return SVGConstants.CSS_MITER_VALUE;
1753: case CompositeGraphicsNode.JOIN_ROUND_IMPL:
1754: return SVGConstants.CSS_ROUND_VALUE;
1755: default:
1756: return SVGConstants.CSS_BEVEL_VALUE;
1757: }
1758: }
1759:
1760: /**
1761: * @param strokeLineCap the value to convert.
1762: * @return the converted value.
1763: */
1764: String strokeLineCapToStringTrait(final int strokeLineCap) {
1765: switch (strokeLineCap) {
1766: case CompositeGraphicsNode.CAP_BUTT_IMPL:
1767: return SVGConstants.CSS_BUTT_VALUE;
1768: case CompositeGraphicsNode.CAP_ROUND_IMPL:
1769: return SVGConstants.CSS_ROUND_VALUE;
1770: case CompositeGraphicsNode.CAP_SQUARE_IMPL:
1771: default:
1772: return SVGConstants.CSS_SQUARE_VALUE;
1773: }
1774: }
1775:
1776: /**
1777: * Supported traits: stroke-width, stroke-miterlimit, stroke-dashoffset,
1778: * fill-rule, stroke-linejoin, stroke-linecap, display, visibility,
1779: * color, fill, stroke, fill-opacity, stroke-opacity, stroke-dasharray,
1780: * opacity
1781: *
1782: * @param name the requested trait's name
1783: * @return the requested trait value, as a string.
1784: *
1785: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1786: * trait is not supported on this element or null.
1787: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1788: * trait's computed value cannot be converted to a String (SVG Tiny only).
1789: */
1790: public String getTraitImpl(final String name) throws DOMException {
1791: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name) {
1792: return Float.toString(getStrokeWidth());
1793: } else if (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == name) {
1794: return Float.toString(getStrokeMiterLimit());
1795: } else if (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == name) {
1796: return Float.toString(getStrokeDashOffset());
1797: } else if (SVGConstants.SVG_FILL_RULE_ATTRIBUTE == name) {
1798: return fillRuleToStringTrait(pack & FILL_RULE_MASK);
1799: } else if (SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == name) {
1800: return strokeLineJoinToStringTrait(pack
1801: & STROKE_LINE_JOIN_MASK);
1802: } else if (SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == name) {
1803: return strokeLineCapToStringTrait(pack
1804: & STROKE_LINE_CAP_MASK);
1805: } else if (SVGConstants.SVG_DISPLAY_ATTRIBUTE == name) {
1806: if (getDisplay()) {
1807: return SVGConstants.CSS_INLINE_VALUE;
1808: } else {
1809: return SVGConstants.CSS_NONE_VALUE;
1810: }
1811: } else if (SVGConstants.SVG_VISIBILITY_ATTRIBUTE == name) {
1812: if (getVisibility()) {
1813: return SVGConstants.CSS_VISIBLE_VALUE;
1814: } else {
1815: return SVGConstants.CSS_HIDDEN_VALUE;
1816: }
1817: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE == name) {
1818: return getColor().toString();
1819: } else if (SVGConstants.SVG_FILL_ATTRIBUTE == name) {
1820: return toString(getFill());
1821: } else if (SVGConstants.SVG_STROKE_ATTRIBUTE == name) {
1822: return toString(getStroke());
1823: } else if (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name) {
1824: return Float.toString(getFillOpacity());
1825: } else if (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == name) {
1826: return Float.toString(getStrokeOpacity());
1827: } else if (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE == name) {
1828: return toStringTrait(getStrokeDashArray());
1829: } else if (SVGConstants.SVG_OPACITY_ATTRIBUTE == name) {
1830: return Float.toString(getOpacity());
1831: } else {
1832: return super .getTraitImpl(name);
1833: }
1834: }
1835:
1836: /**
1837: * Supported float traits: stroke-width, stroke-miterlimit,
1838: * stroke-dashoffset, fill-opacity, stroke-opacity, opacity.
1839: *
1840: * @param name the requested trait's name
1841: * @return the requested trait's value, as a floating point.
1842: *
1843: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1844: * trait is not supported on this element or null.
1845: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1846: * trait's computed value cannot be converted to a float
1847: * @throws SecurityException if the application does not have the necessary
1848: * privilege rights to access this (SVG) content.
1849: */
1850: float getFloatTraitImpl(final String name) throws DOMException {
1851: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name) {
1852: return getStrokeWidth();
1853: } else if (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == name) {
1854: return getStrokeMiterLimit();
1855: } else if (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == name) {
1856: return getStrokeDashOffset();
1857: } else if (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name) {
1858: return getFillOpacity();
1859: } else if (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == name) {
1860: return getStrokeOpacity();
1861: } else if (SVGConstants.SVG_OPACITY_ATTRIBUTE == name) {
1862: return getOpacity();
1863: } else {
1864: return super .getFloatTraitImpl(name);
1865: }
1866: }
1867:
1868: /**
1869: * Supported color traits: color, fill, stroke
1870: *
1871: * @param name the requested trait's name.
1872: * @return the requested trait's value, as an <code>SVGRGBColor</code>.
1873: *
1874: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1875: * trait is not supported on this element or null.
1876: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
1877: * trait's computed value cannot be converted to {@link
1878: * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
1879: * @throws SecurityException if the application does not have the necessary
1880: * privilege rights to access this (SVG) content.
1881: */
1882: SVGRGBColor getRGBColorTraitImpl(String name) throws DOMException {
1883: if (SVGConstants.SVG_FILL_ATTRIBUTE.equals(name)) {
1884: return toSVGRGBColor(SVGConstants.SVG_FILL_ATTRIBUTE,
1885: getFill());
1886: } else if (SVGConstants.SVG_STROKE_ATTRIBUTE.equals(name)) {
1887: return toSVGRGBColor(SVGConstants.SVG_STROKE_ATTRIBUTE,
1888: getStroke());
1889: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE.equals(name)) {
1890: return toSVGRGBColor(SVGConstants.SVG_COLOR_ATTRIBUTE,
1891: getColor());
1892: } else {
1893: return super .getRGBColorTraitImpl(name);
1894: }
1895: }
1896:
1897: /**
1898: * @param traitName the trait name.
1899: */
1900: TraitAnim createTraitAnimImpl(final String traitName) {
1901: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == traitName
1902: || SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == traitName
1903: || SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == traitName
1904: || SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == traitName
1905: || SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == traitName
1906: || SVGConstants.SVG_OPACITY_ATTRIBUTE == traitName) {
1907: return new FloatTraitAnim(this , traitName, TRAIT_TYPE_FLOAT);
1908: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE == traitName
1909: || SVGConstants.SVG_FILL_ATTRIBUTE == traitName
1910: || SVGConstants.SVG_STROKE_ATTRIBUTE == traitName) {
1911: return new FloatTraitAnim(this , traitName,
1912: TRAIT_TYPE_SVG_RGB_COLOR);
1913: } else if (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE == traitName) {
1914: return new FloatTraitAnim(this , traitName,
1915: TRAIT_TYPE_STRING);
1916: } else if (SVGConstants.SVG_DISPLAY_ATTRIBUTE == traitName
1917: || SVGConstants.SVG_FILL_RULE_ATTRIBUTE == traitName
1918: || SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == traitName
1919: || SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == traitName
1920: || SVGConstants.SVG_VISIBILITY_ATTRIBUTE == traitName) {
1921: return new StringTraitAnim(this , NULL_NS, traitName);
1922: } else {
1923: return super .createTraitAnimImpl(traitName);
1924: }
1925: }
1926:
1927: /**
1928: * Set the trait value as float array.
1929: *
1930: * @param name the trait's name.
1931: * @param value the trait's value.
1932: *
1933: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
1934: * trait is not supported on this element.
1935: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
1936: * trait's value cannot be specified as a float
1937: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1938: * value is an invalid value for the given trait.
1939: */
1940: void setFloatArrayTrait(final String name, final float[][] value)
1941: throws DOMException {
1942: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name) {
1943: checkPositive(name, value[0][0]);
1944: setStrokeWidth(value[0][0]);
1945: } else if (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE
1946: .equals(name)) {
1947: if (value[0][0] < 1) {
1948: throw illegalTraitValue(name, Float
1949: .toString(value[0][0]));
1950: }
1951:
1952: setStrokeMiterLimit(value[0][0]);
1953: } else if (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE
1954: .equals(name)) {
1955: setStrokeDashOffset(value[0][0]);
1956: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE == name) {
1957: setColor(toRGB(name, value));
1958: } else if (SVGConstants.SVG_FILL_ATTRIBUTE == name) {
1959: setFill(toRGB(name, value));
1960: } else if (SVGConstants.SVG_STROKE_ATTRIBUTE == name) {
1961: setStroke(toRGB(name, value));
1962: } else if (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name) {
1963: setFillOpacity(value[0][0]);
1964: } else if (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == name) {
1965: setStrokeOpacity(value[0][0]);
1966: } else if (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE
1967: .equals(name)) {
1968: setStrokeDashArray(value[0]);
1969: } else if (SVGConstants.SVG_OPACITY_ATTRIBUTE == name) {
1970: setOpacity(value[0][0]);
1971: } else {
1972: super .setFloatArrayTrait(name, value);
1973: }
1974: }
1975:
1976: /**
1977: * Validates the input trait value.
1978: *
1979: * @param namespaceURI the trait's namespace URI.
1980: * @param traitName the name of the trait to be validated.
1981: * @param value the value to be validated
1982: * @param reqNamespaceURI the namespace of the element requesting
1983: * validation.
1984: * @param reqLocalName the local name of the element requesting validation.
1985: * @param reqTraitNamespace the namespace of the trait which has the values
1986: * value on the requesting element.
1987: * @param reqTraitName the name of the trait which has the values value on
1988: * the requesting element.
1989: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
1990: * value is incompatible with the given trait.
1991: */
1992: String validateTraitNS(final String namespaceURI,
1993: final String traitName, final String value,
1994: final String reqNamespaceURI, final String reqLocalName,
1995: final String reqTraitNamespace, final String reqTraitName)
1996: throws DOMException {
1997: if (namespaceURI != null && namespaceURI != NULL_NS) {
1998: return super .validateTraitNS(namespaceURI, traitName,
1999: value, reqNamespaceURI, reqLocalName,
2000: reqTraitNamespace, reqTraitName);
2001: }
2002:
2003: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == traitName
2004: || SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == traitName
2005: || SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == traitName
2006: || SVGConstants.SVG_COLOR_ATTRIBUTE == traitName
2007: || SVGConstants.SVG_FILL_ATTRIBUTE == traitName
2008: || SVGConstants.SVG_STROKE_ATTRIBUTE == traitName
2009: || SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == traitName
2010: || SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == traitName
2011: || SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE
2012: .equals(traitName)
2013: || SVGConstants.SVG_OPACITY_ATTRIBUTE == traitName) {
2014: throw unsupportedTraitType(traitName, TRAIT_TYPE_FLOAT);
2015: } else if (SVGConstants.SVG_FILL_RULE_ATTRIBUTE == traitName) {
2016: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2017: return fillRuleToStringTrait(getInheritedPackedPropertyState(PROPERTY_FILL_RULE));
2018: }
2019:
2020: if (!SVGConstants.CSS_NONZERO_VALUE.equals(value)
2021: && !SVGConstants.CSS_EVENODD_VALUE.equals(value)) {
2022: throw illegalTraitValue(traitName, value);
2023: }
2024:
2025: return value;
2026: } else if (SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == traitName) {
2027: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2028: return strokeLineJoinToStringTrait(getInheritedPackedPropertyState(PROPERTY_STROKE_LINE_JOIN));
2029: }
2030:
2031: if (!SVGConstants.CSS_MITER_VALUE.equals(value)
2032: && !SVGConstants.CSS_ROUND_VALUE.equals(value)
2033: && !SVGConstants.CSS_BEVEL_VALUE.equals(value)) {
2034: throw illegalTraitValue(traitName, value);
2035: }
2036:
2037: return value;
2038: } else if (SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == traitName) {
2039: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2040: return strokeLineCapToStringTrait(getInheritedPackedPropertyState(PROPERTY_STROKE_LINE_CAP));
2041: }
2042:
2043: if (!SVGConstants.CSS_BUTT_VALUE.equals(value)
2044: && !SVGConstants.CSS_ROUND_VALUE.equals(value)
2045: && !SVGConstants.CSS_SQUARE_VALUE.equals(value)) {
2046: throw illegalTraitValue(traitName, value);
2047: }
2048:
2049: return value;
2050: } else if (SVGConstants.SVG_DISPLAY_ATTRIBUTE == traitName) {
2051: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2052: if (getInheritedPackedPropertyState(PROPERTY_DISPLAY) != 0) {
2053: return SVGConstants.CSS_INLINE_VALUE;
2054: }
2055: return SVGConstants.CSS_NONE_VALUE;
2056: }
2057:
2058: if (!SVGConstants.CSS_INLINE_VALUE.equals(value)
2059: && !SVGConstants.CSS_NONE_VALUE.equals(value)) {
2060: throw illegalTraitValue(traitName, value);
2061: }
2062:
2063: return value;
2064: } else if (SVGConstants.SVG_VISIBILITY_ATTRIBUTE == traitName) {
2065: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2066: if (getInheritedPackedPropertyState(PROPERTY_VISIBILITY) != 0) {
2067: return SVGConstants.CSS_VISIBLE_VALUE;
2068: } else {
2069: return SVGConstants.CSS_HIDDEN_VALUE;
2070: }
2071: }
2072:
2073: if (!SVGConstants.CSS_VISIBLE_VALUE.equals(value)
2074: && !SVGConstants.CSS_HIDDEN_VALUE.equals(value)) {
2075: throw illegalTraitValue(traitName, value);
2076: }
2077:
2078: return value;
2079: }
2080:
2081: return super .validateTraitNS(namespaceURI, traitName, value,
2082: reqNamespaceURI, reqLocalName, reqTraitNamespace,
2083: reqTraitName);
2084: }
2085:
2086: /**
2087: * Validates the float input trait value.
2088: *
2089: * @param traitName the name of the trait to be validated.
2090: * @param value the value to be validated
2091: * @param reqNamespaceURI the namespace of the element requesting
2092: * validation.
2093: * @param reqLocalName the local name of the element requesting validation.
2094: * @param reqTraitNamespace the namespace of the trait which has the values
2095: * value on the requesting element.
2096: * @param reqTraitName the name of the trait which has the values value on
2097: * the requesting element.
2098: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2099: * value is incompatible with the given trait.
2100: */
2101: public float[][] validateFloatArrayTrait(final String traitName,
2102: final String value, final String reqNamespaceURI,
2103: final String reqLocalName, final String reqTraitNamespace,
2104: final String reqTraitName) throws DOMException {
2105: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == traitName) {
2106: return new float[][] { { parsePositiveFloatTrait(traitName,
2107: value) } };
2108: } else if (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE
2109: .equals(traitName)) {
2110: float miter = parseFloatTrait(traitName, value);
2111: if (miter < 1) {
2112: throw illegalTraitValue(traitName, value);
2113: }
2114: return new float[][] { { miter } };
2115: } else if (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE
2116: .equals(traitName)) {
2117: return new float[][] { { parseFloatTrait(traitName, value) } };
2118: } else if (SVGConstants.SVG_FILL_RULE_ATTRIBUTE == traitName
2119: || SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == traitName
2120: || SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == traitName
2121: || SVGConstants.SVG_DISPLAY_ATTRIBUTE == traitName
2122: || SVGConstants.SVG_VISIBILITY_ATTRIBUTE == traitName) {
2123: throw unsupportedTraitType(traitName, TRAIT_TYPE_FLOAT);
2124: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE == traitName) {
2125: RGB color = GraphicsProperties.INITIAL_COLOR;
2126: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2127: color = (RGB) getInheritedPropertyState(PROPERTY_COLOR);
2128: } else {
2129: color = parseColorTrait(
2130: SVGConstants.SVG_COLOR_ATTRIBUTE, value);
2131: }
2132:
2133: if (color == null) {
2134: throw illegalTraitValue(traitName, value);
2135: }
2136: return new float[][] { { color.getRed(), color.getGreen(),
2137: color.getBlue() } };
2138: } else if (SVGConstants.SVG_FILL_ATTRIBUTE == traitName) {
2139: RGB color = GraphicsProperties.INITIAL_FILL;
2140: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2141: color = (RGB) getInheritedPropertyState(PROPERTY_FILL);
2142: } else if (SVGConstants.CSS_CURRENTCOLOR_VALUE
2143: .equals(value)) {
2144: color = this .color;
2145: } else {
2146: color = parseColorTrait(
2147: SVGConstants.SVG_FILL_ATTRIBUTE, value);
2148: }
2149:
2150: if (color == null) {
2151: throw illegalTraitValue(traitName, value);
2152: }
2153: return new float[][] { { color.getRed(), color.getGreen(),
2154: color.getBlue() } };
2155: } else if (SVGConstants.SVG_STROKE_ATTRIBUTE == traitName) {
2156: RGB color = GraphicsProperties.INITIAL_STROKE;
2157: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2158: color = (RGB) getInheritedPropertyState(PROPERTY_STROKE);
2159: } else if (SVGConstants.CSS_CURRENTCOLOR_VALUE
2160: .equals(value)) {
2161: color = getColor();
2162: } else {
2163: color = parseColorTrait(
2164: SVGConstants.SVG_STROKE_ATTRIBUTE, value);
2165: }
2166:
2167: if (color == null) {
2168: throw illegalTraitValue(traitName, value);
2169: }
2170: return new float[][] { { color.getRed(), color.getGreen(),
2171: color.getBlue() } };
2172: } else if (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == traitName) {
2173: float v = GraphicsNode.INITIAL_FILL_OPACITY;
2174: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2175: if (parent != null) {
2176: v = (getInheritedPackedPropertyState(PROPERTY_FILL_OPACITY) >> 7) / 200.0f;
2177: }
2178: } else {
2179: v = parseFloatTrait(traitName, value);
2180: if (v < 0) {
2181: v = 0;
2182: } else if (v > 1) {
2183: v = 1;
2184: }
2185: }
2186: return new float[][] { { v } };
2187: } else if (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == traitName) {
2188: float v = GraphicsProperties.INITIAL_STROKE_OPACITY;
2189: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2190: v = (getInheritedPackedPropertyState(PROPERTY_STROKE_OPACITY) >> 15) / 200.0f;
2191: } else {
2192: v = parseFloatTrait(traitName, value);
2193: if (v < 0) {
2194: v = 0;
2195: } else if (v > 1) {
2196: v = 1;
2197: }
2198: }
2199: return new float[][] { { v } };
2200: } else if (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE
2201: .equals(traitName)) {
2202: float[] da = parsePositiveFloatArrayTrait(traitName, value);
2203: if (da == null) {
2204: throw illegalTraitValue(traitName, value);
2205: } else {
2206: return new float[][] { da };
2207: }
2208: } else if (SVGConstants.SVG_OPACITY_ATTRIBUTE == traitName) {
2209: float v = GraphicsProperties.INITIAL_OPACITY;
2210: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2211: v = getInheritedPackedPropertyState(PROPERTY_OPACITY) / 200.0f;
2212: } else {
2213: v = parseFloatTrait(traitName, value);
2214: if (v < 0) {
2215: v = 0;
2216: } else if (v > 1) {
2217: v = 1;
2218: }
2219: }
2220: return new float[][] { { v } };
2221: } else {
2222: return super .validateFloatArrayTrait(traitName, value,
2223: reqNamespaceURI, reqLocalName, reqTraitNamespace,
2224: reqTraitName);
2225: }
2226:
2227: }
2228:
2229: /**
2230: * CompositeGraphicsNode handles the graphics node traits.
2231: * Other attributes are handled by the super class.
2232: *
2233: * Supported traits: stroke-width, stroke-miterlimit, stroke-dashoffset,
2234: * fill-rule, stroke-linejoin, stroke-linecap, display, visibility,
2235: * color, fill, stroke, fill-opacity, stroke-opacity, stroke-dasharray,
2236: * opacity
2237: *
2238: * @param name the name of the trait to set.
2239: * @param value the value of the trait to set.
2240: *
2241: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2242: * trait is not supported on this element or null.
2243: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2244: * trait's value cannot be specified as a String
2245: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2246: * value is an invalid value for the given trait or null.
2247: * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
2248: * attempt is made to change readonly trait.
2249: */
2250: public void setTraitImpl(final String name, final String value)
2251: throws DOMException {
2252: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name) {
2253:
2254: // ======================= stroke-width ===================== //
2255:
2256: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2257: setFloatInherited(PROPERTY_STROKE_WIDTH, true);
2258: } else {
2259: setStrokeWidth(parsePositiveFloatTrait(name, value));
2260: }
2261: } else if (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE
2262: .equals(name)) {
2263:
2264: // ===================== stroke-miterlimit ================== //
2265:
2266: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2267: setFloatInherited(PROPERTY_STROKE_MITER_LIMIT, true);
2268: } else {
2269: float miter = parseFloatTrait(name, value);
2270: if (miter < 1) {
2271: throw illegalTraitValue(name, value);
2272: }
2273: setStrokeMiterLimit(miter);
2274: }
2275:
2276: } else if (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE
2277: .equals(name)) {
2278:
2279: // ===================== stroke-dashoffset ================== //
2280:
2281: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2282: setFloatInherited(PROPERTY_STROKE_DASH_OFFSET, true);
2283: } else {
2284: setStrokeDashOffset(parseFloatTrait(name, value));
2285: }
2286: } else if (SVGConstants.SVG_FILL_RULE_ATTRIBUTE == name) {
2287:
2288: // ========================= fill-rule ====================== //
2289:
2290: if (SVGConstants.CSS_NONZERO_VALUE.equals(value)) {
2291: setFillRule(GraphicsProperties.WIND_NON_ZERO);
2292: } else if (SVGConstants.CSS_EVENODD_VALUE.equals(value)) {
2293: setFillRule(GraphicsProperties.WIND_EVEN_ODD);
2294: } else if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2295: setPackedInherited(PROPERTY_FILL_RULE, true);
2296: } else {
2297: throw illegalTraitValue(name, value);
2298: }
2299: } else if (SVGConstants.SVG_STROKE_LINEJOIN_ATTRIBUTE == name) {
2300:
2301: // ==================== stroke-linejoin ===================== //
2302:
2303: if (SVGConstants.CSS_MITER_VALUE.equals(value)) {
2304: setStrokeLineJoin(GraphicsProperties.JOIN_MITER);
2305: } else if (SVGConstants.CSS_ROUND_VALUE.equals(value)) {
2306: setStrokeLineJoin(GraphicsProperties.JOIN_ROUND);
2307: } else if (SVGConstants.CSS_BEVEL_VALUE.equals(value)) {
2308: setStrokeLineJoin(GraphicsProperties.JOIN_BEVEL);
2309: } else if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2310: setPackedInherited(PROPERTY_STROKE_LINE_JOIN, true);
2311: } else {
2312: throw illegalTraitValue(name, value);
2313: }
2314: } else if (SVGConstants.SVG_STROKE_LINECAP_ATTRIBUTE == name) {
2315:
2316: // ====================== stroke-linecap ==================== //
2317:
2318: if (SVGConstants.CSS_BUTT_VALUE.equals(value)) {
2319: setStrokeLineCap(GraphicsProperties.CAP_BUTT);
2320: } else if (SVGConstants.CSS_ROUND_VALUE.equals(value)) {
2321: setStrokeLineCap(GraphicsProperties.CAP_ROUND);
2322: } else if (SVGConstants.CSS_SQUARE_VALUE.equals(value)) {
2323: setStrokeLineCap(GraphicsProperties.CAP_SQUARE);
2324: } else if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2325: setPackedInherited(PROPERTY_STROKE_LINE_CAP, true);
2326: } else {
2327: throw illegalTraitValue(name, value);
2328: }
2329: } else if (SVGConstants.SVG_DISPLAY_ATTRIBUTE == name) {
2330:
2331: // ======================== display ========================= //
2332:
2333: if (SVGConstants.CSS_NONE_VALUE.equals(value)) {
2334: setDisplay(false);
2335: } else if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2336: if (!isInherited(PROPERTY_DISPLAY)) {
2337: setPackedInherited(PROPERTY_DISPLAY, true);
2338: }
2339: } else if (SVGConstants.CSS_BLOCK_VALUE.equals(value)
2340: || SVGConstants.CSS_COMPACT_VALUE.equals(value)
2341: || SVGConstants.CSS_INLINE_TABLE_VALUE
2342: .equals(value)
2343: || SVGConstants.CSS_INLINE_VALUE.equals(value)
2344: || SVGConstants.CSS_LIST_ITEM_VALUE.equals(value)
2345: || SVGConstants.CSS_MARKER_VALUE.equals(value)
2346: || SVGConstants.CSS_RUN_IN_VALUE.equals(value)
2347: || SVGConstants.CSS_TABLE_VALUE.equals(value)
2348: || SVGConstants.CSS_TABLE_ROW_GROUP_VALUE
2349: .equals(value)
2350: || SVGConstants.CSS_TABLE_HEADER_GROUP_VALUE
2351: .equals(value)
2352: || SVGConstants.CSS_TABLE_FOOTER_GROUP_VALUE
2353: .equals(value)
2354: || SVGConstants.CSS_TABLE_ROW_VALUE.equals(value)
2355: || SVGConstants.CSS_TABLE_COLUMN_GROUP_VALUE
2356: .equals(value)
2357: || SVGConstants.CSS_TABLE_COLUMN_VALUE
2358: .equals(value)
2359: || SVGConstants.CSS_TABLE_CELL_VALUE.equals(value)
2360: || SVGConstants.CSS_TABLE_CAPTION_VALUE
2361: .equals(value)) {
2362: setDisplay(true);
2363: } else {
2364: throw illegalTraitValue(name, value);
2365: }
2366: } else if (SVGConstants.SVG_VISIBILITY_ATTRIBUTE == name) {
2367:
2368: // ======================= visibility ======================= //
2369:
2370: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2371: setPackedInherited(PROPERTY_VISIBILITY, true);
2372: } else if (SVGConstants.CSS_HIDDEN_VALUE.equals(value)
2373: || SVGConstants.CSS_COLLAPSE_VALUE.equals(value)) {
2374: setVisibility(false);
2375: } else if (SVGConstants.CSS_VISIBLE_VALUE.equals(value)) {
2376: setVisibility(true);
2377: } else {
2378: throw illegalTraitValue(name, value);
2379: }
2380: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE == name) {
2381:
2382: // ========================= color ========================== //
2383:
2384: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2385: setInherited(PROPERTY_COLOR, true);
2386: } else if (SVGConstants.CSS_NONE_VALUE.equals(value)) {
2387: // 'none' is not a legal value for 'color'
2388: throw illegalTraitValue(name, value);
2389: } else {
2390: RGB color = parseColorTrait(
2391: SVGConstants.SVG_COLOR_ATTRIBUTE, value);
2392: setColor(color);
2393: }
2394: } else if (SVGConstants.SVG_FILL_ATTRIBUTE == name) {
2395:
2396: // ========================= fill =========================== //
2397:
2398: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2399: setInherited(PROPERTY_FILL, true);
2400: setColorRelative(PROPERTY_FILL, false);
2401: } else if (SVGConstants.CSS_NONE_VALUE.equals(value)) {
2402: setFill(null);
2403: } else if (SVGConstants.CSS_CURRENTCOLOR_VALUE
2404: .equals(value)) {
2405: setColorRelative(PROPERTY_FILL, true);
2406: setInherited(PROPERTY_FILL, false);
2407: } else {
2408: PaintServer fill = parsePaintTrait(
2409: SVGConstants.SVG_FILL_ATTRIBUTE, this , value);
2410: if (fill != null) {
2411: setFill(fill);
2412: }
2413: }
2414: } else if (SVGConstants.SVG_STROKE_ATTRIBUTE == name) {
2415:
2416: // ========================= stroke ========================= //
2417:
2418: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2419: setInherited(PROPERTY_STROKE, true);
2420: setColorRelative(PROPERTY_STROKE, false);
2421: } else if (SVGConstants.CSS_NONE_VALUE.equals(value)) {
2422: setStroke(null);
2423: } else if (SVGConstants.CSS_CURRENTCOLOR_VALUE
2424: .equals(value)) {
2425: setColorRelative(PROPERTY_STROKE, true);
2426: setInherited(PROPERTY_STROKE, false);
2427: } else {
2428: PaintServer stroke = parsePaintTrait(
2429: SVGConstants.SVG_STROKE_ATTRIBUTE, this , value);
2430: if (stroke != null) {
2431: setStroke(stroke);
2432: }
2433: }
2434: } else if (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name) {
2435:
2436: // ====================== fill-opacity ======================= //
2437:
2438: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2439: setPackedInherited(PROPERTY_FILL_OPACITY, true);
2440: } else {
2441: setFillOpacity(parseFloatTrait(name, value));
2442: }
2443: } else if (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE
2444: .equals(name)) {
2445:
2446: // ================= stroke-opacity ========================= //
2447:
2448: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2449: setPackedInherited(PROPERTY_STROKE_OPACITY, true);
2450: } else {
2451: setStrokeOpacity(parseFloatTrait(name, value));
2452: }
2453: } else if (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE
2454: .equals(name)) {
2455:
2456: // ==================== stroke-dasharray ==================== //
2457:
2458: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2459: setInherited(PROPERTY_STROKE_DASH_ARRAY, true);
2460: } else if (SVGConstants.CSS_NONE_VALUE.equals(value)) {
2461: setStrokeDashArray(null);
2462: } else {
2463: setStrokeDashArray(parsePositiveFloatArrayTrait(name,
2464: value));
2465: }
2466: } else if (SVGConstants.SVG_OPACITY_ATTRIBUTE.equals(name)) {
2467:
2468: // ================= opacity ========================= //
2469:
2470: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
2471: setPackedInherited(PROPERTY_OPACITY, true);
2472: } else {
2473: setOpacity(parseFloatTrait(name, value));
2474: }
2475: } else {
2476: super .setTraitImpl(name, value);
2477: }
2478: }
2479:
2480: /**
2481: * @param name the name of the trait to convert.
2482: * @param value the float trait value to convert.
2483: */
2484: String toStringTrait(final String name, final float[][] value) {
2485: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name
2486: || SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == name
2487: || SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == name
2488: || SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name
2489: || SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == name
2490: || SVGConstants.SVG_OPACITY_ATTRIBUTE == name) {
2491: return Float.toString(value[0][0]);
2492: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE == name
2493: || SVGConstants.SVG_FILL_ATTRIBUTE == name
2494: || SVGConstants.SVG_STROKE_ATTRIBUTE == name) {
2495: return toRGBString(name, value);
2496: } else if (SVGConstants.SVG_STROKE_DASHARRAY_ATTRIBUTE == name) {
2497: return toStringTrait(value[0]);
2498: } else {
2499: return super .toStringTrait(name, value);
2500: }
2501: }
2502:
2503: /**
2504: * Set the trait value as float.
2505: *
2506: * Supported float traits: stroke-width, stroke-miterlimit,
2507: * stroke-dashoffset, fill-opacity, stroke-opacity, opacity.
2508: *
2509: * @param name the name of the trait to set.
2510: * @param value the value of the trait to set.
2511: *
2512: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2513: * trait is not supported on this element.
2514: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2515: * trait's value cannot be specified as a float
2516: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2517: * value is an invalid value for the given trait.
2518: * @throws SecurityException if the application does not have the necessary
2519: * privilege rights to access this (SVG) content.
2520: */
2521: public void setFloatTraitImpl(final String name, final float value)
2522: throws DOMException {
2523: if (SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE == name) {
2524: checkPositive(name, value);
2525: setStrokeWidth(value);
2526: } else if (SVGConstants.SVG_STROKE_MITERLIMIT_ATTRIBUTE == name) {
2527: if (value < 1) {
2528: throw illegalTraitValue(name, Float.toString(value));
2529: }
2530: setStrokeMiterLimit(value);
2531: } else if (SVGConstants.SVG_STROKE_DASHOFFSET_ATTRIBUTE == name) {
2532: setStrokeDashOffset(value);
2533: } else if (SVGConstants.SVG_FILL_OPACITY_ATTRIBUTE == name) {
2534: setFillOpacity(value);
2535: } else if (SVGConstants.SVG_STROKE_OPACITY_ATTRIBUTE == name) {
2536: setStrokeOpacity(value);
2537: } else if (SVGConstants.SVG_OPACITY_ATTRIBUTE == name) {
2538: setOpacity(value);
2539: } else {
2540: super .setFloatTraitImpl(name, value);
2541: }
2542: }
2543:
2544: /**
2545: * Set the trait value as {@link org.w3c.dom.svg.SVGRGBColor SVGRGBColor}.
2546: *
2547: * Supported color traits: color, fill, stroke
2548: *
2549: * @param name the name of the trait to set.
2550: * @param value the value of the trait to set.
2551: *
2552: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
2553: * trait is not supported on this element or null.
2554: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
2555: * trait's value cannot be specified as an {@link
2556: * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
2557: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
2558: * value is null.
2559: * @throws SecurityException if the application does not have the necessary
2560: * privilege rights to access this (SVG) content.
2561: */
2562: void setRGBColorTraitImpl(final String name, final SVGRGBColor color)
2563: throws DOMException {
2564: try {
2565: // We use .equals here because the name string may not have been
2566: // interned.
2567: if (SVGConstants.SVG_FILL_ATTRIBUTE.equals(name)) {
2568: setFill((RGB) color);
2569: } else if (SVGConstants.SVG_STROKE_ATTRIBUTE.equals(name)) {
2570: setStroke((RGB) color);
2571: } else if (SVGConstants.SVG_COLOR_ATTRIBUTE.equals(name)) {
2572: setColor((RGB) color);
2573: } else {
2574: super .setRGBColorTraitImpl(name, color);
2575: }
2576: } catch (IllegalArgumentException iae) {
2577: throw new DOMException(DOMException.INVALID_ACCESS_ERR, iae
2578: .getMessage());
2579: }
2580: }
2581:
2582: /**
2583: * @param paintType the key provided by the PaintTarget when it subscribed
2584: * to associated PaintServer.
2585: * @param paintServer the PaintServer generating the update.
2586: */
2587: public void onPaintServerUpdate(final String paintType,
2588: final PaintServer paintServer) {
2589: if (paintType == SVGConstants.SVG_FILL_ATTRIBUTE) {
2590: setFill(paintServer);
2591: } else if (paintType == SVGConstants.SVG_STROKE_ATTRIBUTE) {
2592: setStroke(paintServer);
2593: } else {
2594: throw new Error();
2595: }
2596: }
2597: }
|