From f950be3e282e62243f78f137577f79e836ed7db8 Mon Sep 17 00:00:00 2001 From: Caleb Hearon Date: Thu, 16 Nov 2017 14:27:14 -0500 Subject: [PATCH] use the PangoLayout to get baseline Instead of getting it via the PangoContext, which seems to be buggy Fixes #1037 --- src/CanvasRenderingContext2d.cc | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 9469d5c32..d7c496632 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -1945,19 +1945,23 @@ NAN_METHOD(Context2d::StrokeText) { } /* - * Gets the baseline adjustment in device pixels, taking into account the - * transformation matrix. TODO This does not handle skew (which cannot easily - * be extracted from the matrix separately from rotation). + * Gets the baseline adjustment in device pixels */ -inline double getBaselineAdjustment(PangoFontMetrics* metrics, cairo_matrix_t matrix, short baseline) { - double yScale = sqrt(matrix.yx * matrix.yx + matrix.yy * matrix.yy); +inline double getBaselineAdjustment(PangoLayout* layout, short baseline) { + PangoRectangle logical_rect; + pango_layout_line_get_extents(pango_layout_get_line(layout, 0), NULL, &logical_rect); + + double scale = 1.0 / PANGO_SCALE; + double ascent = scale * pango_layout_get_baseline(layout); + double descent = scale * logical_rect.height - ascent; + switch (baseline) { case TEXT_BASELINE_ALPHABETIC: - return (pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) * yScale; + return ascent; case TEXT_BASELINE_MIDDLE: - return ((pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics)) / (2.0 * PANGO_SCALE)) * yScale; + return (ascent + descent) / 2.0; case TEXT_BASELINE_BOTTOM: - return ((pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics)) / PANGO_SCALE) * yScale; + return ascent + descent; default: return 0; } @@ -1970,13 +1974,10 @@ inline double getBaselineAdjustment(PangoFontMetrics* metrics, cairo_matrix_t ma void Context2d::setTextPath(const char *str, double x, double y) { PangoRectangle logical_rect; - cairo_matrix_t matrix; pango_layout_set_text(_layout, str, -1); pango_cairo_update_layout(_context, _layout); - cairo_get_matrix(_context, &matrix); - switch (state->textAlignment) { // center case 0: @@ -1990,9 +1991,7 @@ Context2d::setTextPath(const char *str, double x, double y) { break; } - PangoFontMetrics *metrics = PANGO_LAYOUT_GET_METRICS(_layout); - y -= getBaselineAdjustment(metrics, matrix, state->textBaseline); - pango_font_metrics_unref(metrics); + y -= getBaselineAdjustment(_layout, state->textBaseline); cairo_move_to(_context, x, y); if (state->textDrawingMode == TEXT_DRAW_PATHS) { @@ -2132,7 +2131,7 @@ NAN_METHOD(Context2d::MeasureText) { cairo_matrix_t matrix; cairo_get_matrix(ctx, &matrix); - double y_offset = getBaselineAdjustment(metrics, matrix, context->state->textBaseline); + double y_offset = getBaselineAdjustment(layout, context->state->textBaseline); obj->Set(Nan::New("width").ToLocalChecked(), Nan::New(logical_rect.width));