Skip to content

Commit fd9a291

Browse files
committed
canvaslite
1 parent 333136b commit fd9a291

File tree

1 file changed

+116
-82
lines changed

1 file changed

+116
-82
lines changed

examples/CanvasLite.js

Lines changed: 116 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
* CanvasLite
33
* an html canvas implementation in pure JavaScript
44
*
5-
* @version 0.9.92 (2023-07-30 21:49:27)
5+
* @version 0.9.92 (2023-07-31 22:54:20)
66
* https://github.com/foo123/CanvasLite
77
*
88
**//**
99
* CanvasLite
1010
* an html canvas implementation in pure JavaScript
1111
*
12-
* @version 0.9.92 (2023-07-30 21:49:27)
12+
* @version 0.9.92 (2023-07-31 22:54:20)
1313
* https://github.com/foo123/CanvasLite
1414
*
1515
**/
@@ -3268,7 +3268,7 @@ function NOOP() {}
32683268
* Gradient
32693269
* class to create linear/radial/elliptical/conic gradients as bitmaps even without canvas
32703270
*
3271-
* @version 1.2.2
3271+
* @version 1.2.3
32723272
* https://github.com/foo123/Gradient
32733273
*
32743274
**/
@@ -3309,12 +3309,13 @@ function Gradient(grad_color_at)
33093309
});
33103310
self.addColorStop = function(offset, color) {
33113311
_stops = null;
3312-
stops[String(offset)] = [+offset, parseColor(color) || [0,0,0,0]];
3312+
stops[String(offset)] = [+offset, parseColor(color) || BLANK];
33133313
};
33143314
self.getColorAt = function(x, y) {
33153315
var im = transform.imatrix(true),
3316-
p = im ? im.transform(x, y) : null;
3317-
return p ? grad_color_at(p.x, p.y, colorStops(), new ImArray(4), 0) : new ImArray(4);
3316+
p = im ? im.transform(x, y) : null,
3317+
rgba = new ImArray(4);
3318+
return p ? grad_color_at(p[0], p[1], colorStops(), rgba, 0) : rgba;
33183319
};
33193320
self.getBitmap = function(width, height) {
33203321
width = stdMath.round(width);
@@ -3331,13 +3332,13 @@ function Gradient(grad_color_at)
33313332
{
33323333
if (x >= width) {x=0; ++y;}
33333334
p = imatrix.transform(x, y);
3334-
grad_color_at(p.x, p.y, color_stops, bmp, i);
3335+
grad_color_at(p[0], p[1], color_stops, bmp, i);
33353336
}
33363337
}
33373338
return bmp;
33383339
};
33393340
}
3340-
Gradient.VERSION = "1.2.2";
3341+
Gradient.VERSION = "1.2.3";
33413342
Gradient[PROTO] = {
33423343
constructor: Gradient,
33433344
transform: null,
@@ -3448,7 +3449,7 @@ Gradient.createConicGradient = function(angle, cx, cy) {
34483449
cy = cy || 0;
34493450
return new Gradient(function(x, y, stops, pixel, i) {
34503451
var t, stop1, stop2, sl = stops.length;
3451-
t = stdMath.atan2(y - cy, x - cx) + HALF_PI - angle;
3452+
t = stdMath.atan2(y - cy, x - cx) /*+ HALF_PI*/ - angle;
34523453
if (0 > t) t += TWO_PI;
34533454
if (t > TWO_PI) t -= TWO_PI;
34543455
t = clamp(t/TWO_PI, 0, 1);
@@ -3486,8 +3487,13 @@ function Pattern(pat_color_at)
34863487
configurable: false
34873488
});
34883489
self.getColorAt = function(x, y) {
3489-
var p = transform.imatrix(true).transform(x, y);
3490-
return pat_color_at(p.x, p.y, new ImArray(4), 0);
3490+
var im = transform.imatrix(true), p, rgba = new ImArray(4);
3491+
if (im)
3492+
{
3493+
p = im.transform(x, y);
3494+
pat_color_at(p[0], p[1], rgba, 0);
3495+
}
3496+
return rgba;
34913497
};
34923498
self.getBitmap = function(width, height) {
34933499
width = stdMath.round(width);
@@ -3496,11 +3502,14 @@ function Pattern(pat_color_at)
34963502
i, x, y, p,
34973503
size = (width*height) << 2,
34983504
bmp = new ImArray(size);
3499-
for (x=0,y=0,i=0; i<size; i+=4,++x)
3505+
if (imatrix)
35003506
{
3501-
if (x >= width) {x=0; ++y;}
3502-
p = imatrix.transform(x, y);
3503-
pat_color_at(p.x, p.y, bmp, i);
3507+
for (x=0,y=0,i=0; i<size; i+=4,++x)
3508+
{
3509+
if (x >= width) {x=0; ++y;}
3510+
p = imatrix.transform(x, y);
3511+
pat_color_at(p[0], p[1], bmp, i);
3512+
}
35043513
}
35053514
return bmp;
35063515
};
@@ -3530,6 +3539,7 @@ Pattern.createPattern = function(imageData, repetition) {
35303539
pixel[i + 2] = imageData.data[j + 2];
35313540
pixel[i + 3] = imageData.data[j + 3];
35323541
}
3542+
return pixel;
35333543
});
35343544
case 'repeat-x':
35353545
return new Pattern(function(x, y, pixel, i) {
@@ -3545,6 +3555,7 @@ Pattern.createPattern = function(imageData, repetition) {
35453555
pixel[i + 2] = imageData.data[j + 2];
35463556
pixel[i + 3] = imageData.data[j + 3];
35473557
}
3558+
return pixel;
35483559
});
35493560
case 'repeat-y':
35503561
return new Pattern(function(x, y, pixel, i) {
@@ -3560,6 +3571,7 @@ Pattern.createPattern = function(imageData, repetition) {
35603571
pixel[i + 2] = imageData.data[j + 2];
35613572
pixel[i + 3] = imageData.data[j + 3];
35623573
}
3574+
return pixel;
35633575
});
35643576
case 'repeat':
35653577
default:
@@ -3575,6 +3587,7 @@ Pattern.createPattern = function(imageData, repetition) {
35753587
pixel[i + 1] = imageData.data[j + 1];
35763588
pixel[i + 2] = imageData.data[j + 2];
35773589
pixel[i + 3] = imageData.data[j + 3];
3590+
return pixel;
35783591
});
35793592
}
35803593
}
@@ -3633,34 +3646,36 @@ function Transform()
36333646
return self;
36343647
};
36353648
self.scale = function(sx, sy, ox, oy) {
3636-
matrix = Matrix2D.scale(sx, sy, ox, oy).mul(matrix);
3637-
imatrix = imatrix.mul(Matrix2D.scale(1/sx, 1/sy, ox, oy));
3649+
matrix = matrix.mul(Matrix2D.scale(sx, sy, ox, oy));
3650+
imatrix = Matrix2D.scale(1/sx, 1/sy, ox, oy).mul(imatrix);
36383651
return self;
36393652
};
36403653
self.rotate = function(theta, ox, oy) {
3641-
matrix = Matrix2D.rotate(theta, ox, oy).mul(matrix);
3642-
imatrix = imatrix.mul(Matrix2D.rotate(-theta, ox, oy));
3654+
matrix = matrix.mul(Matrix2D.rotate(theta, ox, oy));
3655+
imatrix = Matrix2D.rotate(-theta, ox, oy).mul(imatrix);
36433656
return self;
36443657
};
36453658
self.translate = function(tx, ty) {
3646-
matrix = Matrix2D.translate(tx, ty).mul(matrix);
3647-
imatrix = imatrix.mul(Matrix2D.translate(-tx, -ty));
3659+
matrix = matrix.mul(Matrix2D.translate(tx, ty));
3660+
imatrix = Matrix2D.translate(-tx, -ty).mul(imatrix);
36483661
return self;
36493662
};
36503663
self.skewX = function(s) {
3651-
matrix = Matrix2D.skewX(s).mul(matrix);
3652-
imatrix = imatrix.mul(Matrix2D.skewX(s).inv());
3664+
var m = Matrix2D.skewX(s);
3665+
matrix = matrix.mul(m);
3666+
imatrix = m.inv().mul(imatrix);
36533667
return self;
36543668
};
36553669
self.skewY = function(s) {
3656-
matrix = Matrix2D.skewY(s).mul(matrix);
3657-
imatrix = imatrix.mul(Matrix2D.skewY(s).inv());
3670+
var m = Matrix2D.skewY(s);
3671+
matrix = matrix.mul(m);
3672+
imatrix = m.inv().mul(imatrix);
36583673
return self;
36593674
};
36603675
self.transform = function(a, b, c, d, e, f) {
36613676
var m = new Matrix2D(a, c, e, b, d, f);
3662-
matrix = m.mul(matrix);
3663-
imatrix = imatrix.mul(m.inv());
3677+
matrix = matrix.mul(m);
3678+
imatrix = m.inv().mul(imatrix);
36643679
return self;
36653680
};
36663681

