diff --git a/lib/canvas.js b/lib/canvas.js index 3502a64..ccdfd4a 100644 --- a/lib/canvas.js +++ b/lib/canvas.js @@ -146,7 +146,7 @@ Context2d.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ Context2d.prototype.__defineSetter__('fillStyle', function(val){ if (val instanceof CanvasGradient) { - return this.setSource(val); + this.setFillPattern(val); } else if ('string' == typeof val) { var rgba = exports.parseColor(val) || [0,0,0,1]; this.lastFillStyle = rgba; @@ -177,13 +177,17 @@ Context2d.prototype.__defineGetter__('fillStyle', function(){ */ Context2d.prototype.__defineSetter__('strokeStyle', function(val){ - var rgba = exports.parseColor(val) || [0,0,0,1]; - this.lastStrokeStyle = rgba; - this.setStrokeRGBA( - rgba[0] - , rgba[1] - , rgba[2] - , rgba[3]); + if (val instanceof CanvasGradient) { + this.setStrokePattern(val); + } else if ('string' == typeof val) { + var rgba = exports.parseColor(val) || [0,0,0,1]; + this.lastStrokeStyle = rgba; + this.setStrokeRGBA( + rgba[0] + , rgba[1] + , rgba[2] + , rgba[3]); + } }); /** diff --git a/src/context2d.cc b/src/context2d.cc index 979a07b..ee76c5e 100644 --- a/src/context2d.cc +++ b/src/context2d.cc @@ -24,6 +24,12 @@ using namespace node; _.b = B / 255 * 1; \ _.a = A; \ +#define SET_SOURCE(C) \ + if (C##Pattern) \ + cairo_set_source(ctx, C##Pattern); \ + else \ + SET_SOURCE_RGBA(C) + /* * Set source RGBA. */ @@ -81,9 +87,10 @@ Context2d::Initialize(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "beginPath", BeginPath); NODE_SET_PROTOTYPE_METHOD(t, "closePath", ClosePath); NODE_SET_PROTOTYPE_METHOD(t, "arc", Arc); - NODE_SET_PROTOTYPE_METHOD(t, "setSource", SetSource); NODE_SET_PROTOTYPE_METHOD(t, "setFillRGBA", SetFillRGBA); NODE_SET_PROTOTYPE_METHOD(t, "setStrokeRGBA", SetStrokeRGBA); + NODE_SET_PROTOTYPE_METHOD(t, "setFillPattern", SetFillPattern); + NODE_SET_PROTOTYPE_METHOD(t, "setStrokePattern", SetStrokePattern); proto->SetAccessor(String::NewSymbol("globalCompositeOperation"), GetGlobalCompositeOperation, SetGlobalCompositeOperation); proto->SetAccessor(String::NewSymbol("globalAlpha"), GetGlobalAlpha, SetGlobalAlpha); proto->SetAccessor(String::NewSymbol("miterLimit"), GetMiterLimit, SetMiterLimit); @@ -114,6 +121,7 @@ Context2d::Context2d(Canvas *canvas): ObjectWrap() { _canvas = canvas; _context = cairo_create(canvas->getSurface()); cairo_set_line_width(_context, 1); + fillPattern = strokePattern = NULL; globalAlpha = -1; RGBA(fill,0,0,0,1); RGBA(stroke,0,0,0,1); @@ -322,16 +330,30 @@ Context2d::SetLineCap(Local prop, Local val, const AccessorInfo & } /* - * Set source pattern, used internally for fillStyle= + * Set fill pattern, used internally for fillStyle= + */ + +Handle +Context2d::SetFillPattern(const Arguments &args) { + HandleScope scope; + // TODO: HasInstance / error handling + Context2d *context = ObjectWrap::Unwrap(args.This()); + Gradient *grad = ObjectWrap::Unwrap(args[0]->ToObject()); + context->fillPattern = grad->getPattern(); + return Undefined(); +} + +/* + * Set stroke pattern, used internally for strokeStyle= */ Handle -Context2d::SetSource(const Arguments &args) { +Context2d::SetStrokePattern(const Arguments &args) { HandleScope scope; // TODO: HasInstance / error handling Context2d *context = ObjectWrap::Unwrap(args.This()); Gradient *grad = ObjectWrap::Unwrap(args[0]->ToObject()); - cairo_set_source(context->getContext(), grad->getPattern()); + context->strokePattern = grad->getPattern(); return Undefined(); } @@ -509,7 +531,7 @@ Context2d::Fill(const Arguments &args) { HandleScope scope; Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->getContext(); - SET_SOURCE_RGBA(context->fill); + SET_SOURCE(context->fill); cairo_fill_preserve(ctx); return Undefined(); } @@ -523,7 +545,7 @@ Context2d::Stroke(const Arguments &args) { HandleScope scope; Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->getContext(); - SET_SOURCE_RGBA(context->stroke); + SET_SOURCE(context->stroke); cairo_stroke_preserve(ctx); return Undefined(); } @@ -581,7 +603,7 @@ Context2d::FillRect(const Arguments &args) { Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->getContext(); cairo_rectangle(ctx, x, y, width, height); - SET_SOURCE_RGBA(context->fill); + SET_SOURCE(context->fill); cairo_fill(ctx); return Undefined(); } @@ -597,7 +619,7 @@ Context2d::StrokeRect(const Arguments &args) { Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->getContext(); cairo_rectangle(ctx, x, y, width, height); - SET_SOURCE_RGBA(context->stroke); + SET_SOURCE(context->stroke); cairo_stroke(ctx); return Undefined(); } @@ -614,7 +636,6 @@ Context2d::ClearRect(const Arguments &args) { cairo_t *ctx = context->getContext(); cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR); cairo_rectangle(ctx, x, y, width, height); - SET_SOURCE_RGBA(context->fill); cairo_fill(ctx); cairo_set_operator(ctx, CAIRO_OPERATOR_OVER); return Undefined(); diff --git a/src/context2d.h b/src/context2d.h index dc9fcf2..b348c9f 100644 --- a/src/context2d.h +++ b/src/context2d.h @@ -9,6 +9,7 @@ #define __NODE_CONTEXT2D_H__ #include "canvas.h" +#include "gradient.h" typedef struct { float r, g, b, a; @@ -18,6 +19,8 @@ class Context2d: public node::ObjectWrap { public: rgba_t fill; rgba_t stroke; + cairo_pattern_t *fillPattern; + cairo_pattern_t *strokePattern; float globalAlpha; static void Initialize(Handle target); static Handle New(const Arguments &args); @@ -34,6 +37,8 @@ class Context2d: public node::ObjectWrap { static Handle SetSource(const Arguments &args); static Handle SetFillRGBA(const Arguments &args); static Handle SetStrokeRGBA(const Arguments &args); + static Handle SetFillPattern(const Arguments &args); + static Handle SetStrokePattern(const Arguments &args); static Handle BezierCurveTo(const Arguments &args); static Handle LineTo(const Arguments &args); static Handle MoveTo(const Arguments &args);