dwrite: Cleanup rendering interface with freetype.

This commit is contained in:
Nikolay Sivov 2015-08-27 08:38:50 +03:00 committed by Alexandre Julliard
parent 9303c6eeed
commit 2c4ba8a008
3 changed files with 84 additions and 59 deletions

View File

@ -191,6 +191,16 @@ struct glyph_outline {
extern HRESULT new_glyph_outline(UINT32,struct glyph_outline**) DECLSPEC_HIDDEN; extern HRESULT new_glyph_outline(UINT32,struct glyph_outline**) DECLSPEC_HIDDEN;
/* FreeType integration */ /* 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 BOOL init_freetype(void) DECLSPEC_HIDDEN;
extern void release_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; 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 UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32,INT) DECLSPEC_HIDDEN;
extern BOOL freetype_has_kerning_pairs(IDWriteFontFace2*) DECLSPEC_HIDDEN; extern BOOL freetype_has_kerning_pairs(IDWriteFontFace2*) DECLSPEC_HIDDEN;
extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2*,UINT16,UINT16) 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_bbox(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
extern void freetype_get_glyph_bitmap(IDWriteFontFace2*,FLOAT,UINT16,const RECT*,BYTE*) DECLSPEC_HIDDEN; extern void freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
extern INT freetype_get_charmap_index(IDWriteFontFace2*,BOOL*) 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; extern INT32 freetype_get_glyph_advance(IDWriteFontFace2*,FLOAT,UINT16,DWRITE_MEASURING_MODE) DECLSPEC_HIDDEN;

View File

@ -3496,9 +3496,10 @@ static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *analysis, RECT *bounds) static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *analysis, RECT *bounds)
{ {
struct dwrite_glyphbitmap glyph_bitmap;
IDWriteFontFace2 *fontface2; IDWriteFontFace2 *fontface2;
BOOL nohint, is_rtl;
FLOAT origin_x; FLOAT origin_x;
BOOL is_rtl;
HRESULT hr; HRESULT hr;
UINT32 i; UINT32 i;
@ -3514,29 +3515,35 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
if (FAILED(hr)) if (FAILED(hr))
WARN("failed to get IDWriteFontFace2, 0x%08x\n", 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 /* 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 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
for any non-zero glyph ascender */ for any non-zero glyph ascender */
origin_x = 0.0; origin_x = 0.0;
is_rtl = analysis->run.bidiLevel & 1; 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++) { for (i = 0; i < analysis->run.glyphCount; i++) {
const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL; const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL;
FLOAT advance = analysis->advances[i]; 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) if (is_rtl)
OffsetRect(&bbox, origin_x - advance, 0); OffsetRect(bbox, origin_x - advance, 0);
else else
OffsetRect(&bbox, origin_x, 0); OffsetRect(bbox, origin_x, 0);
if (offset) 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; 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 void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DWRITE_TEXTURE_TYPE type)
{ {
static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
struct dwrite_glyphbitmap glyph_bitmap;
IDWriteFontFace2 *fontface2; IDWriteFontFace2 *fontface2;
BOOL is_rtl, nohint;
FLOAT origin_x; FLOAT origin_x;
UINT32 i, size; UINT32 i, size;
BOOL is_rtl;
HRESULT hr; HRESULT hr;
RECT *bbox;
hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2); hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace2, (void**)&fontface2);
if (FAILED(hr)) { if (FAILED(hr)) {
@ -3600,8 +3609,6 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
return; 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); size = (analysis->bounds.right - analysis->bounds.left)*(analysis->bounds.bottom - analysis->bounds.top);
if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) if (type == DWRITE_TEXTURE_CLEARTYPE_3x1)
size *= 3; size *= 3;
@ -3609,39 +3616,47 @@ static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis, DW
origin_x = 0.0; origin_x = 0.0;
is_rtl = analysis->run.bidiLevel & 1; 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++) { for (i = 0; i < analysis->run.glyphCount; i++) {
const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL; const DWRITE_GLYPH_OFFSET *offset = analysis->offsets ? &analysis->offsets[i] : NULL;
FLOAT advance = analysis->advances[i]; FLOAT advance = analysis->advances[i];
int pitch, x, y, width, height; int x, y, width, height;
BYTE *glyph, *src, *dst; BYTE *src, *dst;
RECT 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 (IsRectEmpty(&bbox)) { if (IsRectEmpty(bbox)) {
origin_x += is_rtl ? -advance : advance; origin_x += is_rtl ? -advance : advance;
continue; continue;
} }
width = bbox.right - bbox.left; width = bbox->right - bbox->left;
height = bbox.bottom - bbox.top; height = bbox->bottom - bbox->top;
pitch = ((width + 31) >> 5) << 2; glyph_bitmap.pitch = ((width + 31) >> 5) << 2;
src = glyph = heap_alloc_zero((bbox.bottom - bbox.top) * pitch); glyph_bitmap.buf = src = heap_alloc_zero(height * glyph_bitmap.pitch);
freetype_get_glyph_bitmap(fontface2, analysis->run.fontEmSize * analysis->ppdip, analysis->run.glyphIndices[i], &bbox, glyph); freetype_get_glyph_bitmap(&glyph_bitmap);
if (is_rtl) if (is_rtl)
OffsetRect(&bbox, origin_x - advance, 0); OffsetRect(bbox, origin_x - advance, 0);
else else
OffsetRect(&bbox, origin_x, 0); OffsetRect(bbox, origin_x, 0);
if (offset) 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 */ /* 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 */ /* convert 1bpp to 8bpp/24bpp */
if (type == DWRITE_TEXTURE_CLEARTYPE_3x1) { 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; origin_x += is_rtl ? -advance : advance;
} }

View File

@ -487,43 +487,43 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le
return adjustment; 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; FTC_ImageTypeRec imagetype;
FT_BBox bbox = { 0 }; FT_BBox bbox = { 0 };
FT_Glyph glyph; FT_Glyph glyph;
imagetype.face_id = fontface; imagetype.face_id = bitmap->fontface;
imagetype.width = 0; imagetype.width = 0;
imagetype.height = emSize; imagetype.height = bitmap->emsize;
imagetype.flags = FT_LOAD_DEFAULT; imagetype.flags = FT_LOAD_DEFAULT;
EnterCriticalSection(&freetype_cs); 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); pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
LeaveCriticalSection(&freetype_cs); LeaveCriticalSection(&freetype_cs);
/* flip Y axis */ /* flip Y axis */
ret->left = bbox.xMin; bitmap->bbox.left = bbox.xMin;
ret->right = bbox.xMax; bitmap->bbox.right = bbox.xMax;
ret->top = -bbox.yMax; bitmap->bbox.top = -bbox.yMax;
ret->bottom = -bbox.yMin; 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; FTC_ImageTypeRec imagetype;
FT_Glyph glyph; FT_Glyph glyph;
imagetype.face_id = fontface; imagetype.face_id = bitmap->fontface;
imagetype.width = 0; imagetype.width = 0;
imagetype.height = emSize; imagetype.height = bitmap->emsize;
imagetype.flags = FT_LOAD_DEFAULT; imagetype.flags = FT_LOAD_DEFAULT;
EnterCriticalSection(&freetype_cs); 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 width = bbox->right - bbox->left;
int pitch = ((width + 31) >> 5) << 2;
int height = bbox->bottom - bbox->top; int height = bbox->bottom - bbox->top;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { 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.width = width;
ft_bitmap.rows = height; ft_bitmap.rows = height;
ft_bitmap.pitch = pitch; ft_bitmap.pitch = bitmap->pitch;
ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; 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. */ /* 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, &copy) == 0) { if (pFT_Outline_New(library, src->n_points, src->n_contours, &copy) == 0) {
pFT_Outline_Copy(src, &copy); pFT_Outline_Copy(src, &copy);
pFT_Outline_Translate(&copy, -bbox->left << 6, bbox->bottom << 6); pFT_Outline_Translate(&copy, -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) { else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
FT_Bitmap *bitmap = &((FT_BitmapGlyph)glyph)->bitmap; FT_Bitmap *ft_bitmap = &((FT_BitmapGlyph)glyph)->bitmap;
BYTE *src = bitmap->buffer, *dst = buf; BYTE *src = ft_bitmap->buffer, *dst = bitmap->buf;
int w = min(pitch, (bitmap->width + 7) >> 3); int w = min(bitmap->pitch, (ft_bitmap->width + 7) >> 3);
int h = min(height, bitmap->rows); int h = min(height, ft_bitmap->rows);
memset(buf, 0, height*pitch); memset(bitmap->buf, 0, height * bitmap->pitch);
while (h--) { while (h--) {
memcpy(dst, src, w); memcpy(dst, src, w);
src += bitmap->pitch; src += ft_bitmap->pitch;
dst += pitch; dst += bitmap->pitch;
} }
} }
else else
FIXME("format %d not handled\n", glyph->format); FIXME("format %x not handled\n", glyph->format);
} }
LeaveCriticalSection(&freetype_cs); LeaveCriticalSection(&freetype_cs);
} }
@ -673,15 +673,15 @@ INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace2 *fontface, UINT16 le
return 0; 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); UINT32 size = (bitmap->bbox.right - bitmap->bbox.left)*(bitmap->bbox.bottom - bitmap->bbox.top);
memset(buf, 0, size); memset(bitmap->buf, 0, size);
} }
INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol) INT freetype_get_charmap_index(IDWriteFontFace2 *fontface, BOOL *is_symbol)