diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index dba80662b..d49a8ddca 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -123,6 +123,7 @@ Context2d::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { Nan::SetPrototypeMethod(ctor, "rotate", Rotate); Nan::SetPrototypeMethod(ctor, "translate", Translate); Nan::SetPrototypeMethod(ctor, "transform", Transform); + Nan::SetPrototypeMethod(ctor, "getTransform", GetTransform); Nan::SetPrototypeMethod(ctor, "resetTransform", ResetTransform); Nan::SetPrototypeMethod(ctor, "setTransform", SetTransform); Nan::SetPrototypeMethod(ctor, "isPointInPath", IsPointInPath); @@ -1751,11 +1752,11 @@ NAN_SETTER(Context2d::SetQuality) { } /* - * Get current transform. + * Helper for get current transform matrix */ -NAN_GETTER(Context2d::GetCurrentTransform) { - Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); +Local +get_current_transform(Context2d *context) { Isolate *iso = Isolate::GetCurrent(); Local arr = Float64Array::New(ArrayBuffer::New(iso, 48), 0, 6); @@ -1771,7 +1772,32 @@ NAN_GETTER(Context2d::GetCurrentTransform) { const int argc = 1; Local argv[argc] = { arr }; - Local instance = Nan::NewInstance(_DOMMatrix.Get(iso), argc, argv).ToLocalChecked(); + return Nan::NewInstance(context->_DOMMatrix.Get(iso), argc, argv).ToLocalChecked(); +} + +/* + * Helper for get/set transform. + */ + +void parse_matrix_from_object(cairo_matrix_t &matrix, Local mat) { + cairo_matrix_init(&matrix, + Nan::To(Nan::Get(mat, Nan::New("a").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), + Nan::To(Nan::Get(mat, Nan::New("b").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), + Nan::To(Nan::Get(mat, Nan::New("c").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), + Nan::To(Nan::Get(mat, Nan::New("d").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), + Nan::To(Nan::Get(mat, Nan::New("e").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), + Nan::To(Nan::Get(mat, Nan::New("f").ToLocalChecked()).ToLocalChecked()).FromMaybe(0) + ); +} + + +/* + * Get current transform. + */ + +NAN_GETTER(Context2d::GetCurrentTransform) { + Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); + Local instance = get_current_transform(context); info.GetReturnValue().Set(instance); } @@ -1792,14 +1818,7 @@ NAN_SETTER(Context2d::SetCurrentTransform) { #endif cairo_matrix_t matrix; - cairo_matrix_init(&matrix, - Nan::To(Nan::Get(mat, Nan::New("a").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), - Nan::To(Nan::Get(mat, Nan::New("b").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), - Nan::To(Nan::Get(mat, Nan::New("c").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), - Nan::To(Nan::Get(mat, Nan::New("d").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), - Nan::To(Nan::Get(mat, Nan::New("e").ToLocalChecked()).ToLocalChecked()).FromMaybe(0), - Nan::To(Nan::Get(mat, Nan::New("f").ToLocalChecked()).ToLocalChecked()).FromMaybe(0) - ); + parse_matrix_from_object(matrix, mat); cairo_transform(context->context(), &matrix); } @@ -2243,6 +2262,17 @@ NAN_METHOD(Context2d::Transform) { cairo_transform(context->context(), &matrix); } +/* + * Get the CTM + */ + +NAN_METHOD(Context2d::GetTransform) { + Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); + Local instance = get_current_transform(context); + + info.GetReturnValue().Set(instance); +} + /* * Reset the CTM, used internally by setTransform(). */ @@ -2258,8 +2288,24 @@ NAN_METHOD(Context2d::ResetTransform) { NAN_METHOD(Context2d::SetTransform) { Context2d *context = Nan::ObjectWrap::Unwrap(info.This()); - cairo_identity_matrix(context->context()); - Context2d::Transform(info); + if (info.Length() == 1) { + Local mat = Nan::To(info[0]).ToLocalChecked(); + + #if NODE_MAJOR_VERSION >= 8 + Local ctx = Nan::GetCurrentContext(); + if (!mat->InstanceOf(ctx, _DOMMatrix.Get(Isolate::GetCurrent())).ToChecked()) { + return Nan::ThrowTypeError("Expected DOMMatrix"); + } + #endif + + cairo_matrix_t matrix; + parse_matrix_from_object(matrix, mat); + + cairo_set_matrix(context->context(), &matrix); + } else { + cairo_identity_matrix(context->context()); + Context2d::Transform(info); + } } /* diff --git a/src/CanvasRenderingContext2d.h b/src/CanvasRenderingContext2d.h index 59d6f6d11..8afb433d1 100644 --- a/src/CanvasRenderingContext2d.h +++ b/src/CanvasRenderingContext2d.h @@ -76,6 +76,7 @@ class Context2d: public Nan::ObjectWrap { static NAN_METHOD(Translate); static NAN_METHOD(Scale); static NAN_METHOD(Transform); + static NAN_METHOD(GetTransform); static NAN_METHOD(ResetTransform); static NAN_METHOD(SetTransform); static NAN_METHOD(IsPointInPath); diff --git a/test/canvas.test.js b/test/canvas.test.js index b824f8da2..59d69005c 100644 --- a/test/canvas.test.js +++ b/test/canvas.test.js @@ -990,6 +990,14 @@ describe('Canvas', function () { var mat3 = ctx.currentTransform; assert.equal(mat3.a, 0.1); assert.equal(mat3.d, 0.3); + + assert.deepEqual(ctx.currentTransform, ctx.getTransform()); + + ctx.setTransform(ctx.getTransform()); + assert.deepEqual(mat3, ctx.getTransform()); + + ctx.setTransform(mat3.a, mat3.b, mat3.c, mat3.d, mat3.e, mat3.f); + assert.deepEqual(mat3, ctx.getTransform()); }); it('Context2d#createImageData(ImageData)', function () {