-
Bug
-
Resolution: Unresolved
-
P3
-
8, 9
I noticed that when I used a dashed stroke with offsets {2.0, 2.0}, SQUARE and thickness 1, and set the StrokeType outside, the stroke was actually a line and not dashed at all. See this picture which compares the same rectangle but with centered and outside as stroke types:
http://250kb.de/u/141113/p/Whvnz2cD0EZK.png
I was baffled by this and made up a program to look what was going on.
consider the following test program:
===============================================
public class LineStrokeDashTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
StackPane pane = new StackPane();
final Color c1 = Color.rgb(20, 20, 220, 0.5);
final Color c2 = Color.rgb(220, 20, 20, 0.5);
final Color c3 = Color.rgb(220, 20, 220, 0.5);
// how it is
final Rectangle rectangle = createRectangle(StrokeLineCap.ROUND, StrokeType.OUTSIDE, c1);
final Rectangle rectangle2 = createRectangle(StrokeLineCap.ROUND, StrokeType.CENTERED, c2);
final Rectangle rectangle3 = createRectangle(StrokeLineCap.ROUND, StrokeType.INSIDE, c3);
// how it (kinda) should look like
// final Rectangle rectangle = createRectangle2(new Rectangle(3, 3, 17, 17), StrokeLineCap.ROUND, StrokeType.CENTERED, c1);
//
// final Rectangle rectangle2 = createRectangle2(new Rectangle(1.5, 1.5, 20, 20), StrokeLineCap.ROUND, StrokeType.CENTERED, c2);
//
// final Rectangle rectangle3 = createRectangle2(new Rectangle(0, 0, 23, 23), StrokeLineCap.ROUND, StrokeType.CENTERED, c3);
pane.getChildren().add(rectangle);
pane.getChildren().add(rectangle2);
pane.getChildren().add(rectangle3);
Scene scene = new Scene(pane, 500, 500, Color.WHITE);
primaryStage.setScene(scene);
primaryStage.show();
}
private Rectangle createRectangle(StrokeLineCap strokeLineCap, StrokeType strokeType, Color stroke) {
Rectangle rectangle = new Rectangle(0, 0, 20, 20);
rectangle.setFill(null);
rectangle.setStroke(stroke);
rectangle.getStrokeDashArray().clear();
rectangle.setStrokeLineCap(strokeLineCap);
rectangle.setStrokeMiterLimit(10.0d);
rectangle.setStrokeWidth(3.0d);
rectangle.setStrokeLineJoin(StrokeLineJoin.MITER);
rectangle.getStrokeDashArray().addAll(2.0, 8.0);
rectangle.setStrokeType(strokeType);
rectangle.getTransforms().add(new Scale(10, 10));
return rectangle;
}
private Rectangle createRectangle2(Rectangle rectangle, StrokeLineCap strokeLineCap, StrokeType strokeType, Color stroke) {
rectangle.setFill(null);
rectangle.setStroke(stroke);
rectangle.getStrokeDashArray().clear();
rectangle.setStrokeLineCap(strokeLineCap);
rectangle.setStrokeMiterLimit(10.0d);
rectangle.setStrokeWidth(3.0d);
rectangle.setStrokeLineJoin(StrokeLineJoin.MITER);
rectangle.getStrokeDashArray().addAll(2.0, 8.0);
rectangle.setStrokeType(strokeType);
rectangle.getTransforms().add(new Scale(10, 10));
return rectangle;
}
}
===============================================
If you run this, the result is depicted here:
http://250kb.de/u/141113/p/FeNzKjL152JC.png
You can see that the algorithm to make the stroke outside/inside is to blow the thickness of the stroke to twice the size and then just crop the not wanted part. Using the BUTT as lineCap with this is fine. But since the SQUARE and ROUND lineCaps use half the stroke width as length for the cap, the dashes enlarge and the offsets are wrong. This explains why in the above example the dashed lines of the rectangle melt together to a single line when set to outside.
I would have expected as outcome when setting outside or inside to be what you can see when you comment the lines in the test program. The result is here:
http://250kb.de/u/141113/p/7sDg96sh75sC.png
As you can see, the stroke is moved to the actual outside or inside and not just blown up and cropped. This is a mock up and thus not perfect, but it gives the idea of what it should look like.
http://250kb.de/u/141113/p/Whvnz2cD0EZK.png
I was baffled by this and made up a program to look what was going on.
consider the following test program:
===============================================
public class LineStrokeDashTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
StackPane pane = new StackPane();
final Color c1 = Color.rgb(20, 20, 220, 0.5);
final Color c2 = Color.rgb(220, 20, 20, 0.5);
final Color c3 = Color.rgb(220, 20, 220, 0.5);
// how it is
final Rectangle rectangle = createRectangle(StrokeLineCap.ROUND, StrokeType.OUTSIDE, c1);
final Rectangle rectangle2 = createRectangle(StrokeLineCap.ROUND, StrokeType.CENTERED, c2);
final Rectangle rectangle3 = createRectangle(StrokeLineCap.ROUND, StrokeType.INSIDE, c3);
// how it (kinda) should look like
// final Rectangle rectangle = createRectangle2(new Rectangle(3, 3, 17, 17), StrokeLineCap.ROUND, StrokeType.CENTERED, c1);
//
// final Rectangle rectangle2 = createRectangle2(new Rectangle(1.5, 1.5, 20, 20), StrokeLineCap.ROUND, StrokeType.CENTERED, c2);
//
// final Rectangle rectangle3 = createRectangle2(new Rectangle(0, 0, 23, 23), StrokeLineCap.ROUND, StrokeType.CENTERED, c3);
pane.getChildren().add(rectangle);
pane.getChildren().add(rectangle2);
pane.getChildren().add(rectangle3);
Scene scene = new Scene(pane, 500, 500, Color.WHITE);
primaryStage.setScene(scene);
primaryStage.show();
}
private Rectangle createRectangle(StrokeLineCap strokeLineCap, StrokeType strokeType, Color stroke) {
Rectangle rectangle = new Rectangle(0, 0, 20, 20);
rectangle.setFill(null);
rectangle.setStroke(stroke);
rectangle.getStrokeDashArray().clear();
rectangle.setStrokeLineCap(strokeLineCap);
rectangle.setStrokeMiterLimit(10.0d);
rectangle.setStrokeWidth(3.0d);
rectangle.setStrokeLineJoin(StrokeLineJoin.MITER);
rectangle.getStrokeDashArray().addAll(2.0, 8.0);
rectangle.setStrokeType(strokeType);
rectangle.getTransforms().add(new Scale(10, 10));
return rectangle;
}
private Rectangle createRectangle2(Rectangle rectangle, StrokeLineCap strokeLineCap, StrokeType strokeType, Color stroke) {
rectangle.setFill(null);
rectangle.setStroke(stroke);
rectangle.getStrokeDashArray().clear();
rectangle.setStrokeLineCap(strokeLineCap);
rectangle.setStrokeMiterLimit(10.0d);
rectangle.setStrokeWidth(3.0d);
rectangle.setStrokeLineJoin(StrokeLineJoin.MITER);
rectangle.getStrokeDashArray().addAll(2.0, 8.0);
rectangle.setStrokeType(strokeType);
rectangle.getTransforms().add(new Scale(10, 10));
return rectangle;
}
}
===============================================
If you run this, the result is depicted here:
http://250kb.de/u/141113/p/FeNzKjL152JC.png
You can see that the algorithm to make the stroke outside/inside is to blow the thickness of the stroke to twice the size and then just crop the not wanted part. Using the BUTT as lineCap with this is fine. But since the SQUARE and ROUND lineCaps use half the stroke width as length for the cap, the dashes enlarge and the offsets are wrong. This explains why in the above example the dashed lines of the rectangle melt together to a single line when set to outside.
I would have expected as outcome when setting outside or inside to be what you can see when you comment the lines in the test program. The result is here:
http://250kb.de/u/141113/p/7sDg96sh75sC.png
As you can see, the stroke is moved to the actual outside or inside and not just blown up and cropped. This is a mock up and thus not perfect, but it gives the idea of what it should look like.
- relates to
-
JDK-8089063 Dotted Border clipped to the outside
-
- Resolved
-