8027708: NASHORN TEST: Create Nashorn test that draws image step-by-step using JavaFX canvas
Reviewed-by: jlaskey, lagergren
@ -372,6 +372,12 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
|
||||
|
||||
<copy file="${file.reference.jfxrt.jar}" todir="dist"/>
|
||||
|
||||
<condition property="jfx.prism.order" value="-Dprism.order=j2d" else=" ">
|
||||
<not>
|
||||
<os family="mac"/>
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<testng outputdir="${build.test.results.dir}" classfilesetref="test.classes"
|
||||
verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}">
|
||||
<jvmarg line="${ext.class.path}"/>
|
||||
@ -380,6 +386,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
|
||||
<propertyref prefix="testjfx-test-sys-prop."/>
|
||||
<mapper from="testjfx-test-sys-prop.*" to="*" type="glob"/>
|
||||
</propertyset>
|
||||
<sysproperty key="test.fork.jvm.options" value="${testjfx-test-sys-prop.test.fork.jvm.options} ${jfx.prism.order}"/>
|
||||
<classpath>
|
||||
<pathelement path="${testjfx.run.test.classpath}"/>
|
||||
</classpath>
|
||||
|
@ -230,7 +230,7 @@ testjfx.run.test.classpath=\
|
||||
${file.reference.jemmyawtinput.jar}${path.separator}\
|
||||
${file.reference.testng.jar}${path.separator}\
|
||||
${nashorn.internal.tests.jar}${path.separator}\
|
||||
${nashorn.api.tests.jar}
|
||||
${nashorn.api.tests.jar}
|
||||
|
||||
# testjfx VM options for script tests with @fork option
|
||||
testjfx-test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} -cp ${testjfx.run.test.classpath}
|
||||
|
@ -37,13 +37,24 @@ var ByWindowType = Java.type("org.jemmy.fx.ByWindowType");
|
||||
var Scene = Java.type("javafx.scene.Scene");
|
||||
var Stage = Java.type("javafx.stage.Stage");
|
||||
var File = Java.type("java.io.File");
|
||||
var Timer = Java.type("java.util.Timer");
|
||||
var TimerTask = Java.type("java.util.TimerTask");
|
||||
var OSInfo = Java.type("sun.awt.OSInfo");
|
||||
var OSType = Java.type("sun.awt.OSInfo.OSType");
|
||||
var StringBuffer = Java.type("java.lang.StringBuffer");
|
||||
var Paint = Java.type("javafx.scene.paint.Paint");
|
||||
var Color = Java.type("javafx.scene.paint.Color");
|
||||
var Image = Java.type("javafx.scene.image.Image");
|
||||
var Canvas = Java.type("javafx.scene.canvas.Canvas");
|
||||
var BorderPane = Java.type("javafx.scene.layout.BorderPane");
|
||||
var StackPane = Java.type("javafx.scene.layout.StackPane");
|
||||
var StrokeLineCap = Java.type("javafx.scene.shape.StrokeLineCap");
|
||||
var Platform = Java.type("javafx.application.Platform");
|
||||
var Runnable = Java.type("java.lang.Runnable");
|
||||
var RunnableExtend = Java.extend(Runnable);
|
||||
var AnimationTimer = Java.type("javafx.animation.AnimationTimer");
|
||||
var AnimationTimerExtend = Java.extend(AnimationTimer);
|
||||
var Timer = Java.type("java.util.Timer");
|
||||
var TimerTask = Java.type("java.util.TimerTask");
|
||||
|
||||
var WAIT = 2000;
|
||||
var TESTNAME = "test";
|
||||
var fsep = System.getProperty("file.separator");
|
||||
|
||||
@ -53,14 +64,16 @@ function checkImageAndExit() {
|
||||
run: function run() {
|
||||
var tmpdir = System.getProperty("java.io.tmpdir");
|
||||
var timenow = (new Date()).getTime();
|
||||
makeScreenShot(tmpdir + fsep + "screenshot" + timenow +".png");
|
||||
var dupImg = isDuplicateImages(tmpdir + fsep + "screenshot" + timenow +".png", __DIR__ + "jfx" + fsep + TESTNAME + fsep + "golden");
|
||||
(new File(mpdir + fsep + "screenshot" + timenow +".png")).delete();
|
||||
if (!dupImg) System.err.println("ERROR: screenshot does not match golden image");
|
||||
var scrShotTmp = tmpdir + fsep + "screenshot" + timenow +".png";
|
||||
var goldenImageDir = __DIR__ + "jfx" + fsep + TESTNAME + fsep + "golden";
|
||||
makeScreenShot(scrShotTmp);
|
||||
var dupImg = isDuplicateImages(scrShotTmp, goldenImageDir);
|
||||
(new File(scrShotTmp)).delete();
|
||||
if (!dupImg) System.err.println("ERROR: screenshot does not match the golden image");
|
||||
exit(0);
|
||||
}
|
||||
};
|
||||
raceTimer.schedule(timerTask, WAIT);
|
||||
raceTimer.schedule(timerTask, 100);
|
||||
}
|
||||
|
||||
function makeScreenShot(shootToImg) {
|
||||
@ -70,10 +83,10 @@ function makeScreenShot(shootToImg) {
|
||||
imageJemmy.save(shootToImg);
|
||||
}
|
||||
|
||||
function isDuplicateImages(file1, file2) {
|
||||
var f1 = new File(file1);
|
||||
function isDuplicateImages(screenShot, goldenDir) {
|
||||
var f1 = new File(screenShot);
|
||||
var f2;
|
||||
var sb = new StringBuffer(file2);
|
||||
var sb = new StringBuffer(goldenDir);
|
||||
if (OSInfo.getOSType() == OSType.WINDOWS) {
|
||||
f2 = new File(sb.append(fsep + "windows.png").toString());
|
||||
} else if (OSInfo.getOSType() == OSType.LINUX) {
|
||||
@ -81,8 +94,6 @@ function isDuplicateImages(file1, file2) {
|
||||
} else if (OSInfo.getOSType() == OSType.MACOSX) {
|
||||
f2 = new File(sb.append(fsep + "macosx.png").toString());
|
||||
}
|
||||
print(f1.getAbsolutePath());
|
||||
print(f2.getAbsolutePath());
|
||||
if (f1.exists() && f2.exists()) {
|
||||
var image1 = new AWTImage(PNGDecoder.decode(f1.getAbsolutePath()));
|
||||
var image2 = new AWTImage(PNGDecoder.decode(f2.getAbsolutePath()));
|
||||
|
@ -31,15 +31,6 @@
|
||||
|
||||
TESTNAME = "flyingimage";
|
||||
|
||||
var Image = Java.type("javafx.scene.image.Image");
|
||||
var Color = Java.type("javafx.scene.paint.Color");
|
||||
var Canvas = Java.type("javafx.scene.canvas.Canvas");
|
||||
var BorderPane = Java.type("javafx.scene.layout.BorderPane");
|
||||
var StackPane = Java.type("javafx.scene.layout.StackPane");
|
||||
var Font = Java.type("javafx.scene.text.Font");
|
||||
var FontSmoothingType = Java.type("javafx.scene.text.FontSmoothingType");
|
||||
var Text = Java.type("javafx.scene.text.Text");
|
||||
|
||||
var WIDTH = 800;
|
||||
var HEIGHT = 600;
|
||||
var canvas = new Canvas(WIDTH, HEIGHT);
|
||||
@ -48,10 +39,9 @@ function fileToURL(file) {
|
||||
}
|
||||
var imageUrl = fileToURL(__DIR__ + "flyingimage/flyingimage.png");
|
||||
var img = new Image(imageUrl);
|
||||
var font = new Font("Arial", 16);
|
||||
var t = 0;
|
||||
var isFrameRendered = false;
|
||||
function renderFrame() {
|
||||
var t = frame;
|
||||
var gc = canvas.graphicsContext2D;
|
||||
gc.setFill(Color.web("#cccccc"));
|
||||
gc.fillRect(0, 0, WIDTH, HEIGHT);
|
||||
@ -61,7 +51,7 @@ function renderFrame() {
|
||||
var c = 200;
|
||||
var msc= 0.5 * HEIGHT / img.height;
|
||||
var sp0 = 0.003;
|
||||
for (var h = 0; h < c; h++, t++) {
|
||||
for (var h = 0; h < c; h++) {
|
||||
gc.setTransform(1, 0, 0, 1, 0, 0);
|
||||
var yh = h / (c - 1);
|
||||
gc.translate((0.5 + Math.sin(t * sp0 + h * 0.1) / 3) * WIDTH, 25 + (HEIGHT * 3 / 4 - 40) * (yh * yh));
|
||||
@ -69,15 +59,26 @@ function renderFrame() {
|
||||
gc.rotate(90 * Math.sin(t * sp0 + h * 0.1 + Math.PI));
|
||||
gc.scale(sc, sc);
|
||||
gc.drawImage(img, -img.width / 2, -img.height / 2);
|
||||
}
|
||||
}
|
||||
gc.setTransform(1, 0, 0, 1, 0, 0);
|
||||
isFrameRendered = true;
|
||||
}
|
||||
var stack = new StackPane();
|
||||
var pane = new BorderPane();
|
||||
|
||||
pane.setCenter(canvas);
|
||||
stack.getChildren().add(pane);
|
||||
$STAGE.scene = new Scene(stack);
|
||||
renderFrame();
|
||||
checkImageAndExit();
|
||||
var frame = 0;
|
||||
var timer = new AnimationTimerExtend() {
|
||||
handle: function handle(now) {
|
||||
if (frame < 200) {
|
||||
renderFrame();
|
||||
frame++;
|
||||
} else {
|
||||
checkImageAndExit();
|
||||
timer.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
|
||||
|
Before ![]() (image error) Size: 439 B After ![]() (image error) Size: 1.2 KiB ![]() ![]() |
Before ![]() (image error) Size: 14 KiB After ![]() (image error) Size: 67 KiB ![]() ![]() |
Before ![]() (image error) Size: 12 KiB After ![]() (image error) Size: 67 KiB ![]() ![]() |
Before ![]() (image error) Size: 9.6 KiB After ![]() (image error) Size: 67 KiB ![]() ![]() |
@ -30,13 +30,6 @@
|
||||
*/
|
||||
|
||||
TESTNAME = "kaleidoscope";
|
||||
WAIT = 4000;
|
||||
|
||||
var Paint = Java.type("javafx.scene.paint.Paint");
|
||||
var Canvas = Java.type("javafx.scene.canvas.Canvas");
|
||||
var BorderPane = Java.type("javafx.scene.layout.BorderPane");
|
||||
var StackPane = Java.type("javafx.scene.layout.StackPane");
|
||||
var StrokeLineCap = Java.type("javafx.scene.shape.StrokeLineCap");
|
||||
|
||||
var WIDTH = 800;
|
||||
var HEIGHT = 600;
|
||||
@ -56,26 +49,28 @@ var d=new Array(6);
|
||||
var r,e;
|
||||
var fade;
|
||||
var prv_x,prv_y,prv_x2,prv_y2;
|
||||
var isFrameRendered = false;
|
||||
|
||||
function renderFrame() {
|
||||
a=0.2*angle;
|
||||
b=0.7*angle;
|
||||
r=0;
|
||||
fade=32;
|
||||
for(var i=0;i<6;i++)
|
||||
{
|
||||
c[i]=1.0/(i+1)/2;
|
||||
d[i]=1.0/(i+1)/2;
|
||||
}
|
||||
radius=Math.round((WIDTH+HEIGHT)/8);
|
||||
e=radius*0.2;
|
||||
p_x=Math.round(WIDTH/2);
|
||||
p_y=Math.round(HEIGHT/2);
|
||||
x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);
|
||||
y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);
|
||||
for (i = 0; i < 800; i++) {
|
||||
anim();
|
||||
if (!isFrameRendered) {
|
||||
a=0.2*angle;
|
||||
b=0.7*angle;
|
||||
r=0;
|
||||
fade=32;
|
||||
for(var i=0;i<6;i++)
|
||||
{
|
||||
c[i]=1.0/(i+1)/2;
|
||||
d[i]=1.0/(i+1)/2;
|
||||
}
|
||||
radius=Math.round((WIDTH+HEIGHT)/8);
|
||||
e=radius*0.2;
|
||||
p_x=Math.round(WIDTH/2);
|
||||
p_y=Math.round(HEIGHT/2);
|
||||
x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);
|
||||
y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);
|
||||
isFrameRendered = true;
|
||||
}
|
||||
anim();
|
||||
}
|
||||
|
||||
function anim() {
|
||||
@ -154,9 +149,19 @@ function draw_line(x,y,x1,y1,x2,y2) {
|
||||
|
||||
var stack = new StackPane();
|
||||
var pane = new BorderPane();
|
||||
|
||||
pane.setCenter(canvas);
|
||||
stack.getChildren().add(pane);
|
||||
$STAGE.scene = new Scene(stack);
|
||||
renderFrame();
|
||||
checkImageAndExit();
|
||||
var frame = 0;
|
||||
var timer = new AnimationTimerExtend() {
|
||||
handle: function handle(now) {
|
||||
if (frame < 800) {
|
||||
renderFrame();
|
||||
frame++;
|
||||
} else {
|
||||
checkImageAndExit();
|
||||
timer.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
|
Before ![]() (image error) Size: 181 KiB After ![]() (image error) Size: 188 KiB ![]() ![]() |
Before ![]() (image error) Size: 198 KiB After ![]() (image error) Size: 198 KiB ![]() ![]() |
Before ![]() (image error) Size: 198 KiB After ![]() (image error) Size: 188 KiB ![]() ![]() |
222
nashorn/test/script/jfx/spread.js
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Testing JavaFX canvas run by Nashorn.
|
||||
*
|
||||
* @test/nocompare
|
||||
* @run
|
||||
* @fork
|
||||
*/
|
||||
|
||||
TESTNAME = "spread";
|
||||
|
||||
var WIDTH = 800;
|
||||
var HEIGHT = 600;
|
||||
var canvas = new Canvas(WIDTH, HEIGHT);
|
||||
var context = canvas.graphicsContext2D;
|
||||
|
||||
/* "Spread" tech demo of canvas by Tom Theisen
|
||||
*
|
||||
* This will animate a sequence of branch structures in a canvas element.
|
||||
* Each frame, a new direction is calculated, similar to the last frame.
|
||||
*/
|
||||
|
||||
var start_width = 20; // starting width of each branch
|
||||
var frame_time = 30; // milliseconds per frame
|
||||
var straighten_factor = 0.95; // value from 0 to 1, factor applied to direction_offset every frame
|
||||
var curviness = 0.2; // amount of random direction change each frame
|
||||
|
||||
var color_speed = 0.03; // speed at which colors change when cycling is enabled
|
||||
var branch_shrink = 0.95; // factor by which branches shrink every frame
|
||||
var min_width = 1; // minimum WIDTH for branch, after which they are discontinued
|
||||
var branch_opacity = 0.4; // opacity of lines drawn
|
||||
var branch_count = 3; // branch count per tree
|
||||
var branch_bud_size = 0.5; // ratio of original branch size at which branch will split
|
||||
var branch_bud_angle = 1; // angle offset for split branch;
|
||||
|
||||
var paper; // reference to graphics context
|
||||
var branches = Object(); // linked list of active branches
|
||||
var color_styles = []; // pre-computed list of colors as styles. format: (r,g,b,a)
|
||||
var direction_offset = 0; // current direction offset in radians. this is applied to all branches.
|
||||
var frame = 0; // frame counter
|
||||
var timespent = 0; // total time spent so far, used to calculate average frame render duration
|
||||
var frameratespan; // html span element for updating performance number
|
||||
|
||||
// preferences object, contains an attribute for each user setting
|
||||
var prefs = {
|
||||
wrap: true, // causes branches reaching edge of viewable area to appear on opposite side
|
||||
fade: false, // fade existing graphics on each frame
|
||||
cycle: true, // gradually change colors each frame
|
||||
new_branch_frames: 20 // number of frames elapsed between each auto-generated tree
|
||||
};
|
||||
|
||||
// create tree at the specified position with number of branches
|
||||
function create_tree(branches, start_width, position, branch_count) {
|
||||
var angle_offset = Math.PI * 2 / branch_count;
|
||||
for (var i = 0; i < branch_count; ++i) {
|
||||
branch_add(branches, new Branch(position, angle_offset * i, start_width));
|
||||
}
|
||||
}
|
||||
|
||||
// add branch to collection
|
||||
function branch_add(branches, branch) {
|
||||
branch.next = branches.next;
|
||||
branches.next = branch;
|
||||
}
|
||||
|
||||
// get the coordinates for the position of a new tree
|
||||
// use the center of the canvas
|
||||
function get_new_tree_center(width, height) {
|
||||
return {
|
||||
x: 0.5 * width,
|
||||
y: 0.5 * height
|
||||
};
|
||||
}
|
||||
|
||||
// Branch constructor
|
||||
// position has x and y properties
|
||||
// direction is in radians
|
||||
function Branch(position, direction, width) {
|
||||
this.x = position.x;
|
||||
this.y = position.y;
|
||||
this.width = width;
|
||||
this.original_width = width;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
// update position, direction and width of a particular branch
|
||||
function branch_update(branches, branch, paper) {
|
||||
paper.beginPath();
|
||||
paper.lineWidth = branch.width;
|
||||
paper.moveTo(branch.x, branch.y);
|
||||
|
||||
branch.width *= branch_shrink;
|
||||
branch.direction += direction_offset;
|
||||
branch.x += Math.cos(branch.direction) * branch.width;
|
||||
branch.y += Math.sin(branch.direction) * branch.width;
|
||||
|
||||
paper.lineTo(branch.x, branch.y);
|
||||
paper.stroke();
|
||||
|
||||
if (prefs.wrap) wrap_branch(branch, WIDTH, HEIGHT);
|
||||
|
||||
if (branch.width < branch.original_width * branch_bud_size) {
|
||||
branch.original_width *= branch_bud_size;
|
||||
branch_add(branches, new Branch(branch, branch.direction + 1, branch.original_width));
|
||||
}
|
||||
}
|
||||
|
||||
function draw_frame() {
|
||||
if (prefs.fade) {
|
||||
paper.fillRect(0, 0, WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
if (prefs.cycle) {
|
||||
paper.setStroke(Paint.valueOf(color_styles[frame % color_styles.length]));
|
||||
}
|
||||
|
||||
if (frame++ % prefs.new_branch_frames == 0) {
|
||||
create_tree(branches, start_width, get_new_tree_center(WIDTH, HEIGHT), branch_count);
|
||||
}
|
||||
|
||||
direction_offset += (0.35 + (frame % 200) * 0.0015) * curviness - curviness / 2;
|
||||
direction_offset *= straighten_factor;
|
||||
|
||||
var branch = branches;
|
||||
var prev_branch = branches;
|
||||
while (branch = branch.next) {
|
||||
branch_update(branches, branch, paper);
|
||||
|
||||
if (branch.width < min_width) {
|
||||
// remove branch from list
|
||||
prev_branch.next = branch.next;
|
||||
}
|
||||
|
||||
prev_branch = branch;
|
||||
}
|
||||
}
|
||||
|
||||
// constrain branch position to visible area by "wrapping" from edge to edge
|
||||
function wrap_branch(branch, WIDTH, HEIGHT) {
|
||||
branch.x = positive_mod(branch.x, WIDTH);
|
||||
branch.y = positive_mod(branch.y, HEIGHT);
|
||||
}
|
||||
|
||||
// for a < 0, b > 0, javascript returns a negative number for a % b
|
||||
// this is a variant of the % operator that adds b to the result in this case
|
||||
function positive_mod(a, b) {
|
||||
// ECMA 262 11.5.3: Applying the % Operator
|
||||
// remainder operator does not convert operands to integers,
|
||||
// although negative results are possible
|
||||
|
||||
return ((a % b) + b) % b;
|
||||
}
|
||||
|
||||
// pre-compute color styles that will be used for color cycling
|
||||
function populate_colors(color_speed, color_styles, branch_opacity) {
|
||||
// used in calculation of RGB values
|
||||
var two_thirds_pi = Math.PI * 2 / 3;
|
||||
var four_thirds_pi = Math.PI * 4 / 3;
|
||||
var two_pi = Math.PI * 2;
|
||||
|
||||
// hue does represent hue, but not in the conventional HSL scheme
|
||||
for(var hue = 0; hue < two_pi; hue += color_speed) {
|
||||
var r = Math.floor(Math.sin(hue) * 128 + 128);
|
||||
var g = Math.floor(Math.sin(hue + two_thirds_pi) * 128 + 128);
|
||||
var b = Math.floor(Math.sin(hue + four_thirds_pi) * 128 + 128);
|
||||
color = "rgba(" + [r, g, b, branch_opacity].join() + ")";
|
||||
|
||||
color_styles.push(color);
|
||||
}
|
||||
}
|
||||
|
||||
// apply initial settings to canvas object
|
||||
function setup_canvas() {
|
||||
paper = canvas.graphicsContext2D;
|
||||
paper.setFill(Paint.valueOf('rgb(0, 0, 0)'));
|
||||
paper.fillRect(0, 0, WIDTH, HEIGHT);
|
||||
paper.setFill(Paint.valueOf("rgba(0, 0, 0, 0.005)"));
|
||||
paper.setStroke(Paint.valueOf("rgba(128, 128, 64, " + String(branch_opacity) + ")"));
|
||||
}
|
||||
|
||||
populate_colors(color_speed, color_styles, branch_opacity);
|
||||
setup_canvas();
|
||||
|
||||
var stack = new StackPane();
|
||||
var pane = new BorderPane();
|
||||
pane.setCenter(canvas);
|
||||
stack.getChildren().add(pane);
|
||||
$STAGE.scene = new Scene(stack);
|
||||
var timer = new AnimationTimerExtend() {
|
||||
handle: function handle(now) {
|
||||
if (frame < 200) {
|
||||
draw_frame();
|
||||
} else {
|
||||
checkImageAndExit();
|
||||
timer.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.start();
|
||||
|
BIN
nashorn/test/script/jfx/spread/golden/linux.png
Normal file
After ![]() (image error) Size: 196 KiB |
BIN
nashorn/test/script/jfx/spread/golden/macosx.png
Normal file
After ![]() (image error) Size: 195 KiB |
BIN
nashorn/test/script/jfx/spread/golden/windows.png
Normal file
After ![]() (image error) Size: 196 KiB |