@@ -3694,7 +3709,7 @@ function quadratic_roots(a, b, c)
36943709
{
36953710
if (is_strictly_equal(a, 0)) return linear_roots(b, c);
36963711
var D = b*b - 4*a*c, DS = 0;
3697-
if (is_almost_equal(D, 0)) return [-b/(2*a)];
3712+
if (is_almost_equal(D, 0, 1e-6)) return [-b/(2*a)];
36983713
if (0 > D) return false;
36993714
DS = stdMath.sqrt(D);
37003715
return [(-b-DS)/(2*a), (-b+DS)/(2*a)];
@@ -6395,25 +6410,73 @@ async function imagepng(type, img, width, height, metaData)
63956410
return '';
63966411
}
63976412

6413+
function detect_image_type(buffer)
6414+
{
6415+
// https://en.wikipedia.org/wiki/List_of_file_signatures
6416+
var data = new Uint8Array(buffer[buffer.subarray ? 'subarray' : 'slice'](0, 8)),
6417+
byteAt = function(offset) {return offset < data.length ? data[offset] : 0;};
6418+
if (0x89 === byteAt(0)
6419+
&& 0x50 === byteAt(1)
6420+
&& 0x4e === byteAt(2)
6421+
&& 0x47 === byteAt(3)
6422+
&& 0x0d === byteAt(4)
6423+
&& 0x0a === byteAt(5)
6424+
&& 0x1a === byteAt(6)
6425+
&& 0x0a === byteAt(7)
6426+
) return 'PNG';
6427+
else if (0x47 === byteAt(0)
6428+
&& 0x49 === byteAt(1)
6429+
&& 0x46 === byteAt(2)
6430+
&& 0x38 === byteAt(3)
6431+
&& (0x37 === byteAt(4) || 0x39 === byteAt(4))
6432+
&& 0x61 === byteAt(5)
6433+
) return 'GIF';
6434+
else if (0xff === byteAt(0)
6435+
&& 0xd8 === byteAt(1)
6436+
/*&& 0xff === byteAt(2)
6437+
&& 0xdb === byteAt(3)*/
6438+
) return 'JPG';
6439+
return 'NOT_SUPPORTED';
6440+
}
6441+
function base64_decode(b64str)
6442+
{
6443+
if ('undefined' !== typeof Buffer)
6444+
{
6445+
return Buffer.from(b64str, 'base64');
6446+
}
6447+
else if ('function' === typeof atob)
6448+
{
6449+
var binaryString = atob(b64str),
6450+
i, n = binaryString.length,
6451+
bytes = new Uint8Array(n);
6452+
for (i=0; i<n; ++i) bytes[i] = binaryString.charCodeAt(i);
6453+
return bytes.buffer;
6454+
}
6455+
}
6456+
63986457
function Image()
63996458
{
6400-
var self = this, src = '', width = 0, height = 0, imageData = null, load;
6459+
var self = this, src = '', width = 0, height = 0, imageData = null, error, load;
64016460

6461+
error = function(e) {
6462+
if (!e instanceof Error) e = new Error(String(e));
6463+
if (self.onerror) self.onerror(e);
6464+
else throw e;
6465+
};
64026466
load = function load(buffer) {
6467+
if (!buffer) return;
64036468
var imgReader = Image.Reader[Image.detectImageType(buffer)];
6404-
if (!imgReader) err('Image file type is not supported!');
6469+
if (!imgReader) return error('Image file type is not supported!');
64056470
imgReader(buffer)
64066471
.then(function(imgData) {
64076472
imageData = imgData;
64086473
width = imgData.width;
64096474
height = imgData.height;
64106475
if (self.onload) self.onload();
64116476
})
6412-
.catch(function(error) {
6413-
if (self.onerror) self.onerror(error);
6414-
else throw error;
6415-
});
6477+
.catch(error);
64166478
};
6479+
64176480
def(self, 'width', {
64186481
get: function() {
64196482
return width;
@@ -6450,41 +6513,38 @@ function Image()
64506513
if ((('undefined' !== typeof ArrayBuffer) && (file instanceof ArrayBuffer))
64516514
|| (('undefined' !== typeof Buffer) && (file instanceof Buffer)))
64526515
{
6516+
// buffer passed
64536517
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
64546518
// https://nodejs.org/api/buffer.html#class-buffer
64556519
load(src = file);
64566520
}
64576521
else if ((('undefined' !== typeof Blob) && (file instanceof Blob))
64586522
|| (('undefined' !== typeof Buffer) && (Buffer.Blob) && (file instanceof Buffer.Blob)))
64596523
{
6524+
// blob passed
64606525
// https://developer.mozilla.org/en-US/docs/Web/API/Blob
64616526
// https://nodejs.org/api/buffer.html#class-blob
6462-
(src = file).arrayBuffer()
6463-
.then(function(buffer) {
6464-
load(buffer);
6465-
})
6466-
.catch(function(error) {
6467-
if (self.onerror) self.onerror(error);
6468-
else throw error;
6469-
})
6527+
(src = file).arrayBuffer().then(load).catch(error);
64706528
}
6471-
else if (isNode && (('string' === typeof file) || (file instanceof String)))
6529+
else if (('string' === typeof file) || (file instanceof String))
64726530
{
6473-
require('fs').readFile(src = file, function(error, buffer) {
6474-
if (error)
6475-
{
6476-
if (self.onerror) self.onerror(error);
6477-
else throw error;
6478-
}
6479-
else
6480-
{
6481-
load(buffer);
6482-
}
6483-
});
6531+
if (/^data:image\/[a-z]+;base64,/.test(file))
6532+
{
6533+
// base64 encoded image
6534+
load(base64_decode((src = file).slice(file.indexOf(';base64,')+8)));
6535+
}
6536+
else if (isNode)
6537+
{
6538+
// file path of image
6539+
require('fs').readFile(src = file, function(err, buffer) {
6540+
if (err) error(err);
6541+
else load(buffer);
6542+
});
6543+
}
64846544
}
64856545
/*else
64866546
{
6487-
err('Unsupported src property');
6547+
error('Unsupported src property');
64886548
}*/
64896549
}
64906550
});
@@ -6509,33 +6569,7 @@ Image.Reader = {
65096569
'JPG': read_jpg,
65106570
'PNG': read_png
65116571
};
6512-
Image.detectImageType = function(buffer) {
6513-
// https://en.wikipedia.org/wiki/List_of_file_signatures
6514-
var data = new Uint8Array(buffer[buffer.subarray ? 'subarray' : 'slice'](0, 8)),
6515-
byteAt = function(offset) {return offset < data.length ? data[offset] : 0;};
6516-
if (0x89 === byteAt(0)
6517-
&& 0x50 === byteAt(1)
6518-
&& 0x4e === byteAt(2)
6519-
&& 0x47 === byteAt(3)
6520-
&& 0x0d === byteAt(4)
6521-
&& 0x0a === byteAt(5)
6522-
&& 0x1a === byteAt(6)
6523-
&& 0x0a === byteAt(7)
6524-
) return 'PNG';
6525-
else if (0x47 === byteAt(0)
6526-
&& 0x49 === byteAt(1)
6527-
&& 0x46 === byteAt(2)
6528-
&& 0x38 === byteAt(3)
6529-
&& (0x37 === byteAt(4) || 0x39 === byteAt(4))
6530-
&& 0x61 === byteAt(5)
6531-
) return 'GIF';
6532-
else if (0xff === byteAt(0)
6533-
&& 0xd8 === byteAt(1)
6534-
/*&& 0xff === byteAt(2)
6535-
&& 0xdb === byteAt(3)*/
6536-
) return 'JPG';
6537-
return 'NOT_SUPPORTED';
6538-
};
6572+
Image.detectImageType = detect_image_type;
65396573

65406574
function CanvasLite(width, height)
65416575
{

0 commit comments

Comments
 (0)