@shqld/canvas 2.11.2-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/Readme.md +600 -0
  2. package/binding.gyp +230 -0
  3. package/browser.js +35 -0
  4. package/index.js +94 -0
  5. package/lib/DOMMatrix.js +620 -0
  6. package/lib/bindings.js +80 -0
  7. package/lib/canvas.js +113 -0
  8. package/lib/context2d.js +14 -0
  9. package/lib/image.js +96 -0
  10. package/lib/jpegstream.js +41 -0
  11. package/lib/parse-font.js +101 -0
  12. package/lib/pattern.js +17 -0
  13. package/lib/pdfstream.js +35 -0
  14. package/lib/pngstream.js +42 -0
  15. package/package.json +71 -0
  16. package/scripts/install.js +24 -0
  17. package/src/Backends.cc +18 -0
  18. package/src/Backends.h +10 -0
  19. package/src/Canvas.cc +965 -0
  20. package/src/Canvas.h +96 -0
  21. package/src/CanvasError.h +23 -0
  22. package/src/CanvasGradient.cc +123 -0
  23. package/src/CanvasGradient.h +22 -0
  24. package/src/CanvasPattern.cc +136 -0
  25. package/src/CanvasPattern.h +37 -0
  26. package/src/CanvasRenderingContext2d.cc +3360 -0
  27. package/src/CanvasRenderingContext2d.h +225 -0
  28. package/src/Image.cc +1434 -0
  29. package/src/Image.h +127 -0
  30. package/src/ImageData.cc +146 -0
  31. package/src/ImageData.h +27 -0
  32. package/src/JPEGStream.h +167 -0
  33. package/src/PNG.h +292 -0
  34. package/src/Point.h +11 -0
  35. package/src/Util.h +9 -0
  36. package/src/backend/Backend.cc +112 -0
  37. package/src/backend/Backend.h +69 -0
  38. package/src/backend/ImageBackend.cc +74 -0
  39. package/src/backend/ImageBackend.h +26 -0
  40. package/src/backend/PdfBackend.cc +53 -0
  41. package/src/backend/PdfBackend.h +24 -0
  42. package/src/backend/SvgBackend.cc +61 -0
  43. package/src/backend/SvgBackend.h +24 -0
  44. package/src/bmp/BMPParser.cc +457 -0
  45. package/src/bmp/BMPParser.h +60 -0
  46. package/src/bmp/LICENSE.md +24 -0
  47. package/src/closure.cc +26 -0
  48. package/src/closure.h +81 -0
  49. package/src/color.cc +779 -0
  50. package/src/color.h +30 -0
  51. package/src/dll_visibility.h +20 -0
  52. package/src/init.cc +94 -0
  53. package/src/register_font.cc +408 -0
  54. package/src/register_font.h +7 -0
  55. package/types/index.d.ts +484 -0
  56. package/util/has_lib.js +119 -0
  57. package/util/win_jpeg_lookup.js +21 -0
