dwrite: Cleanup rendering interface with freetype.
This commit is contained in:
parent
9303c6eeed
commit
2c4ba8a008
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue