diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 4404876..16b1995 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -54,10 +54,10 @@ using namespace node; ||!args[1]->IsNumber() \ ||!args[2]->IsNumber() \ ||!args[3]->IsNumber()) return Undefined(); \ - int x = args[0]->Int32Value(); \ - int y = args[1]->Int32Value(); \ - int width = args[2]->Int32Value(); \ - int height = args[3]->Int32Value(); + double x = args[0]->Int32Value(); \ + double y = args[1]->Int32Value(); \ + double width = args[2]->Int32Value(); \ + double height = args[3]->Int32Value(); /* * Text baselines. @@ -105,7 +105,6 @@ Context2d::Initialize(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "rect", Rect); NODE_SET_PROTOTYPE_METHOD(t, "setTextBaseline", SetTextBaseline); NODE_SET_PROTOTYPE_METHOD(t, "setTextAlignment", SetTextAlignment); - NODE_SET_PROTOTYPE_METHOD(t, "setTextPath", SetTextPath); NODE_SET_PROTOTYPE_METHOD(t, "measureText", MeasureText); NODE_SET_PROTOTYPE_METHOD(t, "moveTo", MoveTo); NODE_SET_PROTOTYPE_METHOD(t, "lineTo", LineTo); @@ -776,8 +775,18 @@ Context2d::Stroke(const Arguments &args) { Handle Context2d::FillText(const Arguments &args) { HandleScope scope; + + if (!args[0]->IsString() + || !args[1]->IsNumber() + || !args[2]->IsNumber()) return Undefined(); + + String::Utf8Value str(args[0]); + double x = args[1]->NumberValue(); + double y = args[2]->NumberValue(); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->getContext(); + context->setTextPath(*str, x, y); SET_SOURCE(context->state->fill); return Undefined(); } @@ -789,12 +798,59 @@ Context2d::FillText(const Arguments &args) { Handle Context2d::StrokeText(const Arguments &args) { HandleScope scope; + + if (!args[0]->IsString() + || !args[1]->IsNumber() + || !args[2]->IsNumber()) return Undefined(); + + String::Utf8Value str(args[0]); + double x = args[1]->NumberValue(); + double y = args[2]->NumberValue(); + Context2d *context = ObjectWrap::Unwrap(args.This()); cairo_t *ctx = context->getContext(); - SET_SOURCE(context->state->fill); + context->setTextPath(*str, x, y); + SET_SOURCE(context->state->stroke); return Undefined(); } +void +Context2d::setTextPath(const char *str, double x, double y) { + // Text extents + cairo_text_extents_t te; + cairo_text_extents(_context, str, &te); + + // Alignment + switch (state->textAlignment) { + // center + case 0: + x -= te.width / 2 + te.x_bearing; + break; + // right + case 1: + x -= te.width + te.x_bearing; + break; + } + + // Baseline approx + // TODO: + switch (state->textBaseline) { + case TEXT_BASELINE_TOP: + case TEXT_BASELINE_HANGING: + y += te.height; + break; + case TEXT_BASELINE_MIDDLE: + y += te.height / 2; + break; + case TEXT_BASELINE_BOTTOM: + y -= te.height / 2; + break; + } + + cairo_move_to(_context, x, y); + cairo_text_path(_context, str); +} + /* * Adds a point to the current subpath. */ @@ -939,64 +995,6 @@ Context2d::SetTextAlignment(const Arguments &args) { return Undefined(); } -/* - * Set text path at x, y. - */ - -Handle -Context2d::SetTextPath(const Arguments &args) { - HandleScope scope; - - // Ignore when args are not present - if (!args[0]->IsString() - || !args[1]->IsNumber() - || !args[2]->IsNumber()) return Undefined(); - - String::Utf8Value str(args[0]); - - double x = args[1]->NumberValue() - , y = args[2]->NumberValue(); - - Context2d *context = ObjectWrap::Unwrap(args.This()); - cairo_t *ctx = context->getContext(); - - // Text extents - cairo_text_extents_t te; - cairo_text_extents(ctx, *str, &te); - - // Alignment - switch (context->state->textAlignment) { - // center - case 0: - x -= te.width / 2 + te.x_bearing; - break; - // right - case 1: - x -= te.width + te.x_bearing; - break; - } - - // Baseline approx - // TODO: - switch (context->state->textBaseline) { - case TEXT_BASELINE_TOP: - case TEXT_BASELINE_HANGING: - y += te.height; - break; - case TEXT_BASELINE_MIDDLE: - y += te.height / 2; - break; - case TEXT_BASELINE_BOTTOM: - y -= te.height / 2; - break; - } - - cairo_move_to(ctx, x, y); - cairo_text_path(ctx, *str); - - return Undefined(); -} - /* * Fill the rectangle defined by x, y, width and height. */ diff --git a/src/CanvasRenderingContext2d.h b/src/CanvasRenderingContext2d.h index abec1ce..8c7fea7 100644 --- a/src/CanvasRenderingContext2d.h +++ b/src/CanvasRenderingContext2d.h @@ -70,7 +70,6 @@ class Context2d: public node::ObjectWrap { static Handle SetStrokePattern(const Arguments &args); static Handle SetTextBaseline(const Arguments &args); static Handle SetTextAlignment(const Arguments &args); - static Handle SetTextPath(const Arguments &args); static Handle MeasureText(const Arguments &args); static Handle BezierCurveTo(const Arguments &args); static Handle QuadraticCurveTo(const Arguments &args); @@ -101,6 +100,7 @@ class Context2d: public node::ObjectWrap { static void SetShadowBlur(Local prop, Local val, const AccessorInfo &info); inline cairo_t *getContext(){ return _context; } inline Canvas *getCanvas(){ return _canvas; } + void setTextPath(const char *str, double x, double y); void saveState(); void restoreState();