diff options
author | Fujii Hironori <Hironori.Fujii@sony.com> | 2023-02-07 15:42:51 +0900 |
---|---|---|
committer | Fujii Hironori <Hironori.Fujii@sony.com> | 2023-02-08 05:41:07 +0900 |
commit | db4c941c34617c1a1ee0519387b94936491fa860 (patch) | |
tree | 01e1f9a00712125a31bbac3424082813ca3cb56a /src/win32 | |
parent | 23e2718bd72ad5cb43abb853ef46ac0a1427f121 (diff) | |
download | cairo-db4c941c34617c1a1ee0519387b94936491fa860.tar.gz |
DWrite: More accurate glyph paths for small fonts
Applying a transformation matrix to a glyph path after converting
floats to fixed point numbers caused caluculation errors. Apply the
transform before the conversion.
Fixes cairo/cairo#611
Diffstat (limited to 'src/win32')
-rw-r--r-- | src/win32/cairo-dwrite-font.cpp | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index 1d84fc047..8346e4856 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -736,8 +736,9 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ class GeometryRecorder : public IDWriteGeometrySink { public: - GeometryRecorder(cairo_path_fixed_t *aCairoPath) - : mCairoPath(aCairoPath) {} + GeometryRecorder(cairo_path_fixed_t *aCairoPath, const cairo_matrix_t &matrix) + : mCairoPath(aCairoPath) + , mMatrix(matrix) {} // IUnknown interface IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) @@ -779,10 +780,14 @@ public: D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) { - mStartPoint = startPoint; + double x = startPoint.x; + double y = startPoint.y; + cairo_matrix_transform_point(&mMatrix, &x, &y); + mStartPointX = _cairo_fixed_from_double(x); + mStartPointY = _cairo_fixed_from_double(y); cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath, - _cairo_fixed_from_double(startPoint.x), - _cairo_fixed_from_double(startPoint.y)); + mStartPointX, + mStartPointY); (void)status; /* squelch warning */ } @@ -791,8 +796,8 @@ public: { if (figureEnd == D2D1_FIGURE_END_CLOSED) { cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, - _cairo_fixed_from_double(mStartPoint.x), - _cairo_fixed_from_double(mStartPoint.y)); + mStartPointX, + mStartPointY); (void)status; /* squelch warning */ } } @@ -802,13 +807,22 @@ public: UINT beziersCount) { for (unsigned int i = 0; i < beziersCount; i++) { + double x1 = beziers[i].point1.x; + double y1 = beziers[i].point1.y; + double x2 = beziers[i].point2.x; + double y2 = beziers[i].point2.y; + double x3 = beziers[i].point3.x; + double y3 = beziers[i].point3.y; + cairo_matrix_transform_point(&mMatrix, &x1, &y1); + cairo_matrix_transform_point(&mMatrix, &x2, &y2); + cairo_matrix_transform_point(&mMatrix, &x3, &y3); cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath, - _cairo_fixed_from_double(beziers[i].point1.x), - _cairo_fixed_from_double(beziers[i].point1.y), - _cairo_fixed_from_double(beziers[i].point2.x), - _cairo_fixed_from_double(beziers[i].point2.y), - _cairo_fixed_from_double(beziers[i].point3.x), - _cairo_fixed_from_double(beziers[i].point3.y)); + _cairo_fixed_from_double(x1), + _cairo_fixed_from_double(y1), + _cairo_fixed_from_double(x2), + _cairo_fixed_from_double(y2), + _cairo_fixed_from_double(x3), + _cairo_fixed_from_double(y3)); (void)status; /* squelch warning */ } } @@ -818,16 +832,21 @@ public: UINT pointsCount) { for (unsigned int i = 0; i < pointsCount; i++) { + double x = points[i].x; + double y = points[i].y; + cairo_matrix_transform_point(&mMatrix, &x, &y); cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, - _cairo_fixed_from_double(points[i].x), - _cairo_fixed_from_double(points[i].y)); + _cairo_fixed_from_double(x), + _cairo_fixed_from_double(y)); (void)status; /* squelch warning */ } } private: cairo_path_fixed_t *mCairoPath; - D2D1_POINT_2F mStartPoint; + const cairo_matrix_t &mMatrix; + cairo_fixed_t mStartPointX; + cairo_fixed_t mStartPointY; }; static cairo_int_status_t @@ -837,7 +856,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon cairo_int_status_t status; cairo_path_fixed_t *path; path = _cairo_path_fixed_create(); - GeometryRecorder recorder(path); + GeometryRecorder recorder(path, scaled_font->base.scale); DWRITE_GLYPH_OFFSET offset; offset.advanceOffset = 0; @@ -846,12 +865,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon FLOAT advance = 0.0; cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face; - /* GetGlyphRunOutline seems to ignore hinting so just use the em size to get the outline - * to avoid rounding errors when converting to cairo_path_fixed_t. - */ - DWRITE_FONT_METRICS metrics; - dwriteff->dwriteface->GetMetrics(&metrics); - HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(metrics.designUnitsPerEm, + HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1, &glyphId, &advance, &offset, @@ -864,12 +878,6 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon status = (cairo_int_status_t)_cairo_path_fixed_close_path(path); - /* Now scale the em size down to 1.0 and apply the font matrix and font ctm. */ - cairo_matrix_t mat = scaled_font->base.ctm; - cairo_matrix_multiply(&mat, &scaled_font->base.font_matrix, &mat); - cairo_matrix_scale (&mat, 1.0/metrics.designUnitsPerEm, 1.0/metrics.designUnitsPerEm); - _cairo_path_fixed_transform(path, &mat); - _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path); |