From 2ffab334b7de3ad8dcbc97026070994c45425b48 Mon Sep 17 00:00:00 2001 From: basvanmeurs Date: Mon, 24 Apr 2017 11:07:38 +0200 Subject: [PATCH 1/4] Image.getRawData method --- src/Image.cc | 18 ++++++++++++++++++ src/Image.h | 1 + test/image.test.js | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/src/Image.cc b/src/Image.cc index 0147f878f..f742dc846 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -45,6 +45,7 @@ Image::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { // Prototype Local proto = ctor->PrototypeTemplate(); + Nan::SetPrototypeMethod(ctor, "getRawData", GetRawData); Nan::SetAccessor(proto, Nan::New("source").ToLocalChecked(), GetSource, SetSource); Nan::SetAccessor(proto, Nan::New("complete").ToLocalChecked(), GetComplete); Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth); @@ -815,6 +816,23 @@ clearMimeData(void *closure) { free(closure); } +NAN_METHOD(Image::GetRawData) { + Image *img = Nan::ObjectWrap::Unwrap(info.This()); + if (img->_surface) { + // Return raw ARGB data -- just a memcpy() + cairo_surface_t *surface = img->_surface; + cairo_surface_flush(surface); + const unsigned char *data = cairo_image_surface_get_data(surface); + + unsigned int nBytes = img->width * img->height * 4; + Local buf = Nan::CopyBuffer(reinterpret_cast(data), nBytes).ToLocalChecked(); + info.GetReturnValue().Set(buf); + } else { + info.GetReturnValue().Set(Nan::Undefined()); + } + return; +} + /* * Assign a given buffer as mime data against the surface. * The provided buffer will be copied, and the copy will diff --git a/src/Image.h b/src/Image.h index 5c7d6a282..cd1d00041 100644 --- a/src/Image.h +++ b/src/Image.h @@ -36,6 +36,7 @@ class Image: public Nan::ObjectWrap { static Nan::Persistent constructor; static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target); static NAN_METHOD(New); + static NAN_METHOD(GetRawData); static NAN_GETTER(GetSource); static NAN_GETTER(GetOnload); static NAN_GETTER(GetOnerror); diff --git a/test/image.test.js b/test/image.test.js index ae39d6207..08155f826 100644 --- a/test/image.test.js +++ b/test/image.test.js @@ -70,6 +70,14 @@ describe('Image', function () { assert.equal(onloadCalled, 1); }); + it('Image#getRawData', function() { + var img = new Image(); + img.src = png_clock; + var buf = img.getRawData(); + assert.ok(buf instanceof Buffer); + assert.strictEqual(409600, img.getRawData().byteLength); + }); + it('Image#onerror', function () { var img = new Image , error From b5ac2bffba55e30608f2bb4c448e01dc15632574 Mon Sep 17 00:00:00 2001 From: basvanmeurs Date: Mon, 24 Apr 2017 11:59:50 +0200 Subject: [PATCH 2/4] Image.getRawData test case: support for node 0.12 and 0.10 --- test/image.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/image.test.js b/test/image.test.js index 08155f826..84e876986 100644 --- a/test/image.test.js +++ b/test/image.test.js @@ -75,7 +75,7 @@ describe('Image', function () { img.src = png_clock; var buf = img.getRawData(); assert.ok(buf instanceof Buffer); - assert.strictEqual(409600, img.getRawData().byteLength); + assert.strictEqual(409600, img.getRawData().length); }); it('Image#onerror', function () { From 6b15caac81940e9f21595003f66cc046ec0bd2f8 Mon Sep 17 00:00:00 2001 From: basvanmeurs Date: Wed, 10 May 2017 16:31:51 +0200 Subject: [PATCH 3/4] reverted to manual font parsing due to https://github.com/Automattic/node-canvas/issues/920 --- lib/context2d.js | 69 ++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/lib/context2d.js b/lib/context2d.js index e95421e61..3ecb37922 100644 --- a/lib/context2d.js +++ b/lib/context2d.js @@ -16,10 +16,6 @@ var canvas = require('./bindings') , CanvasPattern = canvas.CanvasPattern , ImageData = canvas.ImageData; -var parseCssFont = require('parse-css-font'); - -var unitsCss = require('units-css'); - /** * Export `Context2d` as the module. */ @@ -38,6 +34,26 @@ var cache = {}; var baselines = ['alphabetic', 'top', 'bottom', 'middle', 'ideographic', 'hanging']; +/** + * Font RegExp helpers. + */ + +var weights = 'normal|bold|bolder|lighter|[1-9]00' + , styles = 'normal|italic|oblique' + , units = 'px|pt|pc|in|cm|mm|%' + , string = '\'([^\']+)\'|"([^"]+)"|[\\w-]+'; + +/** + * Font parser RegExp; + */ + +var fontre = new RegExp('^ *' + + '(?:(' + weights + ') *)?' + + '(?:(' + styles + ') *)?' + + '([\\d\\.]+)(' + units + ') *' + + '((?:' + string + ')( *, *(?:' + string + '))*)' + ); + /** * Parse font `str`. * @@ -46,51 +62,42 @@ var baselines = ['alphabetic', 'top', 'bottom', 'middle', 'ideographic', 'hangin * @api private */ -var parseFont = exports.parseFont = function(str) { - var parsedFont; +var parseFont = exports.parseFont = function(str){ + var font = {} + , captures = fontre.exec(str); - // Try to parse the font string using parse-css-font. - // It will throw an exception if it fails. - try { - parsedFont = parseCssFont(str); - } - catch (e) { - // Invalid - return; - } + // Invalid + if (!captures) return; // Cached if (cache[str]) return cache[str]; - // Parse size into value and unit using units-css - var size = unitsCss.parse(parsedFont.size); + // Populate font object + font.weight = captures[1] || 'normal'; + font.style = captures[2] || 'normal'; + font.size = parseFloat(captures[3]); + font.unit = captures[4]; + font.family = captures[5].replace(/["']/g, '').split(',').map(function (family) { + return family.trim(); + }).join(','); // TODO: dpi // TODO: remaining unit conversion - switch (size.unit) { + switch (font.unit) { case 'pt': - size.value /= .75; + font.size /= .75; break; case 'in': - size.value *= 96; + font.size *= 96; break; case 'mm': - size.value *= 96.0 / 25.4; + font.size *= 96.0 / 25.4; break; case 'cm': - size.value *= 96.0 / 2.54; + font.size *= 96.0 / 2.54; break; } - // Populate font object - var font = { - weight: parsedFont.weight, - style: parsedFont.style, - size: size.value, - unit: size.unit, - family: parsedFont.family.join(',') - }; - return cache[str] = font; }; From 86ed53a217507a7f20351f0ed5eda89dce9301db Mon Sep 17 00:00:00 2001 From: basvanmeurs Date: Thu, 28 Dec 2017 13:21:54 +0100 Subject: [PATCH 4/4] convert getRawData to rawData because NAN-related issues with prototype functions --- src/Image.cc | 41 +++++++++++++++++++++++------------------ src/Image.h | 2 +- test/image.test.js | 6 +++--- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/Image.cc b/src/Image.cc index f742dc846..029ae84b5 100644 --- a/src/Image.cc +++ b/src/Image.cc @@ -45,7 +45,7 @@ Image::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { // Prototype Local proto = ctor->PrototypeTemplate(); - Nan::SetPrototypeMethod(ctor, "getRawData", GetRawData); + Nan::SetAccessor(proto, Nan::New("rawData").ToLocalChecked(), GetRawData); Nan::SetAccessor(proto, Nan::New("source").ToLocalChecked(), GetSource, SetSource); Nan::SetAccessor(proto, Nan::New("complete").ToLocalChecked(), GetComplete); Nan::SetAccessor(proto, Nan::New("width").ToLocalChecked(), GetWidth); @@ -135,6 +135,28 @@ NAN_GETTER(Image::GetSource) { info.GetReturnValue().Set(Nan::New(img->filename ? img->filename : "").ToLocalChecked()); } + +/* + * Get raw data. + */ + +NAN_GETTER(Image::GetRawData) { + Image *img = Nan::ObjectWrap::Unwrap(info.This()); + if (img->_surface) { + // Return raw ARGB data -- just a memcpy() + cairo_surface_t *surface = img->_surface; + cairo_surface_flush(surface); + const unsigned char *data = cairo_image_surface_get_data(surface); + + unsigned int nBytes = img->width * img->height * 4; + Local buf = Nan::CopyBuffer(reinterpret_cast(data), nBytes).ToLocalChecked(); + info.GetReturnValue().Set(buf); + } else { + info.GetReturnValue().Set(Nan::Undefined()); + } + return; +} + /* * Clean up assets and variables. */ @@ -816,23 +838,6 @@ clearMimeData(void *closure) { free(closure); } -NAN_METHOD(Image::GetRawData) { - Image *img = Nan::ObjectWrap::Unwrap(info.This()); - if (img->_surface) { - // Return raw ARGB data -- just a memcpy() - cairo_surface_t *surface = img->_surface; - cairo_surface_flush(surface); - const unsigned char *data = cairo_image_surface_get_data(surface); - - unsigned int nBytes = img->width * img->height * 4; - Local buf = Nan::CopyBuffer(reinterpret_cast(data), nBytes).ToLocalChecked(); - info.GetReturnValue().Set(buf); - } else { - info.GetReturnValue().Set(Nan::Undefined()); - } - return; -} - /* * Assign a given buffer as mime data against the surface. * The provided buffer will be copied, and the copy will diff --git a/src/Image.h b/src/Image.h index cd1d00041..3d37d94b9 100644 --- a/src/Image.h +++ b/src/Image.h @@ -36,7 +36,7 @@ class Image: public Nan::ObjectWrap { static Nan::Persistent constructor; static void Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target); static NAN_METHOD(New); - static NAN_METHOD(GetRawData); + static NAN_GETTER(GetRawData); static NAN_GETTER(GetSource); static NAN_GETTER(GetOnload); static NAN_GETTER(GetOnerror); diff --git a/test/image.test.js b/test/image.test.js index 84e876986..f9a96d605 100644 --- a/test/image.test.js +++ b/test/image.test.js @@ -70,12 +70,12 @@ describe('Image', function () { assert.equal(onloadCalled, 1); }); - it('Image#getRawData', function() { + it('Image#rawData', function() { var img = new Image(); img.src = png_clock; - var buf = img.getRawData(); + var buf = img.rawData; assert.ok(buf instanceof Buffer); - assert.strictEqual(409600, img.getRawData().length); + assert.strictEqual(409600, img.rawData.length); }); it('Image#onerror', function () {