22* Gradient
33* class to create linear/radial/elliptical/conic gradients as bitmaps even without canvas
44*
5- * @version 1.1.1
5+ * @version 1.2.0
66* https://github.com/foo123/Gradient
77*
88**/
99! function ( root , name , factory ) {
1010"use strict" ;
1111if ( ( 'object' === typeof module ) && module . exports ) /* CommonJS */
12- ( module . $deps = module . $deps || { } ) && ( module . exports = module . $deps [ name ] = factory . call ( root ) ) ;
12+ module . exports = factory . call ( root ) ;
1313else if ( ( 'function' === typeof define ) && define . amd && ( 'function' === typeof require ) && ( 'function' === typeof require . specified ) && require . specified ( name ) /*&& !require.defined(name)*/ ) /* AMD */
14- define ( name , [ 'module' ] , function ( module ) { factory . moduleUri = module . uri ; return factory . call ( root ) ; } ) ;
14+ define ( name , [ 'module' ] , function ( module ) { return factory . call ( root ) ; } ) ;
1515else if ( ! ( name in root ) ) /* Browser/WebWorker/.. */
1616 ( root [ name ] = factory . call ( root ) || 1 ) && ( 'function' === typeof ( define ) ) && define . amd && define ( function ( ) { return root [ name ] ; } ) ;
1717} ( /* current root */ 'undefined' !== typeof self ? self : this ,
@@ -23,6 +23,7 @@ var HAS = Object.prototype.hasOwnProperty,
2323 stdMath = Math , PI = stdMath . PI , TWO_PI = 2 * PI , HALF_PI = PI / 2 , EPS = 1e-6 ,
2424 ImArray = 'undefined' !== typeof Uint8ClampedArray ? Uint8ClampedArray : ( 'undefined' !== typeof Uint8Array ? Uint8Array : Array ) ;
2525
26+ // Gradient Pattern
2627function Gradient ( grad_color_at )
2728{
2829 if (
@@ -71,23 +72,25 @@ function Gradient(grad_color_at)
7172 self . addColorStop = function ( offset , color ) {
7273 _stops = null ;
7374 stops [ String ( offset ) ] = [ + offset , parseColor ( color ) || [ 0 , 0 , 0 , 0 ] ] ;
74- }
75+ } ;
7576 self . getColorAt = function ( x , y ) {
7677 var p = imatrix . transform ( x , y ) ;
7778 return grad_color_at ( p . x , p . y , colorStops ( ) , new ImArray ( 4 ) , 0 ) ;
7879 } ;
79- self . getBitmap = function ( w , h ) {
80- var color_stops = colorStops ( ) , i , x , y , p , size = ( w * h ) << 2 , bmp = new ImArray ( size ) ;
80+ self . getBitmap = function ( width , height ) {
81+ width = stdMath . round ( width ) ;
82+ height = stdMath . round ( height ) ;
83+ var color_stops = colorStops ( ) , i , x , y , p , size = ( width * height ) << 2 , bmp = new ImArray ( size ) ;
8184 for ( x = 0 , y = 0 , i = 0 ; i < size ; i += 4 , ++ x )
8285 {
83- if ( x >= w ) { x = 0 ; ++ y ; }
86+ if ( x >= width ) { x = 0 ; ++ y ; }
8487 p = imatrix . transform ( x , y ) ;
8588 grad_color_at ( p . x , p . y , color_stops , bmp , i ) ;
8689 }
8790 return bmp ;
8891 } ;
8992}
90- Gradient . VERSION = "1.1.1 " ;
93+ Gradient . VERSION = "1.2.0 " ;
9194Gradient . prototype = {
9295 constructor : Gradient ,
9396 transform : null ,
@@ -241,6 +244,138 @@ Gradient.createEllipticGradient = function(cx, cy, rx, ry, angle) {
241244 } ) ;
242245} ;
243246
247+ // Image Pattern
248+ function Pattern ( pat_color_at )
249+ {
250+ if (
251+ ! ( this instanceof Pattern ) ||
252+ ( 'function' !== typeof pat_color_at ) ||
253+ ( 4 > pat_color_at . length )
254+ )
255+ {
256+ throw new Error ( 'Pattern: invalid pattern' ) ;
257+ }
258+
259+ var self = this , imatrix = new Matrix ( ) ;
260+
261+ self . transform = {
262+ reset : function ( ) {
263+ imatrix = new Matrix ( ) ;
264+ } ,
265+ scale : function ( sx , sy , ox , oy ) {
266+ imatrix = imatrix . mul ( Matrix . scale ( 1 / sx , 1 / sy , ox , oy ) ) ;
267+ } ,
268+ rotate : function ( theta , ox , oy ) {
269+ imatrix = imatrix . mul ( Matrix . rotate ( - theta , ox , oy ) ) ;
270+ } ,
271+ translate : function ( tx , ty ) {
272+ imatrix = imatrix . mul ( Matrix . translate ( - tx , - ty ) ) ;
273+ } ,
274+ skewX : function ( s ) {
275+ imatrix = imatrix . mul ( Matrix . skewX ( s ) . inv ( ) ) ;
276+ } ,
277+ skewX : function ( s ) {
278+ imatrix = imatrix . mul ( Matrix . skewY ( s ) . inv ( ) ) ;
279+ }
280+ } ;
281+ self . getColorAt = function ( x , y ) {
282+ var p = imatrix . transform ( x , y ) ;
283+ return pat_color_at ( p . x , p . y , new ImArray ( 4 ) , 0 ) ;
284+ } ;
285+ self . getBitmap = function ( width , height ) {
286+ width = stdMath . round ( width ) ;
287+ height = stdMath . round ( height ) ;
288+ var i , x , y , p , size = ( width * height ) << 2 , bmp = new ImArray ( size ) ;
289+ for ( x = 0 , y = 0 , i = 0 ; i < size ; i += 4 , ++ x )
290+ {
291+ if ( x >= width ) { x = 0 ; ++ y ; }
292+ p = imatrix . transform ( x , y ) ;
293+ pat_color_at ( p . x , p . y , bmp , i ) ;
294+ }
295+ return bmp ;
296+ } ;
297+ }
298+ Pattern . prototype = {
299+ constructor : Pattern ,
300+ transform : null ,
301+ getColorAt : null ,
302+ getBitmap : null
303+ } ;
304+ Pattern . createPattern = function ( imageData , repetition ) {
305+ if ( imageData && imageData . data && imageData . width && imageData . height && ( imageData . data . length === 4 * imageData . width * imageData . height ) )
306+ {
307+ var width = imageData . width , height = imageData . height ;
308+ switch ( repetition )
309+ {
310+ case 'no-repeat' :
311+ return new Pattern ( function ( x , y , pixel , i ) {
312+ x = stdMath . round ( x ) ;
313+ y = stdMath . round ( y ) ;
314+ if ( 0 <= x && x < width && 0 <= y && y < height )
315+ {
316+ var j = ( x + y * width ) << 2 ;
317+ pixel [ i + 0 ] = imageData . data [ j + 0 ] ;
318+ pixel [ i + 1 ] = imageData . data [ j + 1 ] ;
319+ pixel [ i + 2 ] = imageData . data [ j + 2 ] ;
320+ pixel [ i + 3 ] = imageData . data [ j + 3 ] ;
321+ }
322+ } ) ;
323+ case 'repeat-x' :
324+ return new Pattern ( function ( x , y , pixel , i ) {
325+ x = stdMath . round ( x ) ;
326+ y = stdMath . round ( y ) ;
327+ if ( 0 <= y && y < height )
328+ {
329+ x = x % width ;
330+ if ( 0 > x ) x += width ;
331+ var j = ( x + y * width ) << 2 ;
332+ pixel [ i + 0 ] = imageData . data [ j + 0 ] ;
333+ pixel [ i + 1 ] = imageData . data [ j + 1 ] ;
334+ pixel [ i + 2 ] = imageData . data [ j + 2 ] ;
335+ pixel [ i + 3 ] = imageData . data [ j + 3 ] ;
336+ }
337+ } ) ;
338+ case 'repeat-y' :
339+ return new Pattern ( function ( x , y , pixel , i ) {
340+ x = stdMath . round ( x ) ;
341+ y = stdMath . round ( y ) ;
342+ if ( 0 <= x && x < width )
343+ {
344+ y = y % height ;
345+ if ( 0 > y ) y += height ;
346+ var j = ( x + y * width ) << 2 ;
347+ pixel [ i + 0 ] = imageData . data [ j + 0 ] ;
348+ pixel [ i + 1 ] = imageData . data [ j + 1 ] ;
349+ pixel [ i + 2 ] = imageData . data [ j + 2 ] ;
350+ pixel [ i + 3 ] = imageData . data [ j + 3 ] ;
351+ }
352+ } ) ;
353+ case 'repeat' :
354+ default :
355+ return new Pattern ( function ( x , y , pixel , i ) {
356+ x = stdMath . round ( x ) ;
357+ y = stdMath . round ( y ) ;
358+ x = x % width ;
359+ if ( 0 > x ) x += width ;
360+ y = y % height ;
361+ if ( 0 > y ) y += height ;
362+ var j = ( x + y * width ) << 2 ;
363+ pixel [ i + 0 ] = imageData . data [ j + 0 ] ;
364+ pixel [ i + 1 ] = imageData . data [ j + 1 ] ;
365+ pixel [ i + 2 ] = imageData . data [ j + 2 ] ;
366+ pixel [ i + 3 ] = imageData . data [ j + 3 ] ;
367+ } ) ;
368+ }
369+ }
370+ else
371+ {
372+ throw new Error ( 'Pattern: invalid image data' ) ;
373+ }
374+ } ;
375+ Gradient . Pattern = Pattern ;
376+ Gradient . createPattern = Pattern . createPattern ;
377+
378+ // Homogeneous Transformation Matrix
244379function Matrix ( m00 , m01 , m02 , m10 , m11 , m12 )
245380{
246381 var self = this ;
@@ -376,6 +511,7 @@ function binary_search(x, a, n)
376511 }
377512 return l ;
378513}
514+ // color utilities
379515function interpolatePixel ( pixel , index , rgba0 , rgba1 , t )
380516{
381517 pixel [ index + 0 ] = clamp ( stdMath . round ( rgba0 [ 0 ] + t * ( rgba1 [ 0 ] - rgba0 [ 0 ] ) ) , 0 , 255 ) ;
0 commit comments