diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/win32/cairo-dwrite-font.cpp | 152 |
1 files changed, 37 insertions, 115 deletions
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index edd606abe..438bfb15d 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -891,7 +891,6 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s { int width, height; double x1, y1, x2, y2; - cairo_glyph_t glyph; cairo_bool_t uses_foreground_color = FALSE; cairo_dwrite_font_face_t *dwrite_font_face = (cairo_dwrite_font_face_t *)scaled_font->base.font_face; @@ -908,16 +907,12 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s width = (int)(x2 - x1); height = (int)(y2 - y1); - glyph.index = _cairo_scaled_glyph_index (scaled_glyph); - glyph.x = x1; - glyph.y = y1; - DWRITE_GLYPH_RUN run; FLOAT advance = 0; - UINT16 index = (UINT16)glyph.index; + UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); DWRITE_GLYPH_OFFSET offset; - double x = -glyph.x; - double y = -glyph.y; + double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); DWRITE_MATRIX matrix; D2D1_POINT_2F origin = {0, 0}; RefPtr<IDWriteColorGlyphRunEnumerator1> run_enumerator; @@ -1131,7 +1126,6 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status; - cairo_glyph_t glyph; cairo_win32_surface_t *surface; cairo_t *cr; cairo_surface_t *image; @@ -1145,16 +1139,12 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ width = (int)(x2 - x1); height = (int)(y2 - y1); - glyph.index = _cairo_scaled_glyph_index (scaled_glyph); - glyph.x = -x1; - glyph.y = -y1; - DWRITE_GLYPH_RUN run; FLOAT advance = 0; - UINT16 index = (UINT16)glyph.index; + UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); DWRITE_GLYPH_OFFSET offset; - double x = glyph.x; - double y = glyph.y; + double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); RECT area; DWRITE_MATRIX matrix; @@ -1545,8 +1535,15 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, */ rt->SetPixelsPerDip(1.0); + float x = 0, y = 0; if (transform) { - rt->SetCurrentTransform(transform); + DWRITE_MATRIX matrix = *transform; + matrix.dx -= area.left; + matrix.dy -= area.top; + rt->SetCurrentTransform(&matrix); + } else { + x = (float) -area.left; + y = (float) -area.top; } BitBlt(rt->GetMemoryDC(), 0, 0, @@ -1554,7 +1551,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, surface->dc, area.left, area.top, SRCCOPY | NOMIRRORBITMAP); - rt->DrawGlyphRun(0, 0, scaled_font->measuring_mode, run, params, color); + rt->DrawGlyphRun(x, y, scaled_font->measuring_mode, run, params, color); BitBlt(surface->dc, area.left, area.top, area.right - area.left, area.bottom - area.top, @@ -1590,6 +1587,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface, if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; + float x = 0, y = 0; if (transform) { rt->SetTransform(D2D1::Matrix3x2F(transform->m11, transform->m12, @@ -1661,96 +1659,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets); BOOL transform = FALSE; - /* Needed to calculate bounding box for efficient blitting */ - INT32 smallestX = INT_MAX; - INT32 largestX = 0; - INT32 smallestY = INT_MAX; - INT32 largestY = 0; - for (int i = 0; i < num_glyphs; i++) { - if (glyphs[i].x < smallestX) { - smallestX = (INT32)glyphs[i].x; - } - if (glyphs[i].x > largestX) { - largestX = (INT32)glyphs[i].x; - } - if (glyphs[i].y < smallestY) { - smallestY = (INT32)glyphs[i].y; - } - if (glyphs[i].y > largestY) { - largestY = (INT32)glyphs[i].y; - } - } - /* - * Here we try to get a rough estimate of the area that this glyph run will - * cover on the surface. Since we use GDI interop to draw we will be copying - * data around the size of the area of the surface that we map. We will want - * to map an area as small as possible to prevent large surfaces to be - * copied around. We take the X/Y-size of the font as margin on the left/top - * twice the X/Y-size of the font as margin on the right/bottom. - * This should always cover the entire area where the glyphs are. - */ - RECT fontArea; - fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx); - fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2); - fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy); - fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2); - if (fontArea.left < 0) - fontArea.left = 0; - if (fontArea.top < 0) - fontArea.top = 0; - if (fontArea.bottom > dst->extents.height) { - fontArea.bottom = dst->extents.height; - } - if (fontArea.right > dst->extents.width) { - fontArea.right = dst->extents.width; - } - if (fontArea.right <= fontArea.left || - fontArea.bottom <= fontArea.top) { - return CAIRO_INT_STATUS_SUCCESS; - } - if (fontArea.right > dst->extents.width) { - fontArea.right = dst->extents.width; - } - if (fontArea.bottom > dst->extents.height) { - fontArea.bottom = dst->extents.height; - } - - run.bidiLevel = 0; - run.fontFace = dwriteff->dwriteface; - run.isSideways = FALSE; - if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 && - dwritesf->mat.xx == scaled_font->font_matrix.xx && - dwritesf->mat.yy == scaled_font->font_matrix.yy) { - - for (int i = 0; i < num_glyphs; i++) { - indices[i] = (WORD) glyphs[i].index; - // Since we will multiply by our ctm matrix later for rotation effects - // and such, adjust positions by the inverse matrix now. - offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y); - offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left); - advances[i] = 0.0; - } - run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy; - } else { - transform = TRUE; - // See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs - const double EPSILON = 0.0001; - for (int i = 0; i < num_glyphs; i++) { - indices[i] = (WORD) glyphs[i].index; - double x = glyphs[i].x - fontArea.left + EPSILON; - double y = glyphs[i].y - fontArea.top; - cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y); - /* - * Since we will multiply by our ctm matrix later for rotation effects - * and such, adjust positions by the inverse matrix now. The Y-axis - * is inverted so the offset becomes negative. - */ - offsets[i].ascenderOffset = -(FLOAT)y; - offsets[i].advanceOffset = (FLOAT)x; - advances[i] = 0.0; - } - run.fontEmSize = 1.0f; - } + _cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform); cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source; COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8, @@ -1766,18 +1675,31 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, mat = NULL; } - RECT area; - area.left = dst->extents.x; - area.top = dst->extents.y; - area.right = area.left + dst->extents.width; - area.bottom = area.top + dst->extents.height; + RefPtr<IDWriteGlyphRunAnalysis> runAnalysis; + HRESULT hr = DWriteFactory::Instance()-> + CreateGlyphRunAnalysis(&run, 1, mat, + DWRITE_RENDERING_MODE_ALIASED, + dwritesf->measuring_mode, + 0, // baselineOriginX, + 0, // baselineOriginY, + &runAnalysis); + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + RECT fontArea; + hr = runAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1, &fontArea); + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + InflateRect(&fontArea, 1, 1); + /* Needed to calculate bounding box for efficient blitting */ + RECT copyArea, dstArea = { 0, 0, dst->extents.width, dst->extents.height }; + IntersectRect(©Area, &fontArea, &dstArea); #ifdef CAIRO_TRY_D2D_TO_GDI status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst, mat, &run, color, - fontArea); + copyArea); if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) { #endif @@ -1786,7 +1708,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, &run, color, dwritesf, - fontArea); + copyArea); #ifdef CAIRO_TRY_D2D_TO_GDI } |