test/script/jfx/spread.js

changeset 667
bda654c6d59c
parent 0
b1a7da25b547
child 962
ac62e33a99b0
     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 +

mercurial