[PATCH 2/3] dwrite: Store origin, advances and offsets as vectors for run analysis
Nikolay Sivov
nsivov at codeweavers.com
Mon Nov 2 07:38:42 CST 2015
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/dwrite/font.c | 169 ++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 114 insertions(+), 55 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index ecd22de..d3554a5 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -163,14 +163,14 @@ struct dwrite_glyphrunanalysis {
LONG ref;
DWRITE_RENDERING_MODE rendering_mode;
- DWRITE_GLYPH_RUN run;
+ DWRITE_GLYPH_RUN run; /* glyphAdvances and glyphOffsets are not used */
DWRITE_MATRIX m;
FLOAT ppdip;
- FLOAT originX;
- FLOAT originY;
UINT16 *glyphs;
- FLOAT *advances;
- DWRITE_GLYPH_OFFSET *offsets;
+ D2D_POINT_2F origin;
+ D2D_POINT_2F *advances;
+ D2D_POINT_2F *advanceoffsets;
+ D2D_POINT_2F *ascenderoffsets;
UINT8 flags;
RECT bounds;
@@ -4043,7 +4043,8 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
IDWriteFontFace_Release(This->run.fontFace);
heap_free(This->glyphs);
heap_free(This->advances);
- heap_free(This->offsets);
+ heap_free(This->advanceoffsets);
+ heap_free(This->ascenderoffsets);
heap_free(This->bitmap);
heap_free(This);
}
@@ -4055,7 +4056,7 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
{
struct dwrite_glyphbitmap glyph_bitmap;
IDWriteFontFace2 *fontface2;
- FLOAT origin_x;
+ D2D_POINT_2F origin;
BOOL is_rtl;
HRESULT hr;
UINT32 i;
@@ -4075,7 +4076,7 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
/* 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 = 0.0;
+ origin.x = origin.y = 0.0f;
is_rtl = analysis->run.bidiLevel & 1;
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
@@ -4085,29 +4086,46 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
for (i = 0; i < analysis->run.glyphCount; i++) {
- const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL;
- FLOAT advance = analysis->advances[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;
glyph_bitmap.index = analysis->run.glyphIndices[i];
freetype_get_glyph_bbox(&glyph_bitmap);
if (is_rtl)
- OffsetRect(bbox, origin_x - advance, 0);
+ OffsetRect(bbox, origin.x - advance->x, origin.y - advance->y);
else
- OffsetRect(bbox, origin_x, 0);
+ OffsetRect(bbox, origin.x, origin.y);
- if (offset)
- OffsetRect(bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset);
+ if (advanceoffset) {
+ FLOAT offset_x = advanceoffset->x + ascenderoffset->x;
+ FLOAT offset_y = advanceoffset->y + ascenderoffset->y;
+
+ if (is_rtl) {
+ offset_x *= -1.0f;
+ offset_y *= -1.0f;
+ }
+
+ OffsetRect(bbox, offset_x, offset_y);
+ }
UnionRect(&analysis->bounds, &analysis->bounds, bbox);
- origin_x += is_rtl ? -advance : advance;
+ if (is_rtl) {
+ origin.x -= advance->x;
+ origin.y -= advance->y;
+ }
+ else {
+ origin.x += advance->x;
+ origin.y += advance->y;
+ }
}
IDWriteFontFace2_Release(fontface2);
/* translate to given run origin */
- OffsetRect(&analysis->bounds, analysis->originX, analysis->originY);
+ OffsetRect(&analysis->bounds, analysis->origin.x, analysis->origin.y);
analysis->flags |= RUNANALYSIS_BOUNDS_READY;
*bounds = analysis->bounds;
@@ -4154,7 +4172,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
struct dwrite_glyphbitmap glyph_bitmap;
IDWriteFontFace2 *fontface2;
- FLOAT origin_x;
+ D2D_POINT_2F origin;
UINT32 i, size;
BOOL is_rtl;
HRESULT hr;
@@ -4171,7 +4189,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
size *= 3;
analysis->bitmap = heap_alloc_zero(size);
- origin_x = 0.0;
+ origin.x = origin.y = 0.0f;
is_rtl = analysis->run.bidiLevel & 1;
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
@@ -4183,8 +4201,9 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
bbox = &glyph_bitmap.bbox;
for (i = 0; i < analysis->run.glyphCount; i++) {
- const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL;
- FLOAT advance = analysis->advances[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;
int x, y, width, height;
BYTE *src, *dst;
BOOL is_1bpp;
@@ -4193,7 +4212,14 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
freetype_get_glyph_bbox(&glyph_bitmap);
if (IsRectEmpty(bbox)) {
- origin_x += is_rtl ? -advance : advance;
+ if (is_rtl) {
+ origin.x -= advance->x;
+ origin.y -= advance->y;
+ }
+ else {
+ origin.x += advance->x;
+ origin.y += advance->y;
+ }
continue;
}
@@ -4209,14 +4235,23 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
is_1bpp = freetype_get_glyph_bitmap(&glyph_bitmap);
if (is_rtl)
- OffsetRect(bbox, origin_x - advance, 0);
+ OffsetRect(bbox, origin.x - advance->x, origin.y - advance->y);
else
- OffsetRect(bbox, origin_x, 0);
+ OffsetRect(bbox, origin.x, origin.y);
- if (offset)
- OffsetRect(bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset);
+ if (advanceoffset) {
+ FLOAT offset_x = advanceoffset->x + ascenderoffset->x;
+ FLOAT offset_y = advanceoffset->y + ascenderoffset->y;
- OffsetRect(bbox, analysis->originX, analysis->originY);
+ if (is_rtl) {
+ offset_x *= -1.0f;
+ offset_y *= -1.0f;
+ }
+
+ OffsetRect(bbox, offset_x, offset_y);
+ }
+
+ OffsetRect(bbox, analysis->origin.x, analysis->origin.y);
/* blit to analysis bitmap */
dst = get_pixel_ptr(analysis->bitmap, type, bbox, &analysis->bounds);
@@ -4252,7 +4287,14 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
heap_free(glyph_bitmap.buf);
- origin_x += is_rtl ? -advance : advance;
+ if (is_rtl) {
+ origin.x -= advance->x;
+ origin.y -= advance->y;
+ }
+ else {
+ origin.x += advance->x;
+ origin.y += advance->y;
+ }
}
IDWriteFontFace2_Release(fontface2);
@@ -4262,15 +4304,15 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
/* we don't need this anymore */
heap_free(analysis->glyphs);
heap_free(analysis->advances);
- heap_free(analysis->offsets);
+ heap_free(analysis->advanceoffsets);
+ heap_free(analysis->ascenderoffsets);
IDWriteFontFace_Release(analysis->run.fontFace);
analysis->glyphs = NULL;
analysis->advances = NULL;
- analysis->offsets = NULL;
+ analysis->advanceoffsets = NULL;
+ analysis->ascenderoffsets = NULL;
analysis->run.glyphIndices = NULL;
- analysis->run.glyphAdvances = NULL;
- analysis->run.glyphOffsets = NULL;
analysis->run.fontFace = NULL;
}
@@ -4383,6 +4425,18 @@ 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;
+ }
+}
+
HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode, DWRITE_GLYPH_RUN const *run,
FLOAT ppdip, const DWRITE_MATRIX *transform, DWRITE_GRID_FIT_MODE gridfit_mode, DWRITE_TEXT_ANTIALIAS_MODE aa_mode,
FLOAT originX, FLOAT originY, IDWriteGlyphRunAnalysis **ret)
@@ -4406,22 +4460,32 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
analysis->flags = 0;
analysis->bitmap = NULL;
analysis->ppdip = ppdip;
- analysis->originX = originX * ppdip;
- analysis->originY = originY * ppdip;
+ analysis->origin.x = originX * ppdip;
+ analysis->origin.y = originY * ppdip;
SetRectEmpty(&analysis->bounds);
analysis->run = *run;
IDWriteFontFace_AddRef(analysis->run.fontFace);
analysis->glyphs = heap_alloc(run->glyphCount*sizeof(*run->glyphIndices));
- analysis->advances = heap_alloc(run->glyphCount*sizeof(*run->glyphAdvances));
- analysis->offsets = run->glyphOffsets ? heap_alloc(run->glyphCount*sizeof(*run->glyphOffsets)) : NULL;
- if (!analysis->glyphs || !analysis->advances || (!analysis->offsets && run->glyphOffsets)) {
+ analysis->advances = heap_alloc(run->glyphCount*sizeof(*analysis->advances));
+ if (run->glyphOffsets) {
+ analysis->advanceoffsets = heap_alloc(run->glyphCount*sizeof(*analysis->advanceoffsets));
+ analysis->ascenderoffsets = heap_alloc(run->glyphCount*sizeof(*analysis->ascenderoffsets));
+ }
+ else {
+ analysis->advanceoffsets = NULL;
+ analysis->ascenderoffsets = NULL;
+ }
+
+ if (!analysis->glyphs || !analysis->advances || ((!analysis->advanceoffsets || !analysis->ascenderoffsets) && run->glyphOffsets)) {
heap_free(analysis->glyphs);
heap_free(analysis->advances);
- heap_free(analysis->offsets);
+ heap_free(analysis->advanceoffsets);
+ heap_free(analysis->ascenderoffsets);
analysis->glyphs = NULL;
analysis->advances = NULL;
- analysis->offsets = NULL;
+ analysis->advanceoffsets = NULL;
+ analysis->ascenderoffsets = NULL;
IDWriteGlyphRunAnalysis_Release(&analysis->IDWriteGlyphRunAnalysis_iface);
return E_OUTOFMEMORY;
@@ -4436,17 +4500,14 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
memset(&analysis->m, 0, sizeof(analysis->m));
analysis->run.glyphIndices = analysis->glyphs;
- analysis->run.glyphAdvances = analysis->advances;
- analysis->run.glyphOffsets = analysis->offsets;
+ analysis->run.glyphAdvances = NULL;
+ analysis->run.glyphOffsets = NULL;
memcpy(analysis->glyphs, run->glyphIndices, run->glyphCount*sizeof(*run->glyphIndices));
if (run->glyphAdvances) {
- if (ppdip == 1.0f)
- memcpy(analysis->advances, run->glyphAdvances, run->glyphCount*sizeof(*run->glyphAdvances));
- else {
- for (i = 0; i < run->glyphCount; i++)
- analysis->advances[i] = run->glyphAdvances[i] * ppdip;
+ for (i = 0; i < run->glyphCount; i++) {
+ init_2d_vec(analysis->advances + i, run->glyphAdvances[i] * ppdip, run->isSideways);
}
}
else {
@@ -4466,16 +4527,18 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
hr = IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, run->glyphIndices + i, &a, run->isSideways);
if (FAILED(hr))
a = 0;
- analysis->advances[i] = get_scaled_advance_width(a, run->fontEmSize, &metrics) * ppdip;
+ init_2d_vec(analysis->advances + i, get_scaled_advance_width(a, run->fontEmSize, &metrics) * ppdip,
+ run->isSideways);
break;
case DWRITE_MEASURING_MODE_GDI_CLASSIC:
case DWRITE_MEASURING_MODE_GDI_NATURAL:
hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, run->fontEmSize, ppdip, transform,
measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, run->isSideways, 1, run->glyphIndices + i, &a);
if (FAILED(hr))
- analysis->advances[i] = 0.0;
+ init_2d_vec(analysis->advances + i, 0.0f, FALSE);
else
- analysis->advances[i] = floorf(a * run->fontEmSize * ppdip / metrics.designUnitsPerEm + 0.5f);
+ init_2d_vec(analysis->advances + i, floorf(a * run->fontEmSize * ppdip / metrics.designUnitsPerEm + 0.5f),
+ run->isSideways);
break;
default:
;
@@ -4486,13 +4549,9 @@ HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEA
}
if (run->glyphOffsets) {
- if (ppdip == 1.0f)
- memcpy(analysis->offsets, run->glyphOffsets, run->glyphCount*sizeof(*run->glyphOffsets));
- else {
- for (i = 0; i < run->glyphCount; i++) {
- analysis->offsets[i].advanceOffset = run->glyphOffsets[i].advanceOffset * ppdip;
- analysis->offsets[i].ascenderOffset = run->glyphOffsets[i].ascenderOffset * ppdip;
- }
+ for (i = 0; i < run->glyphCount; i++) {
+ init_2d_vec(analysis->advanceoffsets + i, run->glyphOffsets[i].advanceOffset * ppdip, run->isSideways);
+ init_2d_vec(analysis->ascenderoffsets + i, run->glyphOffsets[i].ascenderOffset * ppdip, !run->isSideways);
}
}
--
2.6.1
More information about the wine-patches
mailing list