@@ -405,6 +405,10 @@ Math.round = function(x, decimals) {
405405 }
406406} ;
407407
408+ Math . mod = function ( a , b ) {
409+ return ( ( a % b ) + b ) % b ;
410+ } ;
411+
408412Math . sign = function ( x ) {
409413 if ( x < 0 ) return - 1 ;
410414 if ( x > 0 ) return + 1 ;
@@ -860,11 +864,25 @@ var Color = Class.extend({
860864 hsb [ 0 ] += options . hue || 0 ;
861865 hsb [ 1 ] *= options . saturation || 1 ;
862866 hsb [ 2 ] *= options . brightness || 1 ;
863- return new Color ( hsb [ 0 ] % 1 , hsb [ 1 ] , hsb [ 2 ] , this . a , { "colorspace" : HSB } ) ;
867+ return new Color ( Math . mod ( hsb [ 0 ] , 1 ) , hsb [ 1 ] , hsb [ 2 ] , this . a , { "colorspace" : HSB } ) ;
864868 }
865869} ) ;
866870
871+ function rgb ( r , g , b ) {
872+ /* Returns a new Color from R, G, B values (0-255).
873+ */
874+ return new Color ( r , g , b , 1 * 255 , { "base" : 255 , "colorspace" : RGB } ) ;
875+ }
876+
877+ function rgba ( r , g , b , a ) {
878+ /* Returns a new Color from R, G, B values (0-255) and alpha (0.0-1.0).
879+ */
880+ return new Color ( r , g , b , a * 255 , { "base" : 255 , "colorspace" : RGB } ) ;
881+ }
882+
867883function color ( r , g , b , a , options ) {
884+ /* Returns a new Color from R, G, B, A values (0.0-1.0).
885+ */
868886 return new Color ( r , g , b , a , options ) ;
869887}
870888
@@ -1006,7 +1024,7 @@ function _rgb2hsb(r, g, b) {
10061024 else if ( g == v ) { h = 2 + ( b - r ) / d ; }
10071025 else { h = 4 + ( r - g ) / d ; }
10081026 }
1009- h = h / 6.0 % 1 ;
1027+ h = Math . mod ( h / 6.0 , 1 ) ;
10101028 return [ h , s , v ] ;
10111029}
10121030
@@ -1016,7 +1034,7 @@ function _hsb2rgb(h, s, v) {
10161034 if ( s == 0 ) {
10171035 return [ v , v , v ] ;
10181036 }
1019- h = h % 1 * 6.0 ;
1037+ h = Math . mod ( h , 1 ) * 6.0 ;
10201038 var i = Math . floor ( h ) ;
10211039 var f = h - i ;
10221040 var x = v * ( 1 - s ) ;
@@ -1210,7 +1228,7 @@ function _rotateRYB(h, s, b, angle) {
12101228 * but focuses on aesthetically pleasing complementary colors.
12111229 */
12121230 if ( angle === undefined ) angle = 180 ;
1213- h = h * 360 % 360 ;
1231+ h = Math . mod ( h * 360 , 360 ) ;
12141232 // Find the location (angle) of the hue on the RYB color wheel.
12151233 var x0 , y0 , x1 , y1 , a ;
12161234 var wheel = _COLORWHEEL ;
@@ -1223,7 +1241,7 @@ function _rotateRYB(h, s, b, angle) {
12231241 }
12241242 }
12251243 // Rotate the angle and retrieve the hue.
1226- a = ( a + angle ) % 360 ;
1244+ a = Math . mod ( a + angle , 360 ) ;
12271245 for ( var i = 0 ; i < wheel . length - 1 ; i ++ ) {
12281246 x0 = wheel [ i ] [ 0 ] ; x1 = wheel [ i + 1 ] [ 0 ] ;
12291247 y0 = wheel [ i ] [ 1 ] ; y1 = wheel [ i + 1 ] [ 1 ] ;
@@ -1262,7 +1280,7 @@ function analog(clr, angle, d) {
12621280function _colorMixin ( options ) {
12631281 var s = _ctx . state ;
12641282 var o = options ;
1265- if ( options === undefined ) {
1283+ if ( o === undefined ) {
12661284 return [ s . fill , s . stroke , s . strokewidth , s . strokestyle , s . linecap ] ;
12671285 } else {
12681286 return [
@@ -1343,7 +1361,7 @@ var Gradient = Class.extend({
13431361 this . x = o . x || 0 ;
13441362 this . y = o . y || 0 ;
13451363 this . a = 1.0 ; // Shapes will only be drawn if color or gradient has alpha > 1.0.
1346- this . spread = ( o . spread !== undefined ) ? o . spread : 100 ;
1364+ this . spread = Math . max ( ( o . spread !== undefined ) ? o . spread : 100 , 0 ) ;
13471365 this . angle = o . angle || 0 ;
13481366 } ,
13491367
@@ -1480,7 +1498,7 @@ var AffineTransform = Transform = Class.extend({
14801498 } ,
14811499
14821500 rotation : function ( ) {
1483- return ( Math . degrees ( Math . atan2 ( this . matrix [ 1 ] , this . matrix [ 0 ] ) ) + 360 ) % 360 ;
1501+ return Math . mod ( Math . degrees ( Math . atan2 ( this . matrix [ 1 ] , this . matrix [ 0 ] ) ) + 360 , 360 ) ;
14841502 } ,
14851503
14861504
@@ -2364,7 +2382,6 @@ function line(x0, y0, x1, y1, options) {
23642382 /* Draws a straight line from x0, y0 to x1, y1.
23652383 * The current stroke, strokewidth and strokestyle are applied.
23662384 */
2367- // It is faster to do it directly without creating a Path:
23682385 var a = _colorMixin ( options ) ;
23692386 if ( a [ 1 ] && a [ 1 ] . a > 0 ) {
23702387 _ctx . beginPath ( ) ;
@@ -2378,7 +2395,6 @@ function arc(x, y, radius, angle1, angle2, options) {
23782395 /* Draws an arc with the center at x, y, clockwise from angle1 to angle2.
23792396 * The current stroke, strokewidth and strokestyle are applied.
23802397 */
2381- // It is faster to do it directly without creating a Path:
23822398 var a = _colorMixin ( options ) ;
23832399 if ( a [ 0 ] && a [ 0 ] . a > 0 || a [ 1 ] && a [ 1 ] . a > 0 ) {
23842400 var a1 = Math . radians ( angle1 ) ;
@@ -2393,7 +2409,6 @@ function rect(x, y, width, height, options) {
23932409 /* Draws a rectangle with the top left corner at x, y.
23942410 * The current stroke, strokewidth, strokestyle and fill color are applied.
23952411 */
2396- // It is faster to do it directly without creating a Path:
23972412 var a = _colorMixin ( options ) ;
23982413 if ( a [ 0 ] && a [ 0 ] . a > 0 || a [ 1 ] && a [ 1 ] . a > 0 ) {
23992414 if ( ! options || options . roundness === undefined ) {
@@ -2463,15 +2478,39 @@ function star(x, y, points, outer, inner, options) {
24632478 if ( inner === undefined ) inner = 50 ;
24642479 var p = new Path ( ) ;
24652480 p . moveto ( x , y + outer ) ;
2466- for ( var i = 0 ; i < 2 * points + 1 ; i ++ ) {
2467- var r = ( i % 2 == 0 ) ? outer : inner ;
2468- var a = Math . PI * i / points ;
2469- p . lineto ( x + r * Math . sin ( a ) , y + r * Math . cos ( a ) ) ;
2481+ for ( var i = 0 ; i < 2 * points + 1 ; i ++ ) {
2482+ var r = ( i % 2 == 0 ) ? outer : inner ;
2483+ var a = Math . PI * i / points ;
2484+ p . lineto (
2485+ x + r * Math . sin ( a ) ,
2486+ y + r * Math . cos ( a )
2487+ ) ;
24702488 } ;
24712489 p . closepath ( ) ;
24722490 p . draw ( options ) ;
24732491}
24742492
2493+ // To draw crisp lines, you can use translate(0, 0.5) + line0().
2494+ // We call it "0" because floats are rounded to nearest int.
2495+
2496+ function line0 ( x1 , y1 , x2 , y2 , options ) {
2497+ line (
2498+ Math . round ( x1 ) ,
2499+ Math . round ( y1 ) ,
2500+ Math . round ( x2 ) ,
2501+ Math . round ( y2 ) , options
2502+ ) ;
2503+ }
2504+
2505+ function rect0 ( x , y , width , height , options ) {
2506+ rect (
2507+ Math . round ( x ) ,
2508+ Math . round ( y ) ,
2509+ Math . round ( width ) ,
2510+ Math . round ( height ) , options
2511+ ) ;
2512+ }
2513+
24752514/*##################################################################################################*/
24762515
24772516/*--- CACHE ----------------------------------------------------------------------------------------*/
@@ -3585,7 +3624,7 @@ function adjust(img, options) {
35853624 var adjust_hue = function ( pixels , m ) {
35863625 pixels . map ( function ( p ) {
35873626 var hsb = _rgb2hsb ( p [ 0 ] / 255 , p [ 1 ] / 255 , p [ 2 ] / 255 ) ;
3588- var rgb = _hsb2rgb ( Math . clamp ( ( hsb [ 0 ] + m ) % 1 , 0 , 1 ) , hsb [ 1 ] , hsb [ 2 ] ) ;
3627+ var rgb = _hsb2rgb ( Math . clamp ( Math . mod ( hsb [ 0 ] + m , 1 ) , 0 , 1 ) , hsb [ 1 ] , hsb [ 2 ] ) ;
35893628 return [ rgb [ 0 ] * 255 , rgb [ 1 ] * 255 , rgb [ 2 ] * 255 , p [ 3 ] ] ;
35903629 } ) ;
35913630 }
@@ -4058,26 +4097,27 @@ function widget(canvas, variable, type, options) {
40584097/*--- <SCRIPT TYPE="TEXT/CANVAS"> ------------------------------------------------------------------*/
40594098
40604099attachEvent ( window , "load" , function ( ) {
4061- /* Initializes <script type="text/ canvas"> elements during window.onload().
4062- * Optional arguments include: canvas ="id" (<canvas> to use), and loop="false" (single frame ).
4100+ /* Initializes <script class=" canvas"> elements during window.onload().
4101+ * Optional arguments: width, height, target ="id" (<canvas> to use), loop="false" (static ).
40634102 */
40644103 this . e = document . getElementsByTagName ( "script" ) ;
40654104 for ( this . i = 0 ; this . i < this . e . length ; this . i ++ ) {
40664105 var i = this . i ; // e and i may not be set by globals in eval().
40674106 var e = this . e ;
4068- if ( e [ i ] . type == "text/canvas" ) {
4069- var canvas = e [ i ] . getAttribute ( "canvas" ) ;
4107+ if ( e [ i ] . className == "canvas" || e [ i ] . type == "text/canvas" ) {
4108+ var canvas = e [ i ] . getAttribute ( "target" ) ||
4109+ e [ i ] . getAttribute ( "canvas" ) ;
40704110 if ( canvas ) {
4071- // <script type="text/ canvas" canvas ="id">
4111+ // <script type="canvas" target ="id">
40724112 // Render in the <canvas> with the given id.
40734113 canvas = document . getElementById ( canvas ) ;
40744114 } else {
4075- // <script type="text/ canvas">
4115+ // <script class=" canvas">
40764116 // Create a new <canvas class="canvas"> element.
40774117 canvas = document . createElement ( "canvas" ) ;
40784118 canvas . className = "canvas" ;
4079- canvas . width = 500 ;
4080- canvas . height = 500 ;
4119+ canvas . width = parseInt ( e [ i ] . getAttribute ( "width" ) || 500 ) ;
4120+ canvas . height = parseInt ( e [ i ] . getAttribute ( "height" ) || 500 ) ;
40814121 // Add the new <canvas> to the DOM before the <script> element.
40824122 // If the <script> is in the <head>, add it to the end of the document.
40834123 if ( e [ i ] . parentNode == document . getElementsByTagName ( "head" ) [ 0 ] ) {
@@ -4088,16 +4128,16 @@ attachEvent(window, "load", function() {
40884128 }
40894129 // Evaluate the script and bind setup() and draw() to the canvas.
40904130 var setup = function ( ) { } ;
4091- var draw = function ( ) { } ;
4092- var stop = function ( ) { } ;
4131+ var draw = function ( ) { } ;
4132+ var stop = function ( ) { } ;
40934133 eval ( e [ i ] . innerHTML ) ;
40944134 canvas = new Canvas ( canvas ) ;
40954135 canvas . draw = draw ;
40964136 canvas . setup = setup ;
40974137 canvas . stop = function ( ) {
40984138 stop ( this ) ; this . _stop ( ) ;
40994139 }
4100- // <script type="text/ canvas" loop="false"> renders a single frame.
4140+ // <script class=" canvas" loop="false"> renders a single frame.
41014141 if ( e [ i ] . getAttribute ( "loop" ) == "false" ) {
41024142 canvas . step ( ) ;
41034143 } else {
0 commit comments