From 4e9269cc34b0895ac6d3f99aabba3d6288295d76 Mon Sep 17 00:00:00 2001 From: Hussein Jafferjee Date: Wed, 14 Oct 2015 15:22:09 -0700 Subject: [PATCH 1/4] implement blur on images (drawImage) --- src/CanvasRenderingContext2d.cc | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 5736ef4..8fc1056 100755 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -883,10 +883,29 @@ NAN_METHOD(Context2d::DrawImage) { } if (context->hasShadow()) { - context->setSourceRGBA(context->state->shadow); - cairo_mask_surface(ctx, surface, - dx - sx + context->state->shadowOffsetX, - dy - sy + context->state->shadowOffsetY); + if(context->state->shadowBlur) { + // we need to create a new surface in order to blur + int pad = context->state->shadowBlur * 2; + cairo_surface_t *shadow_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dw + 2 * pad, dh + 2 * pad); + cairo_t *shadow_context = cairo_create(shadow_surface); + + // mask and blur + context->setSourceRGBA(shadow_context, context->state->shadow); + cairo_mask_surface(shadow_context, surface, pad, pad); + context->blur(shadow_surface, context->state->shadowBlur / 2); + + // paint + // @todo figure out where the 1.15 comes from + cairo_set_source_surface(ctx, shadow_surface, + dx - sx + context->state->shadowOffsetX - pad + 1.15, + dx - sx + context->state->shadowOffsetY - pad + 1.15); + cairo_paint(ctx); + } else { + context->setSourceRGBA(context->state->shadow); + cairo_mask_surface(ctx, surface, + dx - sx + context->state->shadowOffsetX, + dy - sy + context->state->shadowOffsetY); + } } context->savePath(); From 4f722ffa53662f11f3184d23d71e6850acb37371 Mon Sep 17 00:00:00 2001 From: Hussein Jafferjee Date: Wed, 14 Oct 2015 15:46:12 -0700 Subject: [PATCH 2/4] forgot to destroy context and surface --- src/CanvasRenderingContext2d.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 8fc1056..72f6275 100755 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -900,6 +900,10 @@ NAN_METHOD(Context2d::DrawImage) { dx - sx + context->state->shadowOffsetX - pad + 1.15, dx - sx + context->state->shadowOffsetY - pad + 1.15); cairo_paint(ctx); + + // cleanup + cairo_destroy(shadow_context); + cairo_surface_destroy(shadow_surface); } else { context->setSourceRGBA(context->state->shadow); cairo_mask_surface(ctx, surface, From f8368996b84ad9579aae803e28ca3e327f172823 Mon Sep 17 00:00:00 2001 From: Hussein Jafferjee Date: Fri, 16 Oct 2015 09:53:54 -0700 Subject: [PATCH 3/4] Change to 1.4 to match chrome --- src/CanvasRenderingContext2d.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 72f6275..0463c66 100755 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -895,10 +895,10 @@ NAN_METHOD(Context2d::DrawImage) { context->blur(shadow_surface, context->state->shadowBlur / 2); // paint - // @todo figure out where the 1.15 comes from + // @todo figure out where the 1.4 comes from cairo_set_source_surface(ctx, shadow_surface, - dx - sx + context->state->shadowOffsetX - pad + 1.15, - dx - sx + context->state->shadowOffsetY - pad + 1.15); + dx - sx + context->state->shadowOffsetX - pad + 1.4, + dx - sx + context->state->shadowOffsetY - pad + 1.4); cairo_paint(ctx); // cleanup From 85aff9e5e492779dd944f4bbfef039bff4653151 Mon Sep 17 00:00:00 2001 From: Hussein Jafferjee Date: Mon, 19 Oct 2015 12:40:08 -0700 Subject: [PATCH 4/4] improve comment on why the offset is there --- src/CanvasRenderingContext2d.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 0463c66..263a799 100755 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -895,7 +895,10 @@ NAN_METHOD(Context2d::DrawImage) { context->blur(shadow_surface, context->state->shadowBlur / 2); // paint - // @todo figure out where the 1.4 comes from + // @note: ShadowBlur looks different in each browser. This implementation matches chrome as close as possible. + // The 1.4 offset comes from visual tests with Chrome. I have read the spec and part of the shadowBlur + // implementation, and its not immediately clear why an offset is necessary, but without it, the result + // in chrome is different. cairo_set_source_surface(ctx, shadow_surface, dx - sx + context->state->shadowOffsetX - pad + 1.4, dx - sx + context->state->shadowOffsetY - pad + 1.4);