70 r.setHeight(100); 71 r.setArcWidth(20); 72 r.setArcHeight(20); 73 </PRE> 74 * @since JavaFX 2.0 75 */ 76 public class Rectangle extends Shape { 77 static { 78 RectangleHelper.setRectangleAccessor(new RectangleHelper.RectangleAccessor() { 79 @Override 80 public NGNode doCreatePeer(Node node) { 81 return ((Rectangle) node).doCreatePeer(); 82 } 83 84 @Override 85 public void doUpdatePeer(Node node) { 86 ((Rectangle) node).doUpdatePeer(); 87 } 88 89 @Override 90 public com.sun.javafx.geom.Shape doConfigShape(Shape shape) { 91 return ((Rectangle) shape).doConfigShape(); 92 } 93 }); 94 } 95 96 private final RoundRectangle2D shape = new RoundRectangle2D(); 97 98 private static final int NON_RECTILINEAR_TYPE_MASK = ~( 99 BaseTransform.TYPE_TRANSLATION | 100 BaseTransform.TYPE_MASK_SCALE | 101 BaseTransform.TYPE_QUADRANT_ROTATION | 102 BaseTransform.TYPE_FLIP); 103 104 { 105 // To initialize the class helper at the begining each constructor of this class 106 RectangleHelper.initHelper(this); 107 } 108 109 /** 155 private DoubleProperty x; 156 157 158 public final void setX(double value) { 159 if (x != null || value != 0.0) { 160 xProperty().set(value); 161 } 162 } 163 164 public final double getX() { 165 return x == null ? 0.0 : x.get(); 166 } 167 168 public final DoubleProperty xProperty() { 169 if (x == null) { 170 x = new DoublePropertyBase() { 171 172 @Override 173 public void invalidated() { 174 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 175 impl_geomChanged(); 176 } 177 178 @Override 179 public Object getBean() { 180 return Rectangle.this; 181 } 182 183 @Override 184 public String getName() { 185 return "x"; 186 } 187 }; 188 } 189 return x; 190 } 191 192 /** 193 * Defines the Y coordinate of the upper-left corner of the rectangle. 194 * 195 * @defaultValue 0.0 196 */ 197 private DoubleProperty y; 198 199 public final void setY(double value) { 200 if (y != null || value != 0.0) { 201 yProperty().set(value); 202 } 203 } 204 205 public final double getY() { 206 return y == null ? 0.0 : y.get(); 207 } 208 209 public final DoubleProperty yProperty() { 210 if (y == null) { 211 y = new DoublePropertyBase() { 212 213 @Override 214 public void invalidated() { 215 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 216 impl_geomChanged(); 217 } 218 219 @Override 220 public Object getBean() { 221 return Rectangle.this; 222 } 223 224 @Override 225 public String getName() { 226 return "y"; 227 } 228 }; 229 } 230 return y; 231 } 232 233 /** 234 * Defines the width of the rectangle. 235 * 236 * @defaultValue 0.0 237 */ 238 private final DoubleProperty width = new DoublePropertyBase() { 239 240 @Override 241 public void invalidated() { 242 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 243 impl_geomChanged(); 244 } 245 246 @Override 247 public Object getBean() { 248 return Rectangle.this; 249 } 250 251 @Override 252 public String getName() { 253 return "width"; 254 } 255 }; 256 257 public final void setWidth(double value) { 258 width.set(value); 259 } 260 261 public final double getWidth() { 262 return width.get(); 263 } 264 265 public final DoubleProperty widthProperty() { 266 return width; 267 } 268 269 /** 270 * Defines the height of the rectangle. 271 * 272 * @defaultValue 0.0 273 */ 274 private final DoubleProperty height = new DoublePropertyBase() { 275 276 @Override 277 public void invalidated() { 278 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 279 impl_geomChanged(); 280 } 281 282 @Override 283 public Object getBean() { 284 return Rectangle.this; 285 } 286 287 @Override 288 public String getName() { 289 return "height"; 290 } 291 }; 292 293 294 public final void setHeight(double value) { 295 height.set(value); 296 } 297 298 public final double getHeight() { 299 return height.get(); 487 // If we are a round rectangle then MITER can produce anomalous 488 // results for very thin or very wide corner arcs when the bezier 489 // curves that approximate the arcs become so distorted that they 490 // shoot out MITER-like extensions. This effect complicates matters 491 // because it makes such "round" rectangles non-round, and also 492 // because it means we might have to pad the bounds to account 493 // for this rare and unpredictable circumstance. 494 // To avoid the problem, we set the Join style to BEVEL for any 495 // rounded rect. The BEVEL join style is more predictable for 496 // anomalous angles and is the simplest join style to compute in 497 // the stroking code. 498 // For non-rounded rectangles, the angles are all 90 degrees and so 499 // the computations are both simple and non-problematic so we pass on 500 // the join style unmodified to the PG layer. 501 if ((getArcWidth() > 0) && (getArcHeight() > 0)) { 502 return StrokeLineJoin.BEVEL; 503 } 504 return t; 505 } 506 507 /** 508 * @treatAsPrivate implementation detail 509 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 510 */ 511 @Deprecated 512 @Override 513 public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) { 514 // if there is no fill or stroke, then there are no bounds. The bounds 515 // must be marked empty in this case to distinguish it from 0,0,0,0 516 // which would actually contribute to the bounds of a group. 517 if (getMode() == NGShape.Mode.EMPTY) { 518 return bounds.makeEmpty(); 519 } 520 if ((getArcWidth() > 0) && (getArcHeight() > 0) 521 && ((tx.getType() & NON_RECTILINEAR_TYPE_MASK) != 0)) { 522 return computeShapeBounds(bounds, tx, ShapeHelper.configShape(this)); 523 } 524 double upad; 525 double dpad; 526 if ((getMode() == NGShape.Mode.FILL) || (getStrokeType() == StrokeType.INSIDE)) { 527 upad = dpad = 0; 528 } else { 529 upad = getStrokeWidth(); 530 if (getStrokeType() == StrokeType.CENTERED) { 531 upad /= 2.0; 532 } 533 dpad = 0.0f; | 70 r.setHeight(100); 71 r.setArcWidth(20); 72 r.setArcHeight(20); 73 </PRE> 74 * @since JavaFX 2.0 75 */ 76 public class Rectangle extends Shape { 77 static { 78 RectangleHelper.setRectangleAccessor(new RectangleHelper.RectangleAccessor() { 79 @Override 80 public NGNode doCreatePeer(Node node) { 81 return ((Rectangle) node).doCreatePeer(); 82 } 83 84 @Override 85 public void doUpdatePeer(Node node) { 86 ((Rectangle) node).doUpdatePeer(); 87 } 88 89 @Override 90 public BaseBounds doComputeGeomBounds(Node node, 91 BaseBounds bounds, BaseTransform tx) { 92 return ((Rectangle) node).doComputeGeomBounds(bounds, tx); 93 } 94 95 @Override 96 public com.sun.javafx.geom.Shape doConfigShape(Shape shape) { 97 return ((Rectangle) shape).doConfigShape(); 98 } 99 }); 100 } 101 102 private final RoundRectangle2D shape = new RoundRectangle2D(); 103 104 private static final int NON_RECTILINEAR_TYPE_MASK = ~( 105 BaseTransform.TYPE_TRANSLATION | 106 BaseTransform.TYPE_MASK_SCALE | 107 BaseTransform.TYPE_QUADRANT_ROTATION | 108 BaseTransform.TYPE_FLIP); 109 110 { 111 // To initialize the class helper at the begining each constructor of this class 112 RectangleHelper.initHelper(this); 113 } 114 115 /** 161 private DoubleProperty x; 162 163 164 public final void setX(double value) { 165 if (x != null || value != 0.0) { 166 xProperty().set(value); 167 } 168 } 169 170 public final double getX() { 171 return x == null ? 0.0 : x.get(); 172 } 173 174 public final DoubleProperty xProperty() { 175 if (x == null) { 176 x = new DoublePropertyBase() { 177 178 @Override 179 public void invalidated() { 180 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 181 NodeHelper.geomChanged(Rectangle.this); 182 } 183 184 @Override 185 public Object getBean() { 186 return Rectangle.this; 187 } 188 189 @Override 190 public String getName() { 191 return "x"; 192 } 193 }; 194 } 195 return x; 196 } 197 198 /** 199 * Defines the Y coordinate of the upper-left corner of the rectangle. 200 * 201 * @defaultValue 0.0 202 */ 203 private DoubleProperty y; 204 205 public final void setY(double value) { 206 if (y != null || value != 0.0) { 207 yProperty().set(value); 208 } 209 } 210 211 public final double getY() { 212 return y == null ? 0.0 : y.get(); 213 } 214 215 public final DoubleProperty yProperty() { 216 if (y == null) { 217 y = new DoublePropertyBase() { 218 219 @Override 220 public void invalidated() { 221 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 222 NodeHelper.geomChanged(Rectangle.this); 223 } 224 225 @Override 226 public Object getBean() { 227 return Rectangle.this; 228 } 229 230 @Override 231 public String getName() { 232 return "y"; 233 } 234 }; 235 } 236 return y; 237 } 238 239 /** 240 * Defines the width of the rectangle. 241 * 242 * @defaultValue 0.0 243 */ 244 private final DoubleProperty width = new DoublePropertyBase() { 245 246 @Override 247 public void invalidated() { 248 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 249 NodeHelper.geomChanged(Rectangle.this); 250 } 251 252 @Override 253 public Object getBean() { 254 return Rectangle.this; 255 } 256 257 @Override 258 public String getName() { 259 return "width"; 260 } 261 }; 262 263 public final void setWidth(double value) { 264 width.set(value); 265 } 266 267 public final double getWidth() { 268 return width.get(); 269 } 270 271 public final DoubleProperty widthProperty() { 272 return width; 273 } 274 275 /** 276 * Defines the height of the rectangle. 277 * 278 * @defaultValue 0.0 279 */ 280 private final DoubleProperty height = new DoublePropertyBase() { 281 282 @Override 283 public void invalidated() { 284 NodeHelper.markDirty(Rectangle.this, DirtyBits.NODE_GEOMETRY); 285 NodeHelper.geomChanged(Rectangle.this); 286 } 287 288 @Override 289 public Object getBean() { 290 return Rectangle.this; 291 } 292 293 @Override 294 public String getName() { 295 return "height"; 296 } 297 }; 298 299 300 public final void setHeight(double value) { 301 height.set(value); 302 } 303 304 public final double getHeight() { 305 return height.get(); 493 // If we are a round rectangle then MITER can produce anomalous 494 // results for very thin or very wide corner arcs when the bezier 495 // curves that approximate the arcs become so distorted that they 496 // shoot out MITER-like extensions. This effect complicates matters 497 // because it makes such "round" rectangles non-round, and also 498 // because it means we might have to pad the bounds to account 499 // for this rare and unpredictable circumstance. 500 // To avoid the problem, we set the Join style to BEVEL for any 501 // rounded rect. The BEVEL join style is more predictable for 502 // anomalous angles and is the simplest join style to compute in 503 // the stroking code. 504 // For non-rounded rectangles, the angles are all 90 degrees and so 505 // the computations are both simple and non-problematic so we pass on 506 // the join style unmodified to the PG layer. 507 if ((getArcWidth() > 0) && (getArcHeight() > 0)) { 508 return StrokeLineJoin.BEVEL; 509 } 510 return t; 511 } 512 513 /* 514 * Note: This method MUST only be called via its accessor method. 515 */ 516 private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) { 517 // if there is no fill or stroke, then there are no bounds. The bounds 518 // must be marked empty in this case to distinguish it from 0,0,0,0 519 // which would actually contribute to the bounds of a group. 520 if (getMode() == NGShape.Mode.EMPTY) { 521 return bounds.makeEmpty(); 522 } 523 if ((getArcWidth() > 0) && (getArcHeight() > 0) 524 && ((tx.getType() & NON_RECTILINEAR_TYPE_MASK) != 0)) { 525 return computeShapeBounds(bounds, tx, ShapeHelper.configShape(this)); 526 } 527 double upad; 528 double dpad; 529 if ((getMode() == NGShape.Mode.FILL) || (getStrokeType() == StrokeType.INSIDE)) { 530 upad = dpad = 0; 531 } else { 532 upad = getStrokeWidth(); 533 if (getStrokeType() == StrokeType.CENTERED) { 534 upad /= 2.0; 535 } 536 dpad = 0.0f; |