I have the following SVG document:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg id="svg602"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="324.02335" height="689.724"
space="preserve" version="1.0">
<defs id="defs604">
<linearGradient id="linearGradient3034">
<stop id="stop3035" offset="0"
style="stop-color:#0000ff;stop-opacity:1" />
<stop id="stop3036" offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<linearGradient id="linearGradient3542"
xlink:href="#linearGradient3034"
x1="10" y1="10"
x2="210" y2="210"
gradientUnits="userSpaceOnUse" />
</defs>
<rect id="r1" x="10" y="10" width="200" height="200"
style="fill:url(#linearGradient3542);stroke:none" />
</svg>
I am trying to achieve the same in JavaFX with the following code:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class GradientSample extends Application {
public static void main(String[] args) { launch(args); }
@Override
public void start(Stage primaryStage) {
Group mainGroup = new Group();
Rectangle r = new Rectangle(10, 10, 200, 200);
Stop[] stops = new Stop[] { new Stop(0, new Color(0.0, 0.0, 1.0, 1.0)),
new Stop(1, new Color(1.0, 1.0, 1.0, 0.0)) };
LinearGradient lg = new LinearGradient(10, 10, 210, 210, false, CycleMethod.NO_CYCLE,
stops);
r.setFill(lg);
mainGroup.getChildren().add(r);
Scene scene = new Scene(mainGroup, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
However, the SVG is rendered (in Inkscape) like this:

while the JavaFX scene is rendered like this:

Obviously, the stop opacity (0.0) of the second stop is not considered by JavaFX (if I set the opacity to 1.0 in the SVG file, it is rendered like the JavaFX scene).
Did I miss something or should I consider this as a bug?
Is there any other solution how to achieve a Stop's opacity other than 1.0 in JavaFX?
You have found a bug, indeed, but not in the opacity!
I've checked first that opacity was working. For instance, you can lay some label beneath the rectangle, and you will see it, so that is not the issue.
So then I exported the image as png, and edited it. I found out that opacity was well interpolated from 1 to 0, from the top left corner to the right bottom one.
To my surprise, red and green were 0 on every pixel!!
Trying to find a reported bug, I didn't find any, but I got the idea of using different rendering pipelines.
Using -Dprism.order with the options d3d (Windows), es2 (Mac) and sw, all gave the same wrong result. But the old and deprecated j2d worked fine on Windows!
To check it, I've slightly modified your code:
public void start(Stage primaryStage) {
Group mainGroup = new Group();
Rectangle r = new Rectangle(0, 0, 200, 200);
Stop[] stops = new Stop[] { new Stop(0, new Color(0.0, 0.0, 1.0, 1.0)),
new Stop(1, new Color(1.0, 1.0, 1.0, 0.0)) };
LinearGradient lg = new LinearGradient(0, 0, 1, 1, true, CycleMethod.NO_CYCLE, stops);
r.setFill(lg);
mainGroup.getChildren().add(r);
Scene scene = new Scene(mainGroup, 200, 200);
scene.setFill(Color.TRANSPARENT);
primaryStage.setScene(scene);
primaryStage.show();
WritableImage image = scene.snapshot(null);
PixelReader pixelReader = image.getPixelReader();
System.out.println("Color: " + pixelReader.getColor((int)image.getWidth()/2, (int)image.getHeight()/2));
}
Running with the regular pipelines you will see this result:
Color: 0x0000ff7f
and only running with -Dprism.order=j2d you will get:
Color: 0x7e7eff7f
As I mentioned before, opacity is interpolated, but not the RGB color: In this case it seems the RGB is the one from the first Stop.
So we may think of a regression at some point that should be reported.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With