package/src/Image.h ADDED
@@ -0,0 +1,127 @@
1
+ // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
2
+
3
+ #pragma once
4
+
5
+ #include <cairo.h>
6
+ #include "CanvasError.h"
7
+ #include <functional>
8
+ #include <nan.h>
9
+ #include <stdint.h> // node < 7 uses libstdc++ on macOS which lacks complete c++11
10
+ #include <v8.h>
11
+
12
+ #ifdef HAVE_JPEG
13
+ #include <jpeglib.h>
14
+ #include <jerror.h>
15
+ #endif
16
+
17
+ #ifdef HAVE_GIF
18
+ #include <gif_lib.h>
19
+
20
+ #if GIFLIB_MAJOR > 5 || GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1
21
+ #define GIF_CLOSE_FILE(gif) DGifCloseFile(gif, NULL)
22
+ #else
23
+ #define GIF_CLOSE_FILE(gif) DGifCloseFile(gif)
24
+ #endif
25
+ #endif
26
+
27
+ #ifdef HAVE_RSVG
28
+ #include <librsvg/rsvg.h>
29
+ // librsvg <= 2.36.1, identified by undefined macro, needs an extra include
30
+ #ifndef LIBRSVG_CHECK_VERSION
31
+ #include <librsvg/rsvg-cairo.h>
32
+ #endif
33
+ #endif
34
+
35
+ using JPEGDecodeL = std::function<uint32_t (uint8_t* const src)>;
36
+
37
+ class Image: public Nan::ObjectWrap {
38
+ public:
39
+ char *filename;
40
+ int width, height;
41
+ int naturalWidth, naturalHeight;
42
+ static Nan::Persistent<v8::FunctionTemplate> constructor;
43
+ static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
44
+ static NAN_METHOD(New);
45
+ static NAN_GETTER(GetComplete);
46
+ static NAN_GETTER(GetWidth);
47
+ static NAN_GETTER(GetHeight);
48
+ static NAN_GETTER(GetNaturalWidth);
49
+ static NAN_GETTER(GetNaturalHeight);
50
+ static NAN_GETTER(GetDataMode);
51
+ static NAN_SETTER(SetDataMode);
52
+ static NAN_SETTER(SetWidth);
53
+ static NAN_SETTER(SetHeight);
54
+ static NAN_METHOD(GetSource);
55
+ static NAN_METHOD(SetSource);
56
+ inline uint8_t *data(){ return cairo_image_surface_get_data(_surface); }
57
+ inline int stride(){ return cairo_image_surface_get_stride(_surface); }
58
+ static int isPNG(uint8_t *data);
59
+ static int isJPEG(uint8_t *data);
60
+ static int isGIF(uint8_t *data);
61
+ static int isSVG(uint8_t *data, unsigned len);
62
+ static int isBMP(uint8_t *data, unsigned len);
63
+ static cairo_status_t readPNG(void *closure, unsigned char *data, unsigned len);
64
+ inline int isComplete(){ return COMPLETE == state; }
65
+ cairo_surface_t *surface();
66
+ cairo_status_t loadSurface();
67
+ cairo_status_t loadFromBuffer(uint8_t *buf, unsigned len);
68
+ cairo_status_t loadPNGFromBuffer(uint8_t *buf);
69
+ cairo_status_t loadPNG();
70
+ void clearData();
71
+ #ifdef HAVE_RSVG
72
+ cairo_status_t loadSVGFromBuffer(uint8_t *buf, unsigned len);
73
+ cairo_status_t loadSVG(FILE *stream);
74
+ cairo_status_t renderSVGToSurface();
75
+ #endif
76
+ #ifdef HAVE_GIF
77
+ cairo_status_t loadGIFFromBuffer(uint8_t *buf, unsigned len);
78
+ cairo_status_t loadGIF(FILE *stream);
79
+ #endif
80
+ #ifdef HAVE_JPEG
81
+ cairo_status_t loadJPEGFromBuffer(uint8_t *buf, unsigned len);
82
+ cairo_status_t loadJPEG(FILE *stream);
83
+ void jpegToARGB(jpeg_decompress_struct* args, uint8_t* data, uint8_t* src, JPEGDecodeL decode);
84
+ cairo_status_t decodeJPEGIntoSurface(jpeg_decompress_struct *info);
85
+ cairo_status_t decodeJPEGBufferIntoMimeSurface(uint8_t *buf, unsigned len);
86
+ cairo_status_t assignDataAsMime(uint8_t *data, int len, const char *mime_type);
87
+ #endif
88
+ cairo_status_t loadBMPFromBuffer(uint8_t *buf, unsigned len);
89
+ cairo_status_t loadBMP(FILE *stream);
90
+ CanvasError errorInfo;
91
+ void loaded();
92
+ cairo_status_t load();
93
+ Image();
94
+
95
+ enum {
96
+ DEFAULT
97
+ , LOADING
98
+ , COMPLETE
99
+ } state;
100
+
101
+ enum data_mode_t {
102
+ DATA_IMAGE = 1
103
+ , DATA_MIME = 2
104
+ } data_mode;
105
+
106
+ typedef enum {
107
+ UNKNOWN
108
+ , GIF
109
+ , JPEG
110
+ , PNG
111
+ , SVG
112
+ } type;
113
+
114
+ static type extension(const char *filename);
115
+
116
+ private:
117
+ cairo_surface_t *_surface;
118
+ uint8_t *_data = nullptr;
119
+ int _data_len;
120
+ #ifdef HAVE_RSVG
121
+ RsvgHandle *_rsvg;
122
+ bool _is_svg;
123
+ int _svg_last_width;
124
+ int _svg_last_height;
125
+ #endif
126
+ ~Image();
127
+ };
@@ -0,0 +1,146 @@
1
+ // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
2
+
3
+ #include "ImageData.h"
4
+
5
+ using namespace v8;
6
+
7
+ Nan::Persistent<FunctionTemplate> ImageData::constructor;
8
+
9
+ /*
10
+ * Initialize ImageData.
11
+ */
12
+
13
+ void
14
+ ImageData::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
15
+ Nan::HandleScope scope;
16
+
17
+ // Constructor
18
+ Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(ImageData::New);
19
+ constructor.Reset(ctor);
20
+ ctor->InstanceTemplate()->SetInternalFieldCount(1);
21
+ ctor->SetClassName(Nan::New("ImageData").ToLocalChecked());
22
+
23
+ // Prototype
24
+ Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
25
+ Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth);
26
+ Nan::SetAccessor(proto, Nan::New("height").ToLocalChecked(), GetHeight);
27
+ Local<Context> ctx = Nan::GetCurrentContext();
28
+ Nan::Set(target, Nan::New("ImageData").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked());
29
+ }
30
+
31
+ /*
32
+ * Initialize a new ImageData object.
33
+ */
34
+
35
+ NAN_METHOD(ImageData::New) {
36
+ if (!info.IsConstructCall()) {
37
+ return Nan::ThrowTypeError("Class constructors cannot be invoked without 'new'");
38
+ }
39
+
40
+ Local<TypedArray> dataArray;
41
+ uint32_t width;
42
+ uint32_t height;
43
+ int length;
44
+
45
+ if (info[0]->IsUint32() && info[1]->IsUint32()) {
46
+ width = Nan::To<uint32_t>(info[0]).FromMaybe(0);
47
+ if (width == 0) {
48
+ Nan::ThrowRangeError("The source width is zero.");
49
+ return;
50
+ }
51
+ height = Nan::To<uint32_t>(info[1]).FromMaybe(0);
52
+ if (height == 0) {
53
+ Nan::ThrowRangeError("The source height is zero.");
54
+ return;
55
+ }
56
+ length = width * height * 4; // ImageData(w, h) constructor assumes 4 BPP; documented.
57
+
58
+ dataArray = Uint8ClampedArray::New(ArrayBuffer::New(Isolate::GetCurrent(), length), 0, length);
59
+
60
+ } else if (info[0]->IsUint8ClampedArray() && info[1]->IsUint32()) {
61
+ dataArray = info[0].As<Uint8ClampedArray>();
62
+
63
+ length = dataArray->Length();
64
+ if (length == 0) {
65
+ Nan::ThrowRangeError("The input data has a zero byte length.");
66
+ return;
67
+ }
68
+
69
+ // Don't assert that the ImageData length is a multiple of four because some
70
+ // data formats are not 4 BPP.
71
+
72
+ width = Nan::To<uint32_t>(info[1]).FromMaybe(0);
73
+ if (width == 0) {
74
+ Nan::ThrowRangeError("The source width is zero.");
75
+ return;
76
+ }
77
+
78
+ // Don't assert that the byte length is a multiple of 4 * width, ditto.
79
+
80
+ if (info[2]->IsUint32()) { // Explicit height given
81
+ height = Nan::To<uint32_t>(info[2]).FromMaybe(0);
82
+ } else { // Calculate height assuming 4 BPP
83
+ int size = length / 4;
84
+ height = size / width;
85
+ }
86
+
87
+ } else if (info[0]->IsUint16Array() && info[1]->IsUint32()) { // Intended for RGB16_565 format
88
+ dataArray = info[0].As<Uint16Array>();
89
+
90
+ length = dataArray->Length();
91
+ if (length == 0) {
92
+ Nan::ThrowRangeError("The input data has a zero byte length.");
93
+ return;
94
+ }
95
+
96
+ width = Nan::To<uint32_t>(info[1]).FromMaybe(0);
97
+ if (width == 0) {
98
+ Nan::ThrowRangeError("The source width is zero.");
99
+ return;
100
+ }
101
+
102
+ if (info[2]->IsUint32()) { // Explicit height given
103
+ height = Nan::To<uint32_t>(info[2]).FromMaybe(0);
104
+ } else { // Calculate height assuming 2 BPP
105
+ int size = length / 2;
106
+ height = size / width;
107
+ }
108
+
109
+ } else {
110
+ Nan::ThrowTypeError("Expected (Uint8ClampedArray, width[, height]), (Uint16Array, width[, height]) or (width, height)");
111
+ return;
112
+ }
113
+
114
+ Nan::TypedArrayContents<uint8_t> dataPtr(dataArray);
115
+
116
+ ImageData *imageData = new ImageData(reinterpret_cast<uint8_t*>(*dataPtr), width, height);
117
+ imageData->Wrap(info.This());
118
+ Nan::Set(info.This(), Nan::New("data").ToLocalChecked(), dataArray).Check();
119
+ info.GetReturnValue().Set(info.This());
120
+ }
121
+
122
+ /*
123
+ * Get width.
124
+ */
125
+
126
+ NAN_GETTER(ImageData::GetWidth) {
127
+ if (!ImageData::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
128
+ Nan::ThrowTypeError("Method ImageData.GetWidth called on incompatible receiver");
129
+ return;
130
+ }
131
+ ImageData *imageData = Nan::ObjectWrap::Unwrap<ImageData>(info.This());
132
+ info.GetReturnValue().Set(Nan::New<Number>(imageData->width()));
133
+ }
134
+
135
+ /*
136
+ * Get height.
137
+ */
138
+
139
+ NAN_GETTER(ImageData::GetHeight) {
140
+ if (!ImageData::constructor.Get(info.GetIsolate())->HasInstance(info.This())) {
141
+ Nan::ThrowTypeError("Method ImageData.GetHeight called on incompatible receiver");
142
+ return;
143
+ }
144
+ ImageData *imageData = Nan::ObjectWrap::Unwrap<ImageData>(info.This());
145
+ info.GetReturnValue().Set(Nan::New<Number>(imageData->height()));
146
+ }
@@ -0,0 +1,27 @@
1
+ // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
2
+
3
+ #pragma once
4
+
5
+ #include <nan.h>
6
+ #include <stdint.h> // node < 7 uses libstdc++ on macOS which lacks complete c++11
7
+ #include <v8.h>
8
+
9
+ class ImageData: public Nan::ObjectWrap {
10
+ public:
11
+ static Nan::Persistent<v8::FunctionTemplate> constructor;
12
+ static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target);
13
+ static NAN_METHOD(New);
14
+ static NAN_GETTER(GetWidth);
15
+ static NAN_GETTER(GetHeight);
16
+
17
+ inline int width() { return _width; }
18
+ inline int height() { return _height; }
19
+ inline uint8_t *data() { return _data; }
20
+ ImageData(uint8_t *data, int width, int height) : _width(width), _height(height), _data(data) {}
21
+
22
+ private:
23
+ int _width;
24
+ int _height;
25
+ uint8_t *_data;
26
+
27
+ };
@@ -0,0 +1,167 @@
1
+ #pragma once
2
+
3
+ #include "closure.h"
4
+ #include <jpeglib.h>
5
+ #include <jerror.h>
6
+
7
+ /*
8
+ * Expanded data destination object for closure output,
9
+ * inspired by IJG's jdatadst.c
10
+ */
11
+
12
+ struct closure_destination_mgr {
13
+ jpeg_destination_mgr pub;
14
+ JpegClosure* closure;
15
+ JOCTET *buffer;
16
+ int bufsize;
17
+ };
18
+
19
+ void
20
+ init_closure_destination(j_compress_ptr cinfo){
21
+ // we really don't have to do anything here
22
+ }
23
+
24
+ boolean
25
+ empty_closure_output_buffer(j_compress_ptr cinfo){
26
+ Nan::HandleScope scope;
27
+ Nan::AsyncResource async("canvas:empty_closure_output_buffer");
28
+ closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest;
29
+
30
+ v8::Local<v8::Object> buf = Nan::NewBuffer((char *)dest->buffer, dest->bufsize).ToLocalChecked();
31
+
32
+ // emit "data"
33
+ v8::Local<v8::Value> argv[2] = {
34
+ Nan::Null()
35
+ , buf
36
+ };
37
+ dest->closure->cb.Call(sizeof argv / sizeof *argv, argv, &async);
38
+
39
+ dest->buffer = (JOCTET *)malloc(dest->bufsize);
40
+ cinfo->dest->next_output_byte = dest->buffer;
41
+ cinfo->dest->free_in_buffer = dest->bufsize;
42
+ return true;
43
+ }
44
+
45
+ void
46
+ term_closure_destination(j_compress_ptr cinfo){
47
+ Nan::HandleScope scope;
48
+ Nan::AsyncResource async("canvas:term_closure_destination");
49
+ closure_destination_mgr *dest = (closure_destination_mgr *) cinfo->dest;
50
+
51
+ /* emit remaining data */
52
+ v8::Local<v8::Object> buf = Nan::NewBuffer((char *)dest->buffer, dest->bufsize - dest->pub.free_in_buffer).ToLocalChecked();
53
+
54
+ v8::Local<v8::Value> data_argv[2] = {
55
+ Nan::Null()
56
+ , buf
57
+ };
58
+ dest->closure->cb.Call(sizeof data_argv / sizeof *data_argv, data_argv, &async);
59
+
60
+ // emit "end"
61
+ v8::Local<v8::Value> end_argv[2] = {
62
+ Nan::Null()
63
+ , Nan::Null()
64
+ };
65
+ dest->closure->cb.Call(sizeof end_argv / sizeof *end_argv, end_argv, &async);
66
+ }
67
+
68
+ void
69
+ jpeg_closure_dest(j_compress_ptr cinfo, JpegClosure* closure, int bufsize){
70
+ closure_destination_mgr * dest;
71
+
72
+ /* The destination object is made permanent so that multiple JPEG images
73
+ * can be written to the same buffer without re-executing jpeg_mem_dest.
74
+ */
75
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
76
+ cinfo->dest = (struct jpeg_destination_mgr *)
77
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
78
+ sizeof(closure_destination_mgr));
79
+ }
80
+
81
+ dest = (closure_destination_mgr *) cinfo->dest;
82
+
83
+ cinfo->dest->init_destination = &init_closure_destination;
84
+ cinfo->dest->empty_output_buffer = &empty_closure_output_buffer;
85
+ cinfo->dest->term_destination = &term_closure_destination;
86
+
87
+ dest->closure = closure;
88
+ dest->bufsize = bufsize;
89
+ dest->buffer = (JOCTET *)malloc(bufsize);
90
+
91
+ cinfo->dest->next_output_byte = dest->buffer;
92
+ cinfo->dest->free_in_buffer = dest->bufsize;
93
+ }
94
+
95
+ void encode_jpeg(jpeg_compress_struct cinfo, cairo_surface_t *surface, int quality, bool progressive, int chromaHSampFactor, int chromaVSampFactor) {
96
+ int w = cairo_image_surface_get_width(surface);
97
+ int h = cairo_image_surface_get_height(surface);
98
+
99
+ cinfo.in_color_space = JCS_RGB;
100
+ cinfo.input_components = 3;
101
+ cinfo.image_width = w;
102
+ cinfo.image_height = h;
103
+ jpeg_set_defaults(&cinfo);
104
+ if (progressive)
105
+ jpeg_simple_progression(&cinfo);
106
+ jpeg_set_quality(&cinfo, quality, (quality < 25) ? 0 : 1);
107
+ cinfo.comp_info[0].h_samp_factor = chromaHSampFactor;
108
+ cinfo.comp_info[0].v_samp_factor = chromaVSampFactor;
109
+
110
+ JSAMPROW slr;
111
+ jpeg_start_compress(&cinfo, TRUE);
112
+ unsigned char *dst;
113
+ unsigned int *src = (unsigned int *)cairo_image_surface_get_data(surface);
114
+ int sl = 0;
115
+ dst = (unsigned char *)malloc(w * 3);
116
+ while (sl < h) {
117
+ unsigned char *dp = dst;
118
+ int x = 0;
119
+ while (x < w) {
120
+ dp[0] = (*src >> 16) & 255;
121
+ dp[1] = (*src >> 8) & 255;
122
+ dp[2] = *src & 255;
123
+ src++;
124
+ dp += 3;
125
+ x++;
126
+ }
127
+ slr = dst;
128
+ jpeg_write_scanlines(&cinfo, &slr, 1);
129
+ sl++;
130
+ }
131
+ free(dst);
132
+ jpeg_finish_compress(&cinfo);
133
+ jpeg_destroy_compress(&cinfo);
134
+ }
135
+
136
+ void
137
+ write_to_jpeg_stream(cairo_surface_t *surface, int bufsize, JpegClosure* closure) {
138
+ jpeg_compress_struct cinfo;
139
+ jpeg_error_mgr jerr;
140
+ cinfo.err = jpeg_std_error(&jerr);
141
+ jpeg_create_compress(&cinfo);
142
+ jpeg_closure_dest(&cinfo, closure, bufsize);
143
+ encode_jpeg(
144
+ cinfo,
145
+ surface,
146
+ closure->quality,
147
+ closure->progressive,
148
+ closure->chromaSubsampling,
149
+ closure->chromaSubsampling);
150
+ }
151
+
152
+ void
153
+ write_to_jpeg_buffer(cairo_surface_t* surface, JpegClosure* closure) {
154
+ jpeg_compress_struct cinfo;
155
+ jpeg_error_mgr jerr;
156
+ cinfo.err = jpeg_std_error(&jerr);
157
+ jpeg_create_compress(&cinfo);
158
+ cinfo.client_data = closure;
159
+ cinfo.dest = closure->jpeg_dest_mgr;
160
+ encode_jpeg(
161
+ cinfo,
162
+ surface,
163
+ closure->quality,
164
+ closure->progressive,
165
+ closure->chromaSubsampling,
166
+ closure->chromaSubsampling);
167
+ }