< prev index next >

modules/graphics/src/main/java/javafx/scene/shape/Shape.java

Print this page




 116  * the shape.
 117  * @since JavaFX 2.0
 118  */
 119 public abstract class Shape extends Node {
 120 
 121     static {
 122         // This is used by classes in different packages to get access to
 123         // private and package private methods.
 124         ShapeHelper.setShapeAccessor(new ShapeHelper.ShapeAccessor() {
 125             @Override
 126             public void doUpdatePeer(Node node) {
 127                 ((Shape) node).doUpdatePeer();
 128             }
 129 
 130             @Override
 131             public void doMarkDirty(Node node, DirtyBits dirtyBit) {
 132                 ((Shape) node).doMarkDirty(dirtyBit);
 133             }
 134 
 135             @Override
















 136             public Paint doCssGetFillInitialValue(Shape shape) {
 137                 return shape.doCssGetFillInitialValue();
 138             }
 139 
 140             @Override
 141             public Paint doCssGetStrokeInitialValue(Shape shape) {
 142                 return shape.doCssGetStrokeInitialValue();
 143             }
 144 
 145             @Override
 146             public NGShape.Mode getMode(Shape shape) {
 147                 return shape.getMode();
 148             }
 149 
 150             @Override
 151             public void setMode(Shape shape, NGShape.Mode mode) {
 152                 shape.setMode(mode);
 153             }
 154 
 155             @Override


 374             return NGShape.Mode.EMPTY;
 375         }
 376     }
 377 
 378     NGShape.Mode getMode() {
 379         return mode;
 380     }
 381 
 382     void setMode(NGShape.Mode mode) {
 383         mode = mode;
 384     }
 385 
 386     private NGShape.Mode mode = NGShape.Mode.FILL;
 387 
 388     private void checkModeChanged() {
 389         NGShape.Mode newMode = computeMode();
 390         if (mode != newMode) {
 391             mode = newMode;
 392 
 393             NodeHelper.markDirty(this, DirtyBits.SHAPE_MODE);
 394             impl_geomChanged();
 395         }
 396     }
 397 
 398     /**
 399      * Defines parameters to fill the interior of an {@code Shape}
 400      * using the settings of the {@code Paint} context.
 401      * The default value is {@code Color.BLACK} for all shapes except
 402      * Line, Polyline, and Path. The default value is {@code null} for
 403      * those shapes.
 404      */
 405     private ObjectProperty<Paint> fill;
 406 
 407 
 408     public final void setFill(Paint value) {
 409         fillProperty().set(value);
 410     }
 411 
 412     public final Paint getFill() {
 413         return fill == null ? Color.BLACK : fill.get();
 414     }


 463     /**
 464      * Defines parameters of a stroke that is drawn around the outline of
 465      * a {@code Shape} using the settings of the specified {@code Paint}.
 466      * The default value is {@code null} for all shapes except
 467      * Line, Polyline, and Path. The default value is {@code Color.BLACK} for
 468      * those shapes.
 469      */
 470     private ObjectProperty<Paint> stroke;
 471 
 472 
 473     public final void setStroke(Paint value) {
 474         strokeProperty().set(value);
 475     }
 476 
 477     private final AbstractNotifyListener platformImageChangeListener =
 478             new AbstractNotifyListener() {
 479         @Override
 480         public void invalidated(Observable valueModel) {
 481             NodeHelper.markDirty(Shape.this, DirtyBits.SHAPE_FILL);
 482             NodeHelper.markDirty(Shape.this, DirtyBits.SHAPE_STROKE);
 483             impl_geomChanged();
 484             checkModeChanged();
 485         }
 486     };
 487 
 488     public final Paint getStroke() {
 489         return stroke == null ? null : stroke.get();
 490     }
 491 
 492     Paint old_stroke;
 493     public final ObjectProperty<Paint> strokeProperty() {
 494         if (stroke == null) {
 495             stroke = new StyleableObjectProperty<Paint>() {
 496 
 497                 boolean needsListener = false;
 498 
 499                 @Override public void invalidated() {
 500 
 501                     Paint _stroke = get();
 502 
 503                     if (needsListener) {


 873      * @return The CssMetaData associated with this class, which may include the
 874      * CssMetaData of its super classes.
 875      * @since JavaFX 8.0
 876      */
 877     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 878         return StyleableProperties.STYLEABLES;
 879     }
 880 
 881     /**
 882      * {@inheritDoc}
 883      *
 884      * @since JavaFX 8.0
 885      */
 886 
 887 
 888     @Override
 889     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 890         return getClassCssMetaData();
 891     }
 892 
 893     /**
 894      * @treatAsPrivate implementation detail
 895      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 896      */
 897     @Deprecated
 898     @Override
 899     public BaseBounds impl_computeGeomBounds(BaseBounds bounds,
 900                                              BaseTransform tx) {
 901         return computeShapeBounds(bounds, tx, ShapeHelper.configShape(this));
 902     }
 903 
 904     /**
 905      * @treatAsPrivate implementation detail
 906      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 907      */
 908     @Deprecated
 909     @Override
 910     protected boolean impl_computeContains(double localX, double localY) {
 911         return computeShapeContains(localX, localY, ShapeHelper.configShape(this));
 912     }
 913 
 914     private static final double MIN_STROKE_WIDTH = 0.0f;
 915     private static final double MIN_STROKE_MITER_LIMIT = 1.0f;
 916 
 917     private void updatePGShape() {
 918         final NGShape peer = NodeHelper.getPeer(this);
 919         if (strokeAttributesDirty && (getStroke() != null)) {
 920             // set attributes of stroke only when stroke paint is not null
 921             final float[] pgDashArray =
 922                     (hasStrokeDashArray())
 923                             ? toPGDashArray(getStrokeDashArray())
 924                             : DEFAULT_PG_STROKE_DASH_ARRAY;
 925 
 926             peer.setDrawStroke(
 927                         (float)Utils.clampMin(getStrokeWidth(),
 928                                               MIN_STROKE_WIDTH),
 929                         getStrokeType(),
 930                         getStrokeLineCap(),


1498         }
1499 
1500         public boolean canSetMiterLimit() {
1501             return (miterLimit == null) || !miterLimit.isBound();
1502         }
1503 
1504         public boolean canSetDashOffset() {
1505             return (dashOffset == null) || !dashOffset.isBound();
1506         }
1507 
1508         public boolean hasDashArray() {
1509             return (dashArray != null);
1510         }
1511 
1512         private void invalidated(final CssMetaData<Shape, ?> propertyCssKey) {
1513             NodeHelper.markDirty(Shape.this, DirtyBits.SHAPE_STROKEATTRS);
1514             strokeAttributesDirty = true;
1515             if (propertyCssKey != StyleableProperties.STROKE_DASH_OFFSET) {
1516                 // all stroke attributes change geometry except for the
1517                 // stroke dash offset
1518                 impl_geomChanged();
1519             }
1520         }
1521     }
1522 
1523     /**
1524      * @treatAsPrivate implementation detail
1525      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1526      */
1527     @Deprecated
1528     @Override
1529     public Object impl_processMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
1530         return alg.processLeafNode(this, ctx);
1531     }
1532 
1533     // PENDING_DOC_REVIEW
1534     /**
1535      * Returns a new {@code Shape} which is created as a union of the specified
1536      * input shapes.
1537      * <p>
1538      * The operation works with geometric areas occupied by the input shapes.
1539      * For a single {@code Shape} such area includes the area occupied by the
1540      * fill if the shape has a non-null fill and the area occupied by the stroke
1541      * if the shape has a non-null stroke. So the area is empty for a shape
1542      * with {@code null} stroke and {@code null} fill. The area of an input
1543      * shape considered by the operation is independent on the type and
1544      * configuration of the paint used for fill or stroke. Before the final
1545      * operation the areas of the input shapes are transformed to the parent
1546      * coordinate space of their respective topmost parent nodes.
1547      * <p>
1548      * The resulting shape will include areas that were contained in any of the
1549      * input shapes.


1699                         fillShape, strokeType, strokeWidth, strokeLineCap,
1700                         strokeLineJoin, strokeMiterLimit,
1701                         dashArray, (float) getStrokeDashOffset());
1702 
1703         if (mode == NGShape.Mode.STROKE) {
1704             return createTransformedArea(strokeShape, transform);
1705         }
1706 
1707         // fill and stroke
1708         final Area combinedArea = new Area(fillShape);
1709         combinedArea.add(new Area(strokeShape));
1710 
1711         return createTransformedArea(combinedArea, transform);
1712     }
1713 
1714     private static BaseTransform calculateNodeToSceneTransform(Node node) {
1715         final Affine3D cumulativeTransformation = new Affine3D();
1716 
1717         do {
1718             cumulativeTransformation.preConcatenate(
1719                     node.impl_getLeafTransform());
1720             node = node.getParent();
1721         } while (node != null);
1722 
1723         return cumulativeTransformation;
1724     }
1725 
1726     private static Area createTransformedArea(
1727             final com.sun.javafx.geom.Shape geomShape,
1728             final BaseTransform transform) {
1729         return transform.isIdentity()
1730                    ? new Area(geomShape)
1731                    : new Area(geomShape.getPathIterator(transform));
1732     }
1733 
1734     private static Path createFromGeomShape(
1735             final com.sun.javafx.geom.Shape geomShape) {
1736         final Path path = new Path();
1737         final ObservableList<PathElement> elements = path.getElements();
1738 
1739         final PathIterator iterator = geomShape.getPathIterator(null);




 116  * the shape.
 117  * @since JavaFX 2.0
 118  */
 119 public abstract class Shape extends Node {
 120 
 121     static {
 122         // This is used by classes in different packages to get access to
 123         // private and package private methods.
 124         ShapeHelper.setShapeAccessor(new ShapeHelper.ShapeAccessor() {
 125             @Override
 126             public void doUpdatePeer(Node node) {
 127                 ((Shape) node).doUpdatePeer();
 128             }
 129 
 130             @Override
 131             public void doMarkDirty(Node node, DirtyBits dirtyBit) {
 132                 ((Shape) node).doMarkDirty(dirtyBit);
 133             }
 134 
 135             @Override
 136             public BaseBounds doComputeGeomBounds(Node node,
 137             BaseBounds bounds, BaseTransform tx) {
 138                 return ((Shape) node).doComputeGeomBounds(bounds, tx);
 139             }
 140 
 141             @Override
 142             public boolean doComputeContains(Node node, double localX, double localY) {
 143                 return ((Shape) node).doComputeContains(localX, localY);
 144             }
 145 
 146             @Override
 147             public Object doProcessMXNode(Node node, MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {
 148                 return ((Shape) node).doProcessMXNode(alg, ctx);
 149             }
 150 
 151             @Override
 152             public Paint doCssGetFillInitialValue(Shape shape) {
 153                 return shape.doCssGetFillInitialValue();
 154             }
 155 
 156             @Override
 157             public Paint doCssGetStrokeInitialValue(Shape shape) {
 158                 return shape.doCssGetStrokeInitialValue();
 159             }
 160 
 161             @Override
 162             public NGShape.Mode getMode(Shape shape) {
 163                 return shape.getMode();
 164             }
 165 
 166             @Override
 167             public void setMode(Shape shape, NGShape.Mode mode) {
 168                 shape.setMode(mode);
 169             }
 170 
 171             @Override


 390             return NGShape.Mode.EMPTY;
 391         }
 392     }
 393 
 394     NGShape.Mode getMode() {
 395         return mode;
 396     }
 397 
 398     void setMode(NGShape.Mode mode) {
 399         mode = mode;
 400     }
 401 
 402     private NGShape.Mode mode = NGShape.Mode.FILL;
 403 
 404     private void checkModeChanged() {
 405         NGShape.Mode newMode = computeMode();
 406         if (mode != newMode) {
 407             mode = newMode;
 408 
 409             NodeHelper.markDirty(this, DirtyBits.SHAPE_MODE);
 410             NodeHelper.geomChanged(this);
 411         }
 412     }
 413 
 414     /**
 415      * Defines parameters to fill the interior of an {@code Shape}
 416      * using the settings of the {@code Paint} context.
 417      * The default value is {@code Color.BLACK} for all shapes except
 418      * Line, Polyline, and Path. The default value is {@code null} for
 419      * those shapes.
 420      */
 421     private ObjectProperty<Paint> fill;
 422 
 423 
 424     public final void setFill(Paint value) {
 425         fillProperty().set(value);
 426     }
 427 
 428     public final Paint getFill() {
 429         return fill == null ? Color.BLACK : fill.get();
 430     }


 479     /**
 480      * Defines parameters of a stroke that is drawn around the outline of
 481      * a {@code Shape} using the settings of the specified {@code Paint}.
 482      * The default value is {@code null} for all shapes except
 483      * Line, Polyline, and Path. The default value is {@code Color.BLACK} for
 484      * those shapes.
 485      */
 486     private ObjectProperty<Paint> stroke;
 487 
 488 
 489     public final void setStroke(Paint value) {
 490         strokeProperty().set(value);
 491     }
 492 
 493     private final AbstractNotifyListener platformImageChangeListener =
 494             new AbstractNotifyListener() {
 495         @Override
 496         public void invalidated(Observable valueModel) {
 497             NodeHelper.markDirty(Shape.this, DirtyBits.SHAPE_FILL);
 498             NodeHelper.markDirty(Shape.this, DirtyBits.SHAPE_STROKE);
 499             NodeHelper.geomChanged(Shape.this);
 500             checkModeChanged();
 501         }
 502     };
 503 
 504     public final Paint getStroke() {
 505         return stroke == null ? null : stroke.get();
 506     }
 507 
 508     Paint old_stroke;
 509     public final ObjectProperty<Paint> strokeProperty() {
 510         if (stroke == null) {
 511             stroke = new StyleableObjectProperty<Paint>() {
 512 
 513                 boolean needsListener = false;
 514 
 515                 @Override public void invalidated() {
 516 
 517                     Paint _stroke = get();
 518 
 519                     if (needsListener) {


 889      * @return The CssMetaData associated with this class, which may include the
 890      * CssMetaData of its super classes.
 891      * @since JavaFX 8.0
 892      */
 893     public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
 894         return StyleableProperties.STYLEABLES;
 895     }
 896 
 897     /**
 898      * {@inheritDoc}
 899      *
 900      * @since JavaFX 8.0
 901      */
 902 
 903 
 904     @Override
 905     public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
 906         return getClassCssMetaData();
 907     }
 908 
 909     /*
 910      * Note: This method MUST only be called via its accessor method.

 911      */
 912     private BaseBounds doComputeGeomBounds(BaseBounds bounds,


 913                                              BaseTransform tx) {
 914         return computeShapeBounds(bounds, tx, ShapeHelper.configShape(this));
 915     }
 916 
 917     /*
 918      * Note: This method MUST only be called via its accessor method.

 919      */
 920     private boolean doComputeContains(double localX, double localY) {


 921         return computeShapeContains(localX, localY, ShapeHelper.configShape(this));
 922     }
 923 
 924     private static final double MIN_STROKE_WIDTH = 0.0f;
 925     private static final double MIN_STROKE_MITER_LIMIT = 1.0f;
 926 
 927     private void updatePGShape() {
 928         final NGShape peer = NodeHelper.getPeer(this);
 929         if (strokeAttributesDirty && (getStroke() != null)) {
 930             // set attributes of stroke only when stroke paint is not null
 931             final float[] pgDashArray =
 932                     (hasStrokeDashArray())
 933                             ? toPGDashArray(getStrokeDashArray())
 934                             : DEFAULT_PG_STROKE_DASH_ARRAY;
 935 
 936             peer.setDrawStroke(
 937                         (float)Utils.clampMin(getStrokeWidth(),
 938                                               MIN_STROKE_WIDTH),
 939                         getStrokeType(),
 940                         getStrokeLineCap(),


1508         }
1509 
1510         public boolean canSetMiterLimit() {
1511             return (miterLimit == null) || !miterLimit.isBound();
1512         }
1513 
1514         public boolean canSetDashOffset() {
1515             return (dashOffset == null) || !dashOffset.isBound();
1516         }
1517 
1518         public boolean hasDashArray() {
1519             return (dashArray != null);
1520         }
1521 
1522         private void invalidated(final CssMetaData<Shape, ?> propertyCssKey) {
1523             NodeHelper.markDirty(Shape.this, DirtyBits.SHAPE_STROKEATTRS);
1524             strokeAttributesDirty = true;
1525             if (propertyCssKey != StyleableProperties.STROKE_DASH_OFFSET) {
1526                 // all stroke attributes change geometry except for the
1527                 // stroke dash offset
1528                 NodeHelper.geomChanged(Shape.this);
1529             }
1530         }
1531     }
1532 
1533     /*
1534      * Note: This method MUST only be called via its accessor method.

1535      */
1536     private Object doProcessMXNode(MXNodeAlgorithm alg, MXNodeAlgorithmContext ctx) {


1537         return alg.processLeafNode(this, ctx);
1538     }
1539 
1540     // PENDING_DOC_REVIEW
1541     /**
1542      * Returns a new {@code Shape} which is created as a union of the specified
1543      * input shapes.
1544      * <p>
1545      * The operation works with geometric areas occupied by the input shapes.
1546      * For a single {@code Shape} such area includes the area occupied by the
1547      * fill if the shape has a non-null fill and the area occupied by the stroke
1548      * if the shape has a non-null stroke. So the area is empty for a shape
1549      * with {@code null} stroke and {@code null} fill. The area of an input
1550      * shape considered by the operation is independent on the type and
1551      * configuration of the paint used for fill or stroke. Before the final
1552      * operation the areas of the input shapes are transformed to the parent
1553      * coordinate space of their respective topmost parent nodes.
1554      * <p>
1555      * The resulting shape will include areas that were contained in any of the
1556      * input shapes.


1706                         fillShape, strokeType, strokeWidth, strokeLineCap,
1707                         strokeLineJoin, strokeMiterLimit,
1708                         dashArray, (float) getStrokeDashOffset());
1709 
1710         if (mode == NGShape.Mode.STROKE) {
1711             return createTransformedArea(strokeShape, transform);
1712         }
1713 
1714         // fill and stroke
1715         final Area combinedArea = new Area(fillShape);
1716         combinedArea.add(new Area(strokeShape));
1717 
1718         return createTransformedArea(combinedArea, transform);
1719     }
1720 
1721     private static BaseTransform calculateNodeToSceneTransform(Node node) {
1722         final Affine3D cumulativeTransformation = new Affine3D();
1723 
1724         do {
1725             cumulativeTransformation.preConcatenate(
1726                     NodeHelper.getLeafTransform(node));
1727             node = node.getParent();
1728         } while (node != null);
1729 
1730         return cumulativeTransformation;
1731     }
1732 
1733     private static Area createTransformedArea(
1734             final com.sun.javafx.geom.Shape geomShape,
1735             final BaseTransform transform) {
1736         return transform.isIdentity()
1737                    ? new Area(geomShape)
1738                    : new Area(geomShape.getPathIterator(transform));
1739     }
1740 
1741     private static Path createFromGeomShape(
1742             final com.sun.javafx.geom.Shape geomShape) {
1743         final Path path = new Path();
1744         final ObservableList<PathElement> elements = path.getElements();
1745 
1746         final PathIterator iterator = geomShape.getPathIterator(null);


< prev index next >