test/script/jfx/spread.js

Wed, 20 Aug 2014 10:25:28 +0200

author
attila
date
Wed, 20 Aug 2014 10:25:28 +0200
changeset 962
ac62e33a99b0
parent 0
b1a7da25b547
permissions
-rw-r--r--

8044638: Tidy up Nashorn codebase for code standards
8055199: Tidy up Nashorn codebase for code standards (August 2014)
Reviewed-by: lagergren, sundar

     1 /*
     2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  * 
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  * 
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  * 
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  * 
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /**
    25  * Testing JavaFX canvas run by Nashorn.
    26  *
    27  * @test/nocompare
    28  * @run
    29  * @fork
    30  */
    32 TESTNAME = "spread";
    34 var WIDTH = 800;
    35 var HEIGHT = 600;
    36 var canvas = new Canvas(WIDTH, HEIGHT);
    37 var context = canvas.graphicsContext2D;
    39 /* "Spread" tech demo of canvas by Tom Theisen
    40  *
    41  * This will animate a sequence of branch structures in a canvas element.
    42  * Each frame, a new direction is calculated, similar to the last frame.
    43  */
    45 var start_width = 20;           // starting width of each branch
    46 var frame_time = 30;            // milliseconds per frame
    47 var straighten_factor = 0.95;   // value from 0 to 1, factor applied to direction_offset every frame
    48 var curviness = 0.2;            // amount of random direction change each frame
    50 var color_speed = 0.03;     // speed at which colors change when cycling is enabled
    51 var branch_shrink = 0.95;   // factor by which branches shrink every frame
    52 var min_width = 1;          // minimum WIDTH for branch, after which they are discontinued
    53 var branch_opacity = 0.4;   // opacity of lines drawn
    54 var branch_count = 3;       // branch count per tree
    55 var branch_bud_size = 0.5;  // ratio of original branch size at which branch will split
    56 var branch_bud_angle = 1;   // angle offset for split branch;
    58 var paper;                  // reference to graphics context
    59 var branches = Object();    // linked list of active branches
    60 var color_styles = [];      // pre-computed list of colors as styles. format: (r,g,b,a)    
    61 var direction_offset = 0;   // current direction offset in radians.  this is applied to all branches.
    62 var frame = 0;              // frame counter
    63 var timespent = 0;          // total time spent so far, used to calculate average frame render duration
    64 var frameratespan;          // html span element for updating performance number
    66 // preferences object, contains an attribute for each user setting
    67 var prefs = {
    68     wrap: true,             // causes branches reaching edge of viewable area to appear on opposite side
    69     fade: false,             // fade existing graphics on each frame
    70     cycle: true,            // gradually change colors each frame
    71     new_branch_frames: 20    // number of frames elapsed between each auto-generated tree
    72 };
    74 // create tree at the specified position with number of branches
    75 function create_tree(branches, start_width, position, branch_count) {
    76     var angle_offset = Math.PI * 2 / branch_count;
    77     for (var i = 0; i < branch_count; ++i) {
    78         branch_add(branches, new Branch(position, angle_offset * i, start_width));
    79     }
    80 }
    82 // add branch to collection
    83 function branch_add(branches, branch) {
    84     branch.next = branches.next;
    85     branches.next = branch;
    86 }
    88 // get the coordinates for the position of a new tree
    89 // use the center of the canvas
    90 function get_new_tree_center(width, height) {
    91     return {
    92         x: 0.5 * width, 
    93         y: 0.5 * height 
    94     };
    95 }
    97 // Branch constructor
    98 // position has x and y properties
    99 // direction is in radians
   100 function Branch(position, direction, width) {
   101     this.x = position.x;
   102     this.y = position.y;
   103     this.width = width;
   104     this.original_width = width;
   105     this.direction = direction;
   106 }
   108 // update position, direction and width of a particular branch
   109 function branch_update(branches, branch, paper) {
   110     paper.beginPath();
   111     paper.lineWidth = branch.width;
   112     paper.moveTo(branch.x, branch.y);
   114     branch.width *= branch_shrink;
   115     branch.direction += direction_offset;
   116     branch.x += Math.cos(branch.direction) * branch.width;
   117     branch.y += Math.sin(branch.direction) * branch.width;
   119     paper.lineTo(branch.x, branch.y);
   120     paper.stroke();
   122     if (prefs.wrap) wrap_branch(branch, WIDTH, HEIGHT);
   124     if (branch.width < branch.original_width * branch_bud_size) {
   125         branch.original_width *= branch_bud_size;
   126         branch_add(branches, new Branch(branch, branch.direction + 1, branch.original_width));
   127     }
   128 }
   130 function draw_frame() {
   131     if (prefs.fade) {
   132         paper.fillRect(0, 0, WIDTH, HEIGHT);
   133     }
   135     if (prefs.cycle) {
   136         paper.setStroke(Paint.valueOf(color_styles[frame % color_styles.length]));
   137     }
   139     if (frame++ % prefs.new_branch_frames == 0) {
   140         create_tree(branches, start_width, get_new_tree_center(WIDTH, HEIGHT), branch_count);
   141     }
   143     direction_offset += (0.35 + (frame % 200) * 0.0015) * curviness - curviness / 2;
   144     direction_offset *= straighten_factor;
   146     var branch = branches;
   147     var prev_branch = branches;
   148     while (branch = branch.next) {
   149         branch_update(branches, branch, paper);
   151         if (branch.width < min_width) {
   152             // remove branch from list
   153             prev_branch.next = branch.next;
   154         }
   156         prev_branch = branch;
   157     }
   158 }
   160 // constrain branch position to visible area by "wrapping" from edge to edge
   161 function wrap_branch(branch, WIDTH, HEIGHT) {
   162     branch.x = positive_mod(branch.x, WIDTH);
   163     branch.y = positive_mod(branch.y, HEIGHT);
   164 }
   166 // for a < 0, b > 0, javascript returns a negative number for a % b
   167 // this is a variant of the % operator that adds b to the result in this case
   168 function positive_mod(a, b) {
   169     // ECMA 262 11.5.3: Applying the % Operator 
   170     // remainder operator does not convert operands to integers,
   171     // although negative results are possible
   173     return ((a % b) + b) % b;
   174 }
   176 // pre-compute color styles that will be used for color cycling
   177 function populate_colors(color_speed, color_styles, branch_opacity) {
   178     // used in calculation of RGB values
   179     var two_thirds_pi = Math.PI * 2 / 3;
   180     var four_thirds_pi = Math.PI * 4 / 3;
   181     var two_pi = Math.PI * 2;
   183     // hue does represent hue, but not in the conventional HSL scheme
   184     for(var hue = 0; hue < two_pi; hue += color_speed) {
   185         var r = Math.floor(Math.sin(hue) * 128 + 128);
   186         var g = Math.floor(Math.sin(hue + two_thirds_pi) * 128 + 128);
   187         var b = Math.floor(Math.sin(hue + four_thirds_pi) * 128 + 128);
   188         color = "rgba(" + [r, g, b, branch_opacity].join() + ")";
   190         color_styles.push(color);
   191     }
   192 }
   194 // apply initial settings to canvas object
   195 function setup_canvas() {
   196     paper = canvas.graphicsContext2D;
   197     paper.setFill(Paint.valueOf('rgb(0, 0, 0)'));
   198     paper.fillRect(0, 0, WIDTH, HEIGHT);
   199     paper.setFill(Paint.valueOf("rgba(0, 0, 0, 0.005)"));
   200     paper.setStroke(Paint.valueOf("rgba(128, 128, 64, " + String(branch_opacity) + ")"));
   201 }
   203 populate_colors(color_speed, color_styles, branch_opacity);
   204 setup_canvas();
   206 var stack = new StackPane();
   207 var pane = new BorderPane();
   208 pane.setCenter(canvas);
   209 stack.getChildren().add(pane);
   210 $STAGE.scene = new Scene(stack);
   211 var timer = new AnimationTimerExtend() {
   212     handle: function handle(now) {
   213         if (frame < 200) {
   214             draw_frame();
   215         } else {
   216             checkImageAndExit();
   217             timer.stop();
   218         }
   219     }
   220 };
   221 timer.start();

mercurial