[PATCH 1/4] dwrite: Use transformed glyph origins in glyph run analysis
Nikolay Sivov
nsivov at codeweavers.com
Tue Apr 4 05:13:17 CDT 2017
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/dwrite/font.c | 207 +++++++++++++++++------------------------------------
1 file changed, 64 insertions(+), 143 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 4e35ceab2e..27f5040252 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -172,10 +172,7 @@ struct dwrite_glyphrunanalysis {
DWRITE_MATRIX m;
FLOAT ppdip;
UINT16 *glyphs;
- D2D_POINT_2F origin;
- D2D_POINT_2F *advances;
- D2D_POINT_2F *advanceoffsets;
- D2D_POINT_2F *ascenderoffsets;
+ D2D_POINT_2F *origins;
UINT8 flags;
RECT bounds;
@@ -4775,9 +4772,7 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
if (This->run.fontFace)
IDWriteFontFace_Release(This->run.fontFace);
heap_free(This->glyphs);
- heap_free(This->advances);
- heap_free(This->advanceoffsets);
- heap_free(This->ascenderoffsets);
+ heap_free(This->origins);
heap_free(This->bitmap);
heap_free(This);
}
@@ -4807,9 +4802,7 @@ static UINT32 get_glyph_bitmap_pitch(DWRITE_TEXTURE_TYPE type, INT width)
static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *analysis, RECT *bounds)
{
struct dwrite_glyphbitmap glyph_bitmap;
- IDWriteFontFace4 *fontface3;
- D2D_POINT_2F origin;
- BOOL is_rtl;
+ IDWriteFontFace4 *fontface;
HRESULT hr;
UINT32 i;
@@ -4821,27 +4814,18 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
if (analysis->run.isSideways)
FIXME("sideways runs are not supported.\n");
- hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace4, (void**)&fontface3);
+ hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace4, (void **)&fontface);
if (FAILED(hr))
WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr);
- /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
- RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
- for any non-zero glyph ascender */
- origin.x = origin.y = 0.0f;
- is_rtl = analysis->run.bidiLevel & 1;
-
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
- glyph_bitmap.fontface = fontface3;
+ glyph_bitmap.fontface = fontface;
glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip;
glyph_bitmap.nohint = is_natural_rendering_mode(analysis->rendering_mode);
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
glyph_bitmap.m = &analysis->m;
for (i = 0; i < analysis->run.glyphCount; i++) {
- const D2D_POINT_2F *advanceoffset = analysis->advanceoffsets ? analysis->advanceoffsets + i : NULL;
- const D2D_POINT_2F *ascenderoffset = analysis->ascenderoffsets ? analysis->ascenderoffsets + i : NULL;
- const D2D_POINT_2F *advance = analysis->advances + i;
RECT *bbox = &glyph_bitmap.bbox;
UINT32 bitmap_size;
@@ -4853,25 +4837,11 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
if (bitmap_size > analysis->max_glyph_bitmap_size)
analysis->max_glyph_bitmap_size = bitmap_size;
- if (is_rtl)
- OffsetRect(bbox, origin.x + advance->x, origin.y + advance->y);
- else
- OffsetRect(bbox, origin.x, origin.y);
-
- if (advanceoffset)
- OffsetRect(bbox, advanceoffset->x + ascenderoffset->x, advanceoffset->y + ascenderoffset->y);
-
+ OffsetRect(bbox, analysis->origins[i].x, analysis->origins[i].y);
UnionRect(&analysis->bounds, &analysis->bounds, bbox);
- origin.x += advance->x;
- origin.y += advance->y;
}
- IDWriteFontFace4_Release(fontface3);
-
- /* translate to given run origin */
- OffsetRect(&analysis->bounds, analysis->origin.x, analysis->origin.y);
- if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
- OffsetRect(&analysis->bounds, analysis->m.dx, analysis->m.dy);
+ IDWriteFontFace4_Release(fontface);
analysis->flags |= RUNANALYSIS_BOUNDS_READY;
*bounds = analysis->bounds;
@@ -4919,7 +4889,6 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
IDWriteFontFace4 *fontface;
D2D_POINT_2F origin;
UINT32 i, size;
- BOOL is_rtl;
HRESULT hr;
RECT *bbox;
@@ -4940,7 +4909,6 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
}
origin.x = origin.y = 0.0f;
- is_rtl = analysis->run.bidiLevel & 1;
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
glyph_bitmap.fontface = fontface;
@@ -4957,9 +4925,6 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
bbox = &glyph_bitmap.bbox;
for (i = 0; i < analysis->run.glyphCount; i++) {
- const D2D_POINT_2F *advanceoffset = analysis->advanceoffsets ? analysis->advanceoffsets + i : NULL;
- const D2D_POINT_2F *ascenderoffset = analysis->ascenderoffsets ? analysis->ascenderoffsets + i : NULL;
- const D2D_POINT_2F *advance = analysis->advances + i;
BYTE *src = glyph_bitmap.buf, *dst;
int x, y, width, height;
BOOL is_1bpp;
@@ -4967,11 +4932,8 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
glyph_bitmap.index = analysis->run.glyphIndices[i];
freetype_get_glyph_bbox(&glyph_bitmap);
- if (IsRectEmpty(bbox)) {
- origin.x += advance->x;
- origin.y += advance->y;
+ if (IsRectEmpty(bbox))
continue;
- }
width = bbox->right - bbox->left;
height = bbox->bottom - bbox->top;
@@ -4980,17 +4942,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
memset(src, 0, height * glyph_bitmap.pitch);
is_1bpp = freetype_get_glyph_bitmap(&glyph_bitmap);
- if (is_rtl)
- OffsetRect(bbox, origin.x + advance->x, origin.y + advance->y);
- else
- OffsetRect(bbox, origin.x, origin.y);
-
- if (advanceoffset)
- OffsetRect(bbox, advanceoffset->x + ascenderoffset->x, advanceoffset->y + ascenderoffset->y);
-
- OffsetRect(bbox, analysis->origin.x, analysis->origin.y);
- if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
- OffsetRect(bbox, analysis->m.dx, analysis->m.dy);
+ OffsetRect(bbox, analysis->origins[i].x, analysis->origins[i].y);
/* blit to analysis bitmap */
dst = get_pixel_ptr(analysis->bitmap, analysis->texture_type, bbox, &analysis->bounds);
@@ -5025,9 +4977,6 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
dst += (analysis->bounds.right - analysis->bounds.left) * 3;
}
}
-
- origin.x += advance->x;
- origin.y += advance->y;
}
heap_free(glyph_bitmap.buf);
@@ -5037,15 +4986,11 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
/* we don't need this anymore */
heap_free(analysis->glyphs);
- heap_free(analysis->advances);
- heap_free(analysis->advanceoffsets);
- heap_free(analysis->ascenderoffsets);
+ heap_free(analysis->origins);
IDWriteFontFace_Release(analysis->run.fontFace);
analysis->glyphs = NULL;
- analysis->advances = NULL;
- analysis->advanceoffsets = NULL;
- analysis->ascenderoffsets = NULL;
+ analysis->origins = NULL;
analysis->run.glyphIndices = NULL;
analysis->run.fontFace = NULL;
@@ -5154,29 +5099,20 @@ static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl = {
glyphrunanalysis_GetAlphaBlendParams
};
-static inline void init_2d_vec(D2D_POINT_2F *vec, FLOAT length, BOOL is_vertical)
-{
- if (is_vertical) {
- vec->x = 0.0f;
- vec->y = length;
- }
- else {
- vec->x = length;
- vec->y = 0.0f;
- }
-}
-
-static inline void transform_2d_vec(D2D_POINT_2F *vec, const DWRITE_MATRIX *m)
+static inline void transform_point(D2D_POINT_2F *point, const DWRITE_MATRIX *m)
{
D2D_POINT_2F ret;
- ret.x = vec->x * m->m11 + vec->y * m->m21;
- ret.y = vec->x * m->m12 + vec->y * m->m22;
- *vec = ret;
+ ret.x = point->x * m->m11 + point->y * m->m21 + m->dx;
+ ret.y = point->x * m->m12 + point->y * m->m22 + m->dy;
+ *point = ret;
}
HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc *desc, IDWriteGlyphRunAnalysis **ret)
{
struct dwrite_glyphrunanalysis *analysis;
+ DWRITE_FONT_METRICS metrics;
+ IDWriteFontFace1 *fontface1;
+ D2D_POINT_2F origin;
FLOAT rtl_factor;
UINT32 i;
@@ -5205,32 +5141,18 @@ HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc *desc, IDWrit
analysis->bitmap = NULL;
analysis->max_glyph_bitmap_size = 0;
analysis->ppdip = desc->ppdip;
- analysis->origin.x = desc->origin_x * desc->ppdip;
- analysis->origin.y = desc->origin_y * desc->ppdip;
SetRectEmpty(&analysis->bounds);
analysis->run = *desc->run;
IDWriteFontFace_AddRef(analysis->run.fontFace);
- analysis->glyphs = heap_alloc(desc->run->glyphCount*sizeof(*desc->run->glyphIndices));
- analysis->advances = heap_alloc(desc->run->glyphCount*sizeof(*analysis->advances));
- if (desc->run->glyphOffsets) {
- analysis->advanceoffsets = heap_alloc(desc->run->glyphCount*sizeof(*analysis->advanceoffsets));
- analysis->ascenderoffsets = heap_alloc(desc->run->glyphCount*sizeof(*analysis->ascenderoffsets));
- }
- else {
- analysis->advanceoffsets = NULL;
- analysis->ascenderoffsets = NULL;
- }
+ analysis->glyphs = heap_alloc(desc->run->glyphCount * sizeof(*analysis->glyphs));
+ analysis->origins = heap_alloc(desc->run->glyphCount * sizeof(*analysis->origins));
- if (!analysis->glyphs || !analysis->advances || ((!analysis->advanceoffsets || !analysis->ascenderoffsets) && desc->run->glyphOffsets)) {
+ if (!analysis->glyphs || !analysis->origins) {
heap_free(analysis->glyphs);
- heap_free(analysis->advances);
- heap_free(analysis->advanceoffsets);
- heap_free(analysis->ascenderoffsets);
+ heap_free(analysis->origins);
analysis->glyphs = NULL;
- analysis->advances = NULL;
- analysis->advanceoffsets = NULL;
- analysis->ascenderoffsets = NULL;
+ analysis->origins = NULL;
IDWriteGlyphRunAnalysis_Release(&analysis->IDWriteGlyphRunAnalysis_iface);
return E_OUTOFMEMORY;
@@ -5250,71 +5172,70 @@ HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc *desc, IDWrit
rtl_factor = desc->run->bidiLevel & 1 ? -1.0f : 1.0f;
- if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
- transform_2d_vec(&analysis->origin, &analysis->m);
-
memcpy(analysis->glyphs, desc->run->glyphIndices, desc->run->glyphCount*sizeof(*desc->run->glyphIndices));
- if (desc->run->glyphAdvances) {
- for (i = 0; i < desc->run->glyphCount; i++) {
- init_2d_vec(analysis->advances + i, rtl_factor * desc->run->glyphAdvances[i] * desc->ppdip, desc->run->isSideways);
- if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
- transform_2d_vec(analysis->advances + i, &analysis->m);
- }
- }
- else {
- DWRITE_FONT_METRICS metrics;
- IDWriteFontFace1 *fontface1;
+ IDWriteFontFace_GetMetrics(desc->run->fontFace, &metrics);
+ IDWriteFontFace_QueryInterface(desc->run->fontFace, &IID_IDWriteFontFace1, (void **)&fontface1);
- IDWriteFontFace_GetMetrics(desc->run->fontFace, &metrics);
- IDWriteFontFace_QueryInterface(desc->run->fontFace, &IID_IDWriteFontFace1, (void**)&fontface1);
+ origin.x = desc->origin_x * desc->ppdip;
+ origin.y = desc->origin_y * desc->ppdip;
+ for (i = 0; i < desc->run->glyphCount; i++) {
+ FLOAT advance;
- for (i = 0; i < desc->run->glyphCount; i++) {
- HRESULT hr;
+ /* Use nominal advances if not provided by caller. */
+ if (desc->run->glyphAdvances)
+ advance = rtl_factor * desc->run->glyphAdvances[i] * desc->ppdip;
+ else {
INT32 a;
+ advance = 0.0f;
switch (desc->measuring_mode)
{
case DWRITE_MEASURING_MODE_NATURAL:
- hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, desc->run->glyphIndices + i, &a, desc->run->isSideways);
- if (FAILED(hr))
- a = 0;
- init_2d_vec(analysis->advances + i, rtl_factor * get_scaled_advance_width(a, desc->run->fontEmSize, &metrics) * desc->ppdip,
- desc->run->isSideways);
+ if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, desc->run->glyphIndices + i, &a,
+ desc->run->isSideways)))
+ advance = rtl_factor * get_scaled_advance_width(a, desc->run->fontEmSize, &metrics) * desc->ppdip;
break;
case DWRITE_MEASURING_MODE_GDI_CLASSIC:
case DWRITE_MEASURING_MODE_GDI_NATURAL:
- hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, desc->run->fontEmSize, desc->ppdip, desc->transform,
- desc->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, desc->run->isSideways, 1, desc->run->glyphIndices + i, &a);
- if (FAILED(hr))
- init_2d_vec(analysis->advances + i, 0.0f, FALSE);
- else
- init_2d_vec(analysis->advances + i, rtl_factor * floorf(a * desc->run->fontEmSize * desc->ppdip / metrics.designUnitsPerEm + 0.5f),
- desc->run->isSideways);
+ if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, desc->run->fontEmSize,
+ desc->ppdip, desc->transform, desc->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL,
+ desc->run->isSideways, 1, desc->run->glyphIndices + i, &a)))
+ advance = rtl_factor * floorf(a * desc->run->fontEmSize * desc->ppdip / metrics.designUnitsPerEm + 0.5f);
break;
default:
;
}
-
- if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
- transform_2d_vec(analysis->advances + i, &analysis->m);
}
- IDWriteFontFace1_Release(fontface1);
- }
+ analysis->origins[i] = origin;
+
+ /* Offsets are optional, appled to pre-transformed origin. */
+ if (desc->run->glyphOffsets) {
+ FLOAT advanceoffset = rtl_factor * desc->run->glyphOffsets[i].advanceOffset * desc->ppdip;
+ FLOAT ascenderoffset = -desc->run->glyphOffsets[i].ascenderOffset * desc->ppdip;
- if (desc->run->glyphOffsets) {
- for (i = 0; i < desc->run->glyphCount; i++) {
- init_2d_vec(analysis->advanceoffsets + i, rtl_factor * desc->run->glyphOffsets[i].advanceOffset * desc->ppdip, desc->run->isSideways);
- /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
- init_2d_vec(analysis->ascenderoffsets + i, -desc->run->glyphOffsets[i].ascenderOffset * desc->ppdip, !desc->run->isSideways);
- if (analysis->flags & RUNANALYSIS_USE_TRANSFORM) {
- transform_2d_vec(analysis->advanceoffsets + i, &analysis->m);
- transform_2d_vec(analysis->ascenderoffsets + i, &analysis->m);
+ if (desc->run->isSideways) {
+ analysis->origins[i].x += ascenderoffset;
+ analysis->origins[i].y += advanceoffset;
+ }
+ else {
+ analysis->origins[i].x += advanceoffset;
+ analysis->origins[i].y += ascenderoffset;
}
}
+
+ if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
+ transform_point(analysis->origins + i, &analysis->m);
+
+ if (desc->run->isSideways)
+ origin.y += advance;
+ else
+ origin.x += advance;
}
+ IDWriteFontFace1_Release(fontface1);
+
*ret = &analysis->IDWriteGlyphRunAnalysis_iface;
return S_OK;
}
--
2.11.0
More information about the wine-patches
mailing list