From 8cf26690d358ff9d7d28866bc4fcef72450d2442 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:11:30 -0700 Subject: [PATCH 01/12] Started Gradient --- src/canvas.cc | 2 +- src/canvas.h | 2 -- src/gradient.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gradient.h | 28 ++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/gradient.cc create mode 100644 src/gradient.h diff --git a/src/canvas.cc b/src/canvas.cc index 9068a8e..ea7bd48 100644 --- a/src/canvas.cc +++ b/src/canvas.cc @@ -37,7 +37,7 @@ Canvas::New(const Arguments &args) { if (!args[1]->IsNumber()) return ThrowException(Exception::TypeError(String::New("height required"))); - Canvas *canvas = new Canvas(args[0]->Uint32Value(), args[1]->Uint32Value()); + Canvas *canvas = new Canvas(args[0]->Int32Value(), args[1]->Int32Value()); canvas->Wrap(args.This()); return args.This(); } diff --git a/src/canvas.h b/src/canvas.h index 57138c1..104080e 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -21,8 +21,6 @@ class Canvas: public node::ObjectWrap { static Handle New(const Arguments &args); static Handle SavePNG(const Arguments &args); inline cairo_surface_t *getSurface(){ return _surface; } - - protected: Canvas(int width, int height); private: diff --git a/src/gradient.cc b/src/gradient.cc new file mode 100644 index 0000000..dfe1538 --- /dev/null +++ b/src/gradient.cc @@ -0,0 +1,48 @@ + +// +// gradient.cc +// +// Copyright (c) 2010 LearnBoost +// + +#include "canvas.h" +#include "gradient.h" + +void +Gradient::Initialize(Handle target) { + HandleScope scope; + Local t = FunctionTemplate::New(Gradient::New); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(String::NewSymbol("CanvasGradient")); + + target->Set(String::NewSymbol("CanvasGradient"), t->GetFunction()); +} + +Handle +Gradient::New(const Arguments &args) { + HandleScope scope; + + // Linear + if (4 == args.Length()) { + Gradient *grad = new Gradient( + args[0]->NumberValue() + , args[1]->NumberValue() + , args[2]->NumberValue() + , args[3]->NumberValue()); + } + + // Radial + if (6 == args.Length()) { + Gradient *grad = new Gradient( + args[0]->NumberValue() + , args[1]->NumberValue() + , args[2]->NumberValue() + , args[3]->NumberValue() + , args[4]->NumberValue() + , args[5]->NumberValue()); + grad->Wrap(args.This()); + return args.This(); + } + + return ThrowException(Exception::TypeError(String::New("invalid arguments"))); +} \ No newline at end of file diff --git a/src/gradient.h b/src/gradient.h new file mode 100644 index 0000000..48a08a3 --- /dev/null +++ b/src/gradient.h @@ -0,0 +1,28 @@ + +// +// gradient.h +// +// Copyright (c) 2010 LearnBoost +// + +#ifndef __NODE_GRADIENT_H__ +#define __NODE_GRADIENT_H__ + +#include "canvas.h" + +using namespace v8; + +class Gradient: public node::ObjectWrap { + public: + static void Initialize(Handle target); + static Handle New(const Arguments &args); + Gradient(double x0, double y0, double x1, double y1): + _x0(x0), _y0(y0), _x1(x1), _y1(y1) {}; + Gradient(double x0, double y0, double r0, double x1, double y1, double r1): + _x0(x0), _y0(y0), _x1(x1), _y1(y1), _r0(r0), _r1(r1) {}; + + private: + double _x0, _y0, _x1, _y1, _r0, _r1; +}; + +#endif \ No newline at end of file From 41a0109c3fe25d9f0ffde5c6c57159b8b3339152 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:14:35 -0700 Subject: [PATCH 02/12] Added Context2d#createRadialGradient() --- lib/canvas.js | 6 ++++++ src/node-canvas.cc | 2 ++ 2 files changed, 8 insertions(+) diff --git a/lib/canvas.js b/lib/canvas.js index fa4243d..d013d2a 100644 --- a/lib/canvas.js +++ b/lib/canvas.js @@ -13,6 +13,7 @@ var canvas = require('../build/default/canvas') , colors = require('./colors') , Canvas = canvas.Canvas , Context2d = canvas.Context2d + , CanvasGradient = canvas.CanvasGradient , cairoVersion = canvas.cairoVersion; /** @@ -118,6 +119,11 @@ Canvas.prototype.getContext = function(contextId){ } }; +Context2d.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ + return new CanvasGradient(x0, y0, r0, x1, y1, r1); +}; + + /** * Set the fill style with the given css color string. * diff --git a/src/node-canvas.cc b/src/node-canvas.cc index 6e72460..1b0ee68 100644 --- a/src/node-canvas.cc +++ b/src/node-canvas.cc @@ -7,11 +7,13 @@ #include "canvas.h" #include "context2d.h" +#include "gradient.h" extern "C" void init (Handle target) { HandleScope scope; Canvas::Initialize(target); Context2d::Initialize(target); + Gradient::Initialize(target); target->Set(String::New("cairoVersion"), String::New(cairo_version_string())); } \ No newline at end of file From e532001ce56284d6935fe6f15c2c3aedfd3b13e3 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:15:12 -0700 Subject: [PATCH 03/12] Added Context2d#createLinearGradient() --- lib/canvas.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/canvas.js b/lib/canvas.js index d013d2a..86b7843 100644 --- a/lib/canvas.js +++ b/lib/canvas.js @@ -119,11 +119,14 @@ Canvas.prototype.getContext = function(contextId){ } }; +Context2d.prototype.createLinearGradient = function(x0, y0, x1, y1){ + return new CanvasGradient(x0, y0, x1, y1); +}; + Context2d.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ return new CanvasGradient(x0, y0, r0, x1, y1, r1); }; - /** * Set the fill style with the given css color string. * From d0118c06a208768c74f581524f86818206197de4 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:19:06 -0700 Subject: [PATCH 04/12] Added Gradient constructors --- src/gradient.cc | 14 +++++++++++++- src/gradient.h | 7 +++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/gradient.cc b/src/gradient.cc index dfe1538..a2cff54 100644 --- a/src/gradient.cc +++ b/src/gradient.cc @@ -29,6 +29,8 @@ Gradient::New(const Arguments &args) { , args[1]->NumberValue() , args[2]->NumberValue() , args[3]->NumberValue()); + grad->Wrap(args.This()); + return args.This(); } // Radial @@ -45,4 +47,14 @@ Gradient::New(const Arguments &args) { } return ThrowException(Exception::TypeError(String::New("invalid arguments"))); -} \ No newline at end of file +} + +Gradient::Gradient(double x0, double y0, double x1, double y1): + _x0(x0), _y0(y0), _x1(x1), _y1(y1) { + _grad = cairo_pattern_create_linear(x0, y0, x1, y1); +} + +Gradient::Gradient(double x0, double y0, double r0, double x1, double y1, double r1): + _x0(x0), _y0(y0), _x1(x1), _y1(y1), _r0(r0), _r1(r1) { + _grad = cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1); +} diff --git a/src/gradient.h b/src/gradient.h index 48a08a3..8a79015 100644 --- a/src/gradient.h +++ b/src/gradient.h @@ -16,13 +16,12 @@ class Gradient: public node::ObjectWrap { public: static void Initialize(Handle target); static Handle New(const Arguments &args); - Gradient(double x0, double y0, double x1, double y1): - _x0(x0), _y0(y0), _x1(x1), _y1(y1) {}; - Gradient(double x0, double y0, double r0, double x1, double y1, double r1): - _x0(x0), _y0(y0), _x1(x1), _y1(y1), _r0(r0), _r1(r1) {}; + Gradient(double x0, double y0, double x1, double y1); + Gradient(double x0, double y0, double r0, double x1, double y1, double r1); private: double _x0, _y0, _x1, _y1, _r0, _r1; + cairo_pattern_t *_grad; }; #endif \ No newline at end of file From 6ecdcec101af9aa56afee69da99eb1686ee67dfb Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:27:33 -0700 Subject: [PATCH 05/12] Added Gradient#AddColorStopRGBA() --- src/canvas.h | 18 ++++++++++++++++++ src/context2d.cc | 22 ++-------------------- src/gradient.cc | 16 ++++++++++++++-- src/gradient.h | 4 +++- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/canvas.h b/src/canvas.h index 104080e..f359be5 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -13,6 +13,24 @@ #include #include +/* + * RGBA arg assertions. + */ + +#define RGBA_ARGS(N) \ + if (!args[N]->IsNumber()) \ + return ThrowException(Exception::TypeError(String::New("r required"))); \ + if (!args[N+1]->IsNumber()) \ + return ThrowException(Exception::TypeError(String::New("g required"))); \ + if (!args[N+2]->IsNumber()) \ + return ThrowException(Exception::TypeError(String::New("b required"))); \ + if (!args[N+3]->IsNumber()) \ + return ThrowException(Exception::TypeError(String::New("alpha required"))); \ + float r = args[N]->Int32Value(); \ + float g = args[N+1]->Int32Value(); \ + float b = args[N+2]->Int32Value(); \ + float a = args[N+3]->NumberValue(); + using namespace v8; class Canvas: public node::ObjectWrap { diff --git a/src/context2d.cc b/src/context2d.cc index c318918..45b0bb0 100644 --- a/src/context2d.cc +++ b/src/context2d.cc @@ -48,24 +48,6 @@ using namespace node; int width = args[2]->Int32Value(); \ int height = args[3]->Int32Value(); -/* - * RGBA arg assertions. - */ - -#define RGBA_ARGS \ - if (!args[0]->IsNumber()) \ - return ThrowException(Exception::TypeError(String::New("r required"))); \ - if (!args[1]->IsNumber()) \ - return ThrowException(Exception::TypeError(String::New("g required"))); \ - if (!args[2]->IsNumber()) \ - return ThrowException(Exception::TypeError(String::New("b required"))); \ - if (!args[3]->IsNumber()) \ - return ThrowException(Exception::TypeError(String::New("alpha required"))); \ - float r = args[0]->Int32Value(); \ - float g = args[1]->Int32Value(); \ - float b = args[2]->Int32Value(); \ - float a = args[3]->NumberValue(); - /* * Initialize Context2d. */ @@ -344,7 +326,7 @@ Context2d::SetLineCap(Local prop, Local val, const AccessorInfo & Handle Context2d::SetFillRGBA(const Arguments &args) { HandleScope scope; - RGBA_ARGS; + RGBA_ARGS(0); Context2d *context = ObjectWrap::Unwrap(args.This()); RGBA(context->fill,r,g,b,a); return Undefined(); @@ -357,7 +339,7 @@ Context2d::SetFillRGBA(const Arguments &args) { Handle Context2d::SetStrokeRGBA(const Arguments &args) { HandleScope scope; - RGBA_ARGS; + RGBA_ARGS(0); Context2d *context = ObjectWrap::Unwrap(args.This()); RGBA(context->stroke,r,g,b,a); return Undefined(); diff --git a/src/gradient.cc b/src/gradient.cc index a2cff54..645f73e 100644 --- a/src/gradient.cc +++ b/src/gradient.cc @@ -15,6 +15,7 @@ Gradient::Initialize(Handle target) { t->InstanceTemplate()->SetInternalFieldCount(1); t->SetClassName(String::NewSymbol("CanvasGradient")); + NODE_SET_PROTOTYPE_METHOD(t, "addColorStopRGBA", AddColorStopRGBA); target->Set(String::NewSymbol("CanvasGradient"), t->GetFunction()); } @@ -49,12 +50,23 @@ Gradient::New(const Arguments &args) { return ThrowException(Exception::TypeError(String::New("invalid arguments"))); } +Handle +Gradient::AddColorStopRGBA(const Arguments &args) { + HandleScope scope; + if (!args[0]->IsNumber()) \ + return ThrowException(Exception::TypeError(String::New("offset required"))); \ + RGBA_ARGS(1); + Gradient *grad = ObjectWrap::Unwrap(args.This()); + cairo_pattern_add_color_stop_rgba(grad->getPattern(), args[0]->NumberValue(), r, g, b, a); + return Undefined(); +} + Gradient::Gradient(double x0, double y0, double x1, double y1): _x0(x0), _y0(y0), _x1(x1), _y1(y1) { - _grad = cairo_pattern_create_linear(x0, y0, x1, y1); + _pattern = cairo_pattern_create_linear(x0, y0, x1, y1); } Gradient::Gradient(double x0, double y0, double r0, double x1, double y1, double r1): _x0(x0), _y0(y0), _x1(x1), _y1(y1), _r0(r0), _r1(r1) { - _grad = cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1); + _pattern = cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1); } diff --git a/src/gradient.h b/src/gradient.h index 8a79015..097d779 100644 --- a/src/gradient.h +++ b/src/gradient.h @@ -16,12 +16,14 @@ class Gradient: public node::ObjectWrap { public: static void Initialize(Handle target); static Handle New(const Arguments &args); + static Handle AddColorStopRGBA(const Arguments &args); Gradient(double x0, double y0, double x1, double y1); Gradient(double x0, double y0, double r0, double x1, double y1, double r1); + inline cairo_pattern_t *getPattern(){ return _pattern; } private: double _x0, _y0, _x1, _y1, _r0, _r1; - cairo_pattern_t *_grad; + cairo_pattern_t *_pattern; }; #endif \ No newline at end of file From b09542c639dce780b7f18dafa674388771c684fc Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:29:04 -0700 Subject: [PATCH 06/12] Added CanvasGradient#addColorStop() --- lib/canvas.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/canvas.js b/lib/canvas.js index 86b7843..26b3990 100644 --- a/lib/canvas.js +++ b/lib/canvas.js @@ -119,6 +119,16 @@ Canvas.prototype.getContext = function(contextId){ } }; +CanvasGradient.prototype.addColorStop = function(offset, color){ + var rgba = exports.parseColor(color) || [0,0,0,1]; + this.addColorStopRGBA( + offset + , rgba[0] + , rgba[1] + , rgba[2] + , rgba[3]); +}; + Context2d.prototype.createLinearGradient = function(x0, y0, x1, y1){ return new CanvasGradient(x0, y0, x1, y1); }; From 1ec3e5d603f093690a11b5a2dafec44cce0ca081 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:29:44 -0700 Subject: [PATCH 07/12] Misc refactoring --- src/gradient.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gradient.cc b/src/gradient.cc index 645f73e..af2e63b 100644 --- a/src/gradient.cc +++ b/src/gradient.cc @@ -57,7 +57,10 @@ Gradient::AddColorStopRGBA(const Arguments &args) { return ThrowException(Exception::TypeError(String::New("offset required"))); \ RGBA_ARGS(1); Gradient *grad = ObjectWrap::Unwrap(args.This()); - cairo_pattern_add_color_stop_rgba(grad->getPattern(), args[0]->NumberValue(), r, g, b, a); + cairo_pattern_add_color_stop_rgba( + grad->getPattern() + , args[0]->NumberValue() + , r, g, b, a); return Undefined(); } From 8e219b468a4908d880541dc3eb1495edb5fc98ef Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 13:43:24 -0700 Subject: [PATCH 08/12] Prepping fillStyle for grads --- lib/canvas.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/canvas.js b/lib/canvas.js index 26b3990..3502a64 100644 --- a/lib/canvas.js +++ b/lib/canvas.js @@ -145,13 +145,17 @@ Context2d.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ */ Context2d.prototype.__defineSetter__('fillStyle', function(val){ - var rgba = exports.parseColor(val) || [0,0,0,1]; - this.lastFillStyle = rgba; - this.setFillRGBA( - rgba[0] - , rgba[1] - , rgba[2] - , rgba[3]); + if (val instanceof CanvasGradient) { + return this.setSource(val); + } else if ('string' == typeof val) { + var rgba = exports.parseColor(val) || [0,0,0,1]; + this.lastFillStyle = rgba; + this.setFillRGBA( + rgba[0] + , rgba[1] + , rgba[2] + , rgba[3]); + } }); /** From 97b67300528c727ce33260c390588864faf2452e Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 14:26:57 -0700 Subject: [PATCH 09/12] Added Context2d::SetSource() --- src/context2d.cc | 20 ++++++++++++++++++-- src/context2d.h | 1 + src/gradient.cc | 5 ++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/context2d.cc b/src/context2d.cc index 45b0bb0..979a07b 100644 --- a/src/context2d.cc +++ b/src/context2d.cc @@ -5,10 +5,11 @@ // Copyright (c) 2010 LearnBoost // -#include "canvas.h" -#include "context2d.h" #include #include +#include "canvas.h" +#include "context2d.h" +#include "gradient.h" using namespace v8; using namespace node; @@ -80,6 +81,7 @@ 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); proto->SetAccessor(String::NewSymbol("globalCompositeOperation"), GetGlobalCompositeOperation, SetGlobalCompositeOperation); @@ -319,6 +321,20 @@ Context2d::SetLineCap(Local prop, Local val, const AccessorInfo & } } +/* + * Set source pattern, used internally for fillStyle= + */ + +Handle +Context2d::SetSource(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()); + return Undefined(); +} + /* * Set fill RGBA, used internally for fillStyle= */ diff --git a/src/context2d.h b/src/context2d.h index e5fc5f9..dc9fcf2 100644 --- a/src/context2d.h +++ b/src/context2d.h @@ -31,6 +31,7 @@ class Context2d: public node::ObjectWrap { static Handle ClosePath(const Arguments &args); static Handle Fill(const Arguments &args); static Handle Stroke(const Arguments &args); + static Handle SetSource(const Arguments &args); static Handle SetFillRGBA(const Arguments &args); static Handle SetStrokeRGBA(const Arguments &args); static Handle BezierCurveTo(const Arguments &args); diff --git a/src/gradient.cc b/src/gradient.cc index af2e63b..8423694 100644 --- a/src/gradient.cc +++ b/src/gradient.cc @@ -60,7 +60,10 @@ Gradient::AddColorStopRGBA(const Arguments &args) { cairo_pattern_add_color_stop_rgba( grad->getPattern() , args[0]->NumberValue() - , r, g, b, a); + , r / 255 * 1 + , g / 255 * 1 + , b / 255 * 1 + , a); return Undefined(); } From d6d4c7b13453284325b86341b481d6d6c1f46d2a Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 14:50:00 -0700 Subject: [PATCH 10/12] Fixed gradients --- lib/canvas.js | 20 ++++++++++++-------- src/context2d.cc | 39 ++++++++++++++++++++++++++++++--------- src/context2d.h | 5 +++++ 3 files changed, 47 insertions(+), 17 deletions(-) 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); From a34a5524334bfbb7e57c185cb8dce8c22c3b47aa Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 14:52:02 -0700 Subject: [PATCH 11/12] Added gradients example --- examples/gradients.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 examples/gradients.js diff --git a/examples/gradients.js b/examples/gradients.js new file mode 100644 index 0000000..3bbb880 --- /dev/null +++ b/examples/gradients.js @@ -0,0 +1,29 @@ + +/** + * Module dependencies. + */ + +var Canvas = require('../lib/canvas') + , canvas = new Canvas(320, 320) + , ctx = canvas.getContext('2d'); + +// Create gradients +var lingrad = ctx.createLinearGradient(0,0,0,150); +lingrad.addColorStop(0, '#00ABEB'); +lingrad.addColorStop(0.5, '#fff'); +lingrad.addColorStop(0.5, '#26C000'); +lingrad.addColorStop(1, '#fff'); + +var lingrad2 = ctx.createLinearGradient(0,50,0,95); +lingrad2.addColorStop(0.5, '#000'); +lingrad2.addColorStop(1, 'rgba(0,0,0,0)'); + +// assign gradients to fill and stroke styles +ctx.fillStyle = lingrad; +ctx.strokeStyle = lingrad2; + +// draw shapes +ctx.fillRect(10,10,130,130); +ctx.strokeRect(50,50,50,50); + +canvas.savePNG(__dirname + '/gradients.png'); \ No newline at end of file From 4183ab3d3999b3b7bcd24745ef12cffb77f2c637 Mon Sep 17 00:00:00 2001 From: Tj Holowaychuk Date: Thu, 30 Sep 2010 14:52:12 -0700 Subject: [PATCH 12/12] Todo --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index bb852b7..d1294a6 100644 --- a/Readme.md +++ b/Readme.md @@ -14,9 +14,9 @@ [x] list of valid css colors [x] match canvas defaults (mostly, test suite from webkit would be nice) [x] transformations + [x] gradients [ ] make sure constructor names match [ ] anti aliasing - [ ] gradients [ ] Image [ ] patterns [ ] text