summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/win32/cairo-dwrite-font.cpp152
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(&copyArea, &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
}