1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/script/jfx/spread.js Tue Nov 05 13:09:40 2013 +0400 1.3 @@ -0,0 +1,222 @@ 1.4 +/* 1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 +/** 1.28 + * Testing JavaFX canvas run by Nashorn. 1.29 + * 1.30 + * @test/nocompare 1.31 + * @run 1.32 + * @fork 1.33 + */ 1.34 + 1.35 +TESTNAME = "spread"; 1.36 + 1.37 +var WIDTH = 800; 1.38 +var HEIGHT = 600; 1.39 +var canvas = new Canvas(WIDTH, HEIGHT); 1.40 +var context = canvas.graphicsContext2D; 1.41 + 1.42 +/* "Spread" tech demo of canvas by Tom Theisen 1.43 + * 1.44 + * This will animate a sequence of branch structures in a canvas element. 1.45 + * Each frame, a new direction is calculated, similar to the last frame. 1.46 + */ 1.47 + 1.48 +var start_width = 20; // starting width of each branch 1.49 +var frame_time = 30; // milliseconds per frame 1.50 +var straighten_factor = 0.95; // value from 0 to 1, factor applied to direction_offset every frame 1.51 +var curviness = 0.2; // amount of random direction change each frame 1.52 + 1.53 +var color_speed = 0.03; // speed at which colors change when cycling is enabled 1.54 +var branch_shrink = 0.95; // factor by which branches shrink every frame 1.55 +var min_width = 1; // minimum WIDTH for branch, after which they are discontinued 1.56 +var branch_opacity = 0.4; // opacity of lines drawn 1.57 +var branch_count = 3; // branch count per tree 1.58 +var branch_bud_size = 0.5; // ratio of original branch size at which branch will split 1.59 +var branch_bud_angle = 1; // angle offset for split branch; 1.60 + 1.61 +var paper; // reference to graphics context 1.62 +var branches = Object(); // linked list of active branches 1.63 +var color_styles = []; // pre-computed list of colors as styles. format: (r,g,b,a) 1.64 +var direction_offset = 0; // current direction offset in radians. this is applied to all branches. 1.65 +var frame = 0; // frame counter 1.66 +var timespent = 0; // total time spent so far, used to calculate average frame render duration 1.67 +var frameratespan; // html span element for updating performance number 1.68 + 1.69 +// preferences object, contains an attribute for each user setting 1.70 +var prefs = { 1.71 + wrap: true, // causes branches reaching edge of viewable area to appear on opposite side 1.72 + fade: false, // fade existing graphics on each frame 1.73 + cycle: true, // gradually change colors each frame 1.74 + new_branch_frames: 20 // number of frames elapsed between each auto-generated tree 1.75 +}; 1.76 + 1.77 +// create tree at the specified position with number of branches 1.78 +function create_tree(branches, start_width, position, branch_count) { 1.79 + var angle_offset = Math.PI * 2 / branch_count; 1.80 + for (var i = 0; i < branch_count; ++i) { 1.81 + branch_add(branches, new Branch(position, angle_offset * i, start_width)); 1.82 + } 1.83 +} 1.84 + 1.85 +// add branch to collection 1.86 +function branch_add(branches, branch) { 1.87 + branch.next = branches.next; 1.88 + branches.next = branch; 1.89 +} 1.90 + 1.91 +// get the coordinates for the position of a new tree 1.92 +// use the center of the canvas 1.93 +function get_new_tree_center(width, height) { 1.94 + return { 1.95 + x: 0.5 * width, 1.96 + y: 0.5 * height 1.97 + }; 1.98 +} 1.99 + 1.100 +// Branch constructor 1.101 +// position has x and y properties 1.102 +// direction is in radians 1.103 +function Branch(position, direction, width) { 1.104 + this.x = position.x; 1.105 + this.y = position.y; 1.106 + this.width = width; 1.107 + this.original_width = width; 1.108 + this.direction = direction; 1.109 +} 1.110 + 1.111 +// update position, direction and width of a particular branch 1.112 +function branch_update(branches, branch, paper) { 1.113 + paper.beginPath(); 1.114 + paper.lineWidth = branch.width; 1.115 + paper.moveTo(branch.x, branch.y); 1.116 + 1.117 + branch.width *= branch_shrink; 1.118 + branch.direction += direction_offset; 1.119 + branch.x += Math.cos(branch.direction) * branch.width; 1.120 + branch.y += Math.sin(branch.direction) * branch.width; 1.121 + 1.122 + paper.lineTo(branch.x, branch.y); 1.123 + paper.stroke(); 1.124 + 1.125 + if (prefs.wrap) wrap_branch(branch, WIDTH, HEIGHT); 1.126 + 1.127 + if (branch.width < branch.original_width * branch_bud_size) { 1.128 + branch.original_width *= branch_bud_size; 1.129 + branch_add(branches, new Branch(branch, branch.direction + 1, branch.original_width)); 1.130 + } 1.131 +} 1.132 + 1.133 +function draw_frame() { 1.134 + if (prefs.fade) { 1.135 + paper.fillRect(0, 0, WIDTH, HEIGHT); 1.136 + } 1.137 + 1.138 + if (prefs.cycle) { 1.139 + paper.setStroke(Paint.valueOf(color_styles[frame % color_styles.length])); 1.140 + } 1.141 + 1.142 + if (frame++ % prefs.new_branch_frames == 0) { 1.143 + create_tree(branches, start_width, get_new_tree_center(WIDTH, HEIGHT), branch_count); 1.144 + } 1.145 + 1.146 + direction_offset += (0.35 + (frame % 200) * 0.0015) * curviness - curviness / 2; 1.147 + direction_offset *= straighten_factor; 1.148 + 1.149 + var branch = branches; 1.150 + var prev_branch = branches; 1.151 + while (branch = branch.next) { 1.152 + branch_update(branches, branch, paper); 1.153 + 1.154 + if (branch.width < min_width) { 1.155 + // remove branch from list 1.156 + prev_branch.next = branch.next; 1.157 + } 1.158 + 1.159 + prev_branch = branch; 1.160 + } 1.161 +} 1.162 + 1.163 +// constrain branch position to visible area by "wrapping" from edge to edge 1.164 +function wrap_branch(branch, WIDTH, HEIGHT) { 1.165 + branch.x = positive_mod(branch.x, WIDTH); 1.166 + branch.y = positive_mod(branch.y, HEIGHT); 1.167 +} 1.168 + 1.169 +// for a < 0, b > 0, javascript returns a negative number for a % b 1.170 +// this is a variant of the % operator that adds b to the result in this case 1.171 +function positive_mod(a, b) { 1.172 + // ECMA 262 11.5.3: Applying the % Operator 1.173 + // remainder operator does not convert operands to integers, 1.174 + // although negative results are possible 1.175 + 1.176 + return ((a % b) + b) % b; 1.177 +} 1.178 + 1.179 +// pre-compute color styles that will be used for color cycling 1.180 +function populate_colors(color_speed, color_styles, branch_opacity) { 1.181 + // used in calculation of RGB values 1.182 + var two_thirds_pi = Math.PI * 2 / 3; 1.183 + var four_thirds_pi = Math.PI * 4 / 3; 1.184 + var two_pi = Math.PI * 2; 1.185 + 1.186 + // hue does represent hue, but not in the conventional HSL scheme 1.187 + for(var hue = 0; hue < two_pi; hue += color_speed) { 1.188 + var r = Math.floor(Math.sin(hue) * 128 + 128); 1.189 + var g = Math.floor(Math.sin(hue + two_thirds_pi) * 128 + 128); 1.190 + var b = Math.floor(Math.sin(hue + four_thirds_pi) * 128 + 128); 1.191 + color = "rgba(" + [r, g, b, branch_opacity].join() + ")"; 1.192 + 1.193 + color_styles.push(color); 1.194 + } 1.195 +} 1.196 + 1.197 +// apply initial settings to canvas object 1.198 +function setup_canvas() { 1.199 + paper = canvas.graphicsContext2D; 1.200 + paper.setFill(Paint.valueOf('rgb(0, 0, 0)')); 1.201 + paper.fillRect(0, 0, WIDTH, HEIGHT); 1.202 + paper.setFill(Paint.valueOf("rgba(0, 0, 0, 0.005)")); 1.203 + paper.setStroke(Paint.valueOf("rgba(128, 128, 64, " + String(branch_opacity) + ")")); 1.204 +} 1.205 + 1.206 +populate_colors(color_speed, color_styles, branch_opacity); 1.207 +setup_canvas(); 1.208 + 1.209 +var stack = new StackPane(); 1.210 +var pane = new BorderPane(); 1.211 +pane.setCenter(canvas); 1.212 +stack.getChildren().add(pane); 1.213 +$STAGE.scene = new Scene(stack); 1.214 +var timer = new AnimationTimerExtend() { 1.215 + handle: function handle(now) { 1.216 + if (frame < 200) { 1.217 + draw_frame(); 1.218 + } else { 1.219 + checkImageAndExit(); 1.220 + timer.stop(); 1.221 + } 1.222 + } 1.223 +}; 1.224 +timer.start(); 1.225 +