From 2c4ba8a0087d0145709cdf28692da879d47ecb28 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 27 Aug 2015 08:38:50 +0300 Subject: [PATCH] dwrite: Cleanup rendering interface with freetype. --- dlls/dwrite/dwrite_private.h | 14 ++++++- dlls/dwrite/font.c | 71 ++++++++++++++++++++++-------------- dlls/dwrite/freetype.c | 58 ++++++++++++++--------------- 3 files changed, 84 insertions(+), 59 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index d1127f10846..39043d924e9 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -191,6 +191,16 @@ struct glyph_outline { extern HRESULT new_glyph_outline(UINT32,struct glyph_outline**) DECLSPEC_HIDDEN; /* FreeType integration */ +struct dwrite_glyphbitmap { + IDWriteFontFace2 *fontface; + FLOAT emsize; + BOOL nohint; + UINT16 index; + INT pitch; + RECT bbox; + BYTE *buf; +}; + extern BOOL init_freetype(void) DECLSPEC_HIDDEN; extern void release_freetype(void) DECLSPEC_HIDDEN; extern HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace2*,UINT16,UINT16,DWRITE_GLYPH_METRICS*) DECLSPEC_HIDDEN; @@ -201,8 +211,8 @@ extern UINT16 freetype_get_glyphcount(IDWriteFontFace2*) DECLSPEC_HIDDEN; extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32,INT) DECLSPEC_HIDDEN; extern BOOL freetype_has_kerning_pairs(IDWriteFontFace2*) DECLSPEC_HIDDEN; extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2*,UINT16,UINT16) DECLSPEC_HIDDEN; -extern void freetype_get_glyph_bbox(IDWriteFontFace2*,FLOAT,UINT16,BOOL,RECT*) DECLSPEC_HIDDEN; -extern void freetype_get_glyph_bitmap(IDWriteFontFace2*,FLOAT,UINT16,const RECT*,BYTE*) DECLSPEC_HIDDEN; +extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; +extern void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; extern INT freetype_get_charmap_index(IDWriteFontFace2*,BOOL*) DECLSPEC_HIDDEN; extern INT32 freetype_get_glyph_advance(IDWriteFontFace2*,FLOAT,UINT16,DWRITE_MEASURING_MODE) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 0d5cbc0c3a3..f66d49c2f15 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -3496,9 +3496,10 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface) static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *analysis, RECT *bounds) { + struct dwrite_glyphbitmap glyph_bitmap; IDWriteFontFace2 *fontface2; - BOOL nohint, is_rtl; FLOAT origin_x; + BOOL is_rtl; HRESULT hr; UINT32 i; @@ -3514,29 +3515,35 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a if (FAILED(hr)) WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr); - nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; - /* 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; is_rtl = analysis->run.bidiLevel & 1; + + memset(&glyph_bitmap, 0, sizeof(glyph_bitmap)); + glyph_bitmap.fontface = fontface2; + glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip; + glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || + 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]; - RECT bbox; + RECT *bbox = &glyph_bitmap.bbox; - freetype_get_glyph_bbox(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], nohint, &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, 0); else - OffsetRect(&bbox, origin_x, 0); + OffsetRect(bbox, origin_x, 0); if (offset) - OffsetRect(&bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset); + OffsetRect(bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset); - UnionRect(&analysis->bounds, &analysis->bounds, &bbox); + UnionRect(&analysis->bounds, &analysis->bounds, bbox); origin_x += is_rtl ? -advance : advance; } @@ -3588,11 +3595,13 @@ static inline BYTE *get_pixel_ptr(BYTE *ptr, DWRITE_TEXTURE_TYPE type, const REC static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DWRITE_TEXTURE_TYPE type) { static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + struct dwrite_glyphbitmap glyph_bitmap; IDWriteFontFace2 *fontface2; - BOOL is_rtl, nohint; FLOAT origin_x; UINT32 i, size; + BOOL is_rtl; HRESULT hr; + RECT *bbox; hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2); if (FAILED(hr)) { @@ -3600,8 +3609,6 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW return; } - nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; - size = (analysis->bounds.right - analysis->bounds.left)*(analysis->bounds.bottom - analysis->bounds.top); if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) size *= 3; @@ -3609,39 +3616,47 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW origin_x = 0.0; is_rtl = analysis->run.bidiLevel & 1; + + memset(&glyph_bitmap, 0, sizeof(glyph_bitmap)); + glyph_bitmap.fontface = fontface2; + glyph_bitmap.emsize = analysis->run.fontEmSize * analysis->ppdip; + glyph_bitmap.nohint = analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL || + analysis->rendering_mode == DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC; + 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]; - int pitch, x, y, width, height; - BYTE *glyph, *src, *dst; - RECT bbox; + int x, y, width, height; + BYTE *src, *dst; - freetype_get_glyph_bbox(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], nohint, &bbox); + glyph_bitmap.index = analysis->run.glyphIndices[i]; + freetype_get_glyph_bbox(&glyph_bitmap); - if (IsRectEmpty(&bbox)) { + if (IsRectEmpty(bbox)) { origin_x += is_rtl ? -advance : advance; continue; } - width = bbox.right - bbox.left; - height = bbox.bottom - bbox.top; - pitch = ((width + 31) >> 5) << 2; + width = bbox->right - bbox->left; + height = bbox->bottom - bbox->top; + glyph_bitmap.pitch = ((width + 31) >> 5) << 2; - src = glyph = heap_alloc_zero((bbox.bottom - bbox.top) * pitch); - freetype_get_glyph_bitmap(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], &bbox, glyph); + glyph_bitmap.buf = src = heap_alloc_zero(height * glyph_bitmap.pitch); + freetype_get_glyph_bitmap(&glyph_bitmap); if (is_rtl) - OffsetRect(&bbox, origin_x - advance, 0); + OffsetRect(bbox, origin_x - advance, 0); else - OffsetRect(&bbox, origin_x, 0); + OffsetRect(bbox, origin_x, 0); if (offset) - OffsetRect(&bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset); + OffsetRect(bbox, is_rtl ? -offset->advanceOffset : offset->advanceOffset, is_rtl ? -offset->ascenderOffset : offset->ascenderOffset); - OffsetRect(&bbox, analysis->originX, analysis->originY); + OffsetRect(bbox, analysis->originX, analysis->originY); /* blit to analysis bitmap */ - dst = get_pixel_ptr(analysis->bitmap, type, &bbox, &analysis->bounds); + dst = get_pixel_ptr(analysis->bitmap, type, bbox, &analysis->bounds); /* convert 1bpp to 8bpp/24bpp */ if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) { @@ -3661,7 +3676,7 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW } } - heap_free(glyph); + heap_free(glyph_bitmap.buf); origin_x += is_rtl ? -advance : advance; } diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index ec6a13f4cd1..dc6d701f4c4 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -487,43 +487,43 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le return adjustment; } -void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, BOOL nohint, RECT *ret) +void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap) { FTC_ImageTypeRec imagetype; FT_BBox bbox = { 0 }; FT_Glyph glyph; - imagetype.face_id = fontface; + imagetype.face_id = bitmap->fontface; imagetype.width = 0; - imagetype.height = emSize; + imagetype.height = bitmap->emsize; imagetype.flags = FT_LOAD_DEFAULT; EnterCriticalSection(&freetype_cs); - if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0) + if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox); LeaveCriticalSection(&freetype_cs); /* flip Y axis */ - ret->left = bbox.xMin; - ret->right = bbox.xMax; - ret->top = -bbox.yMax; - ret->bottom = -bbox.yMin; + bitmap->bbox.left = bbox.xMin; + bitmap->bbox.right = bbox.xMax; + bitmap->bbox.top = -bbox.yMax; + bitmap->bbox.bottom = -bbox.yMin; } -void freetype_get_glyph_bitmap(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, const RECT *bbox, BYTE *buf) +void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) { + const RECT *bbox = &bitmap->bbox; FTC_ImageTypeRec imagetype; FT_Glyph glyph; - imagetype.face_id = fontface; + imagetype.face_id = bitmap->fontface; imagetype.width = 0; - imagetype.height = emSize; + imagetype.height = bitmap->emsize; imagetype.flags = FT_LOAD_DEFAULT; EnterCriticalSection(&freetype_cs); - if (pFTC_ImageCache_Lookup(image_cache, &imagetype, index, &glyph, NULL) == 0) { + if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->index, &glyph, NULL) == 0) { int width = bbox->right - bbox->left; - int pitch = ((width + 31) >> 5) << 2; int height = bbox->bottom - bbox->top; if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { @@ -534,12 +534,12 @@ void freetype_get_glyph_bitmap(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 ft_bitmap.width = width; ft_bitmap.rows = height; - ft_bitmap.pitch = pitch; + ft_bitmap.pitch = bitmap->pitch; ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; - ft_bitmap.buffer = buf; + ft_bitmap.buffer = bitmap->buf; /* Note: FreeType will only set 'black' bits for us. */ - memset(buf, 0, height*pitch); + memset(bitmap->buf, 0, height * bitmap->pitch); if (pFT_Outline_New(library, src->n_points, src->n_contours, ©) == 0) { pFT_Outline_Copy(src, ©); pFT_Outline_Translate(©, -bbox->left << 6, bbox->bottom << 6); @@ -548,21 +548,21 @@ void freetype_get_glyph_bitmap(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 } } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { - FT_Bitmap *bitmap = &((FT_BitmapGlyph)glyph)->bitmap; - BYTE *src = bitmap->buffer, *dst = buf; - int w = min(pitch, (bitmap->width + 7) >> 3); - int h = min(height, bitmap->rows); + FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap; + BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf; + int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3); + int h = min(height, ft_bitmap->rows); - memset(buf, 0, height*pitch); + memset(bitmap->buf, 0, height * bitmap->pitch); while (h--) { memcpy(dst, src, w); - src += bitmap->pitch; - dst += pitch; + src += ft_bitmap->pitch; + dst += bitmap->pitch; } } else - FIXME("format %d not handled\n", glyph->format); + FIXME("format %x not handled\n", glyph->format); } LeaveCriticalSection(&freetype_cs); } @@ -673,15 +673,15 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le return 0; } -void freetype_get_glyph_bbox(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, BOOL nohint, RECT *ret) +void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap) { - ret->left = ret->right = ret->top = ret->bottom = 0; + memset(&bitmap->bbox, 0, sizeof(bitmap->bbox)); } -void freetype_get_glyph_bitmap(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, const RECT *bbox, BYTE *buf) +void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) { - UINT32 size = (bbox->right - bbox->left)*(bbox->bottom - bbox->top); - memset(buf, 0, size); + UINT32 size = (bitmap->bbox.right - bitmap->bbox.left)*(bitmap->bbox.bottom - bitmap->bbox.top); + memset(bitmap->buf, 0, size); } INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol)