From 9963f71796fd9bd115050bcaf55a189797ecbb07 Mon Sep 17 00:00:00 2001 From: atomizer Date: Tue, 19 Apr 2011 23:39:52 +0400 Subject: [PATCH 1/7] restorePath(): clear current path before appending Signed-off-by: Tj Holowaychuk --- src/CanvasRenderingContext2d.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index ec62a75..17cf9d4 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -203,6 +203,7 @@ Context2d::savePath() { void Context2d::restorePath() { + cairo_new_path(_context); cairo_append_path(_context, _path); } From 5ae1c4607014733a9df71d065ab5bda36f0fd443 Mon Sep 17 00:00:00 2001 From: atomizer Date: Tue, 19 Apr 2011 23:50:28 +0400 Subject: [PATCH 2/7] preserve current path during fillRect() and strokeRect() Signed-off-by: Tj Holowaychuk --- src/CanvasRenderingContext2d.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 17cf9d4..15cfdd5 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -1640,9 +1640,10 @@ Context2d::FillRect(const Arguments &args) { if (0 == width || 0 == height) return Undefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); - cairo_new_path(ctx); + context->savePath(); cairo_rectangle(ctx, x, y, width, height); context->fill(); + context->restorePath(); return Undefined(); } @@ -1657,9 +1658,10 @@ Context2d::StrokeRect(const Arguments &args) { if (0 == width && 0 == height) return Undefined(); Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); - cairo_new_path(ctx); + context->savePath(); cairo_rectangle(ctx, x, y, width, height); context->stroke(); + context->restorePath(); return Undefined(); } From c8b82ae4ea2d0b77db230d72600f776fdf854e80 Mon Sep 17 00:00:00 2001 From: atomizer Date: Wed, 20 Apr 2011 00:34:28 +0400 Subject: [PATCH 3/7] ... and clearRect() Signed-off-by: Tj Holowaychuk --- src/CanvasRenderingContext2d.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 15cfdd5..165e9d5 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -1677,9 +1677,11 @@ Context2d::ClearRect(const Arguments &args) { Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->context(); cairo_save(ctx); + context->savePath(); cairo_rectangle(ctx, x, y, width, height); cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR); cairo_fill(ctx); + context->restorePath(); cairo_restore(ctx); return Undefined(); } From cd3e9027d913635eda90b56d2b67dc582ac08aa6 Mon Sep 17 00:00:00 2001 From: atomizer Date: Wed, 20 Apr 2011 01:54:36 +0400 Subject: [PATCH 4/7] visual test Signed-off-by: Tj Holowaychuk --- test/public/tests.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/public/tests.js b/test/public/tests.js index 9fd8342..0300b85 100644 --- a/test/public/tests.js +++ b/test/public/tests.js @@ -601,6 +601,33 @@ tests['states with stroke/fill/globalAlpha'] = function(ctx){ ctx.fillRect(60,60,30,30); }; +tests['path through fillRect/strokeRect/clearRect'] = function(ctx){ + // left: fillRect() + ctx.beginPath(); + ctx.rect(0, 50, 50, 50); + ctx.fillStyle = '#F00'; + ctx.fillRect(10, 60, 30, 30); + ctx.fillStyle = '#0F0'; + ctx.fill(); + + // center: strokeRect() + ctx.beginPath(); + ctx.rect(50, 50, 50, 50); + ctx.strokeStyle = '#F00'; + ctx.lineWidth = 5; + ctx.strokeRect(60, 60, 30, 30); + ctx.fillStyle = '#0F0'; + ctx.fill(); + + // right: clearRect() + ctx.beginPath(); + ctx.rect(100, 50, 50, 50); + ctx.fillStyle = '#0F0'; + ctx.fill(); + ctx.clearRect(110, 60, 30, 30); + ctx.fill(); +} + tests['invalid stroke/fill styles'] = function(ctx){ ctx.fillStyle = 'red'; ctx.strokeStyle = 'yellow'; From 11c5d3d45eda1fe7340a1dc2ea02ddaae61265c0 Mon Sep 17 00:00:00 2001 From: atomizer Date: Wed, 20 Apr 2011 02:25:27 +0400 Subject: [PATCH 5/7] do not clamp arguments to integer values Signed-off-by: Tj Holowaychuk --- src/CanvasRenderingContext2d.cc | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 165e9d5..ab1000a 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -26,10 +26,10 @@ Persistent Context2d::constructor; ||!args[1]->IsNumber() \ ||!args[2]->IsNumber() \ ||!args[3]->IsNumber()) return Undefined(); \ - double x = args[0]->Int32Value(); \ - double y = args[1]->Int32Value(); \ - double width = args[2]->Int32Value(); \ - double height = args[3]->Int32Value(); + double x = args[0]->NumberValue(); \ + double y = args[1]->NumberValue(); \ + double width = args[2]->NumberValue(); \ + double height = args[3]->NumberValue(); /* * Text baselines. @@ -548,26 +548,26 @@ Context2d::DrawImage(const Arguments &args) { switch (args.Length()) { // img, sx, sy, sw, sh, dx, dy, dw, dh case 9: - sx = args[1]->Int32Value(); - sy = args[2]->Int32Value(); - sw = args[3]->Int32Value(); - sh = args[4]->Int32Value(); - dx = args[5]->Int32Value(); - dy = args[6]->Int32Value(); - dw = args[7]->Int32Value(); - dh = args[8]->Int32Value(); + sx = args[1]->NumberValue(); + sy = args[2]->NumberValue(); + sw = args[3]->NumberValue(); + sh = args[4]->NumberValue(); + dx = args[5]->NumberValue(); + dy = args[6]->NumberValue(); + dw = args[7]->NumberValue(); + dh = args[8]->NumberValue(); break; // img, dx, dy, dw, dh case 5: - dx = args[1]->Int32Value(); - dy = args[2]->Int32Value(); - dw = args[3]->Int32Value(); - dh = args[4]->Int32Value(); + dx = args[1]->NumberValue(); + dy = args[2]->NumberValue(); + dw = args[3]->NumberValue(); + dh = args[4]->NumberValue(); break; // img, dx, dy case 3: - dx = args[1]->Int32Value(); - dy = args[2]->Int32Value(); + dx = args[1]->NumberValue(); + dy = args[2]->NumberValue(); dw = sw; dh = sh; break; @@ -852,7 +852,7 @@ Context2d::GetShadowBlur(Local prop, const AccessorInfo &info) { void Context2d::SetShadowBlur(Local prop, Local val, const AccessorInfo &info) { - int n = val->Uint32Value(); + int n = val->NumberValue(); if (n >= 0) { Context2d *context = ObjectWrap::Unwrap(info.This()); context->state->shadowBlur = n; From 5ec0f947ca2f12ea68ee4a9e58c1a9ff21782781 Mon Sep 17 00:00:00 2001 From: atomizer Date: Wed, 20 Apr 2011 02:27:34 +0400 Subject: [PATCH 6/7] simple visual test Signed-off-by: Tj Holowaychuk --- test/public/tests.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/public/tests.js b/test/public/tests.js index 0300b85..6f9b112 100644 --- a/test/public/tests.js +++ b/test/public/tests.js @@ -490,6 +490,16 @@ tests['fill with stroke'] = function(ctx){ ctx.stroke(); }; +tests['floating point coordinates'] = function(ctx){ + ctx.lineCap = 'square'; + for (var i=0; i<70; i+=3.05) { + ctx.rect(i+3, 10.5, 0, 130); + ctx.moveTo(i+77, 10.5); + ctx.lineTo(i+77, 140.5); + } + ctx.stroke(); +} + tests['lineWidth'] = function(ctx){ for (var i = 0; i < 10; i++){ ctx.lineWidth = 1+i; From 24c327ac5ed0890b216d7cfca7e86a82313fd099 Mon Sep 17 00:00:00 2001 From: atomizer Date: Wed, 20 Apr 2011 02:47:36 +0400 Subject: [PATCH 7/7] special case of zero-width rectangle Signed-off-by: Tj Holowaychuk --- src/CanvasRenderingContext2d.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index ab1000a..9ec21a1 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -1695,7 +1695,16 @@ Context2d::Rect(const Arguments &args) { HandleScope scope; RECT_ARGS; Context2d *context = ObjectWrap::Unwrap(args.This()); - cairo_rectangle(context->context(), x, y, width, height); + cairo_t *ctx = context->context(); + if (width == 0) { + cairo_move_to(ctx, x, y); + cairo_line_to(ctx, x, y + height); + } else if (height == 0) { + cairo_move_to(ctx, x, y); + cairo_line_to(ctx, x + width, y); + } else { + cairo_rectangle(ctx, x, y, width, height); + } return Undefined(); }