Commit b3ad9000 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Move glyph box cache to PE side.

parent 4ae2058e
...@@ -734,7 +734,7 @@ struct font_backend_funcs ...@@ -734,7 +734,7 @@ struct font_backend_funcs
UINT16 (CDECL *get_glyph_count)(font_object_handle object); UINT16 (CDECL *get_glyph_count)(font_object_handle object);
INT32 (CDECL *get_glyph_advance)(font_object_handle object, float em_size, UINT16 glyph, INT32 (CDECL *get_glyph_advance)(font_object_handle object, float em_size, UINT16 glyph,
DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours); DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours);
void (CDECL *get_glyph_bbox)(void *key, struct dwrite_glyphbitmap *bitmap_desc); void (CDECL *get_glyph_bbox)(font_object_handle object, struct dwrite_glyphbitmap *bitmap_desc);
BOOL (CDECL *get_glyph_bitmap)(void *key, struct dwrite_glyphbitmap *bitmap_desc); BOOL (CDECL *get_glyph_bitmap)(void *key, struct dwrite_glyphbitmap *bitmap_desc);
void (CDECL *get_design_glyph_metrics)(font_object_handle object, UINT16 upem, UINT16 ascent, unsigned int simulations, void (CDECL *get_design_glyph_metrics)(font_object_handle object, UINT16 upem, UINT16 ascent, unsigned int simulations,
UINT16 glyph, DWRITE_GLYPH_METRICS *metrics); UINT16 glyph, DWRITE_GLYPH_METRICS *metrics);
......
...@@ -47,11 +47,6 @@ static const FLOAT RECOMMENDED_NATURAL_PPEM = 20.0f; ...@@ -47,11 +47,6 @@ static const FLOAT RECOMMENDED_NATURAL_PPEM = 20.0f;
static const struct font_backend_funcs *font_funcs; static const struct font_backend_funcs *font_funcs;
void dwrite_fontface_get_glyph_bbox(IDWriteFontFace *fontface, struct dwrite_glyphbitmap *bitmap)
{
font_funcs->get_glyph_bbox(fontface, bitmap);
}
struct cache_key struct cache_key
{ {
float size; float size;
...@@ -65,40 +60,28 @@ struct cache_entry ...@@ -65,40 +60,28 @@ struct cache_entry
struct list mru; struct list mru;
struct cache_key key; struct cache_key key;
float advance; float advance;
RECT bbox;
unsigned int has_contours : 1; unsigned int has_contours : 1;
unsigned int has_advance : 1; unsigned int has_advance : 1;
unsigned int has_bbox : 1;
}; };
static struct cache_entry * fontface_get_cache_entry(struct dwrite_fontface *fontface, const struct cache_key *key)
{
struct cache_entry *entry;
struct wine_rb_entry *e;
if (!(e = wine_rb_get(&fontface->cache.tree, key))) return NULL;
entry = WINE_RB_ENTRY_VALUE(e, struct cache_entry, entry);
list_remove(&entry->mru);
list_add_head(&fontface->cache.mru, &entry->mru);
return WINE_RB_ENTRY_VALUE(entry, struct cache_entry, entry);
}
static size_t fontface_get_cache_entry_size(const struct cache_entry *entry) static size_t fontface_get_cache_entry_size(const struct cache_entry *entry)
{ {
return sizeof(*entry); return sizeof(*entry);
} }
static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float fontsize, unsigned short glyph, static struct cache_entry * fontface_get_cache_entry(struct dwrite_fontface *fontface, const struct cache_key *key)
unsigned short mode, BOOL *has_contours)
{ {
struct cache_key key = { .size = fontsize, .glyph = glyph, .mode = mode };
struct cache_entry *entry, *old_entry; struct cache_entry *entry, *old_entry;
struct wine_rb_entry *e;
size_t size; size_t size;
BOOL value;
if (!(entry = fontface_get_cache_entry(fontface, &key))) if (!(e = wine_rb_get(&fontface->cache.tree, key)))
{ {
if (!(entry = calloc(1, sizeof(*entry)))) if (!(entry = calloc(1, sizeof(*entry)))) return NULL;
return 0.0f; entry->key = *key;
entry->key = key; list_init(&entry->mru);
size = fontface_get_cache_entry_size(entry); size = fontface_get_cache_entry_size(entry);
if ((fontface->cache.size + size > fontface->cache.max_size) && !list_empty(&fontface->cache.mru)) if ((fontface->cache.size + size > fontface->cache.max_size) && !list_empty(&fontface->cache.mru))
...@@ -110,16 +93,33 @@ static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float ...@@ -110,16 +93,33 @@ static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float
free(old_entry); free(old_entry);
} }
list_add_head(&fontface->cache.mru, &entry->mru);
if (wine_rb_put(&fontface->cache.tree, &key, &entry->entry) == -1) if (wine_rb_put(&fontface->cache.tree, &key, &entry->entry) == -1)
{ {
WARN("Failed to add cache entry.\n"); WARN("Failed to add cache entry.\n");
return 0.0f; free(entry);
return NULL;
} }
fontface->cache.size += size; fontface->cache.size += size;
} }
else
entry = WINE_RB_ENTRY_VALUE(e, struct cache_entry, entry);
list_remove(&entry->mru);
list_add_head(&fontface->cache.mru, &entry->mru);
return entry;
}
static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float fontsize, unsigned short glyph,
unsigned short mode, BOOL *has_contours)
{
struct cache_key key = { .size = fontsize, .glyph = glyph, .mode = mode };
struct cache_entry *entry;
BOOL value;
if (!(entry = fontface_get_cache_entry(fontface, &key)))
return 0.0f;
if (!entry->has_advance) if (!entry->has_advance)
{ {
...@@ -132,6 +132,32 @@ static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float ...@@ -132,6 +132,32 @@ static float fontface_get_glyph_advance(struct dwrite_fontface *fontface, float
return entry->advance; return entry->advance;
} }
void dwrite_fontface_get_glyph_bbox(IDWriteFontFace *iface, struct dwrite_glyphbitmap *bitmap)
{
struct cache_key key = { .size = bitmap->emsize, .glyph = bitmap->glyph, .mode = DWRITE_MEASURING_MODE_NATURAL };
struct dwrite_fontface *fontface = unsafe_impl_from_IDWriteFontFace(iface);
struct cache_entry *entry;
EnterCriticalSection(&fontface->cs);
/* For now bypass cache for transformed cases. */
if (bitmap->m && memcmp(bitmap->m, &identity, sizeof(*bitmap->m)))
{
font_funcs->get_glyph_bbox(fontface->get_font_object(fontface), bitmap);
}
else if ((entry = fontface_get_cache_entry(fontface, &key)))
{
if (entry->has_bbox)
bitmap->bbox = entry->bbox;
else
{
font_funcs->get_glyph_bbox(fontface->get_font_object(fontface), bitmap);
entry->bbox = bitmap->bbox;
entry->has_bbox = 1;
}
}
LeaveCriticalSection(&fontface->cs);
}
static int fontface_cache_compare(const void *k, const struct wine_rb_entry *e) static int fontface_cache_compare(const void *k, const struct wine_rb_entry *e)
{ {
const struct cache_entry *entry = WINE_RB_ENTRY_VALUE(e, const struct cache_entry, entry); const struct cache_entry *entry = WINE_RB_ENTRY_VALUE(e, const struct cache_entry, entry);
...@@ -5819,8 +5845,6 @@ static UINT32 get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode, INT ...@@ -5819,8 +5845,6 @@ static UINT32 get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode, INT
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; struct dwrite_glyphbitmap glyph_bitmap;
IDWriteFontFace4 *fontface;
HRESULT hr;
UINT32 i; UINT32 i;
if (analysis->flags & RUNANALYSIS_BOUNDS_READY) { if (analysis->flags & RUNANALYSIS_BOUNDS_READY) {
...@@ -5831,12 +5855,8 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a ...@@ -5831,12 +5855,8 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
if (analysis->run.isSideways) if (analysis->run.isSideways)
FIXME("sideways runs are not supported.\n"); FIXME("sideways runs are not supported.\n");
hr = IDWriteFontFace_QueryInterface(analysis->run.fontFace, &IID_IDWriteFontFace4, (void **)&fontface);
if (FAILED(hr))
WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr);
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap)); memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
glyph_bitmap.simulations = IDWriteFontFace4_GetSimulations(fontface); glyph_bitmap.simulations = IDWriteFontFace_GetSimulations(analysis->run.fontFace);
glyph_bitmap.emsize = analysis->run.fontEmSize; glyph_bitmap.emsize = analysis->run.fontEmSize;
glyph_bitmap.nohint = is_natural_rendering_mode(analysis->rendering_mode); glyph_bitmap.nohint = is_natural_rendering_mode(analysis->rendering_mode);
if (analysis->flags & RUNANALYSIS_USE_TRANSFORM) if (analysis->flags & RUNANALYSIS_USE_TRANSFORM)
...@@ -5847,7 +5867,7 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a ...@@ -5847,7 +5867,7 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
UINT32 bitmap_size; UINT32 bitmap_size;
glyph_bitmap.glyph = analysis->run.glyphIndices[i]; glyph_bitmap.glyph = analysis->run.glyphIndices[i];
font_funcs->get_glyph_bbox(fontface, &glyph_bitmap); dwrite_fontface_get_glyph_bbox(analysis->run.fontFace, &glyph_bitmap);
bitmap_size = get_glyph_bitmap_pitch(analysis->rendering_mode, bbox->right - bbox->left) * bitmap_size = get_glyph_bitmap_pitch(analysis->rendering_mode, bbox->right - bbox->left) *
(bbox->bottom - bbox->top); (bbox->bottom - bbox->top);
...@@ -5858,8 +5878,6 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a ...@@ -5858,8 +5878,6 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
UnionRect(&analysis->bounds, &analysis->bounds, bbox); UnionRect(&analysis->bounds, &analysis->bounds, bbox);
} }
IDWriteFontFace4_Release(fontface);
analysis->flags |= RUNANALYSIS_BOUNDS_READY; analysis->flags |= RUNANALYSIS_BOUNDS_READY;
*bounds = analysis->bounds; *bounds = analysis->bounds;
} }
...@@ -5946,7 +5964,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis) ...@@ -5946,7 +5964,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
BOOL is_1bpp; BOOL is_1bpp;
glyph_bitmap.glyph = analysis->run.glyphIndices[i]; glyph_bitmap.glyph = analysis->run.glyphIndices[i];
font_funcs->get_glyph_bbox(fontface, &glyph_bitmap); dwrite_fontface_get_glyph_bbox(analysis->run.fontFace, &glyph_bitmap);
if (IsRectEmpty(bbox)) if (IsRectEmpty(bbox))
continue; continue;
......
...@@ -76,6 +76,7 @@ MAKE_FUNCPTR(FT_Done_FreeType); ...@@ -76,6 +76,7 @@ MAKE_FUNCPTR(FT_Done_FreeType);
MAKE_FUNCPTR(FT_Done_Glyph); MAKE_FUNCPTR(FT_Done_Glyph);
MAKE_FUNCPTR(FT_Done_Size); MAKE_FUNCPTR(FT_Done_Size);
MAKE_FUNCPTR(FT_Get_First_Char); MAKE_FUNCPTR(FT_Get_First_Char);
MAKE_FUNCPTR(FT_Get_Glyph);
MAKE_FUNCPTR(FT_Get_Kerning); MAKE_FUNCPTR(FT_Get_Kerning);
MAKE_FUNCPTR(FT_Get_Sfnt_Table); MAKE_FUNCPTR(FT_Get_Sfnt_Table);
MAKE_FUNCPTR(FT_Glyph_Copy); MAKE_FUNCPTR(FT_Glyph_Copy);
...@@ -184,6 +185,7 @@ static BOOL init_freetype(void) ...@@ -184,6 +185,7 @@ static BOOL init_freetype(void)
LOAD_FUNCPTR(FT_Done_Glyph) LOAD_FUNCPTR(FT_Done_Glyph)
LOAD_FUNCPTR(FT_Done_Size) LOAD_FUNCPTR(FT_Done_Size)
LOAD_FUNCPTR(FT_Get_First_Char) LOAD_FUNCPTR(FT_Get_First_Char)
LOAD_FUNCPTR(FT_Get_Glyph)
LOAD_FUNCPTR(FT_Get_Kerning) LOAD_FUNCPTR(FT_Get_Kerning)
LOAD_FUNCPTR(FT_Get_Sfnt_Table) LOAD_FUNCPTR(FT_Get_Sfnt_Table)
LOAD_FUNCPTR(FT_Glyph_Copy) LOAD_FUNCPTR(FT_Glyph_Copy)
...@@ -572,7 +574,7 @@ static BOOL is_face_scalable(void *key) ...@@ -572,7 +574,7 @@ static BOOL is_face_scalable(void *key)
return FALSE; return FALSE;
} }
static BOOL get_glyph_transform(void *key, struct dwrite_glyphbitmap *bitmap, FT_Matrix *ret) static BOOL get_glyph_transform(struct dwrite_glyphbitmap *bitmap, FT_Matrix *ret)
{ {
FT_Matrix m; FT_Matrix m;
...@@ -583,7 +585,7 @@ static BOOL get_glyph_transform(void *key, struct dwrite_glyphbitmap *bitmap, FT ...@@ -583,7 +585,7 @@ static BOOL get_glyph_transform(void *key, struct dwrite_glyphbitmap *bitmap, FT
/* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef. /* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef.
Disable transform if that's the case. */ Disable transform if that's the case. */
if (!is_face_scalable(key) || (!bitmap->m && !bitmap->simulations)) if (!bitmap->m && !bitmap->simulations)
return FALSE; return FALSE;
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) { if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
...@@ -602,42 +604,42 @@ static BOOL get_glyph_transform(void *key, struct dwrite_glyphbitmap *bitmap, FT ...@@ -602,42 +604,42 @@ static BOOL get_glyph_transform(void *key, struct dwrite_glyphbitmap *bitmap, FT
return TRUE; return TRUE;
} }
static void CDECL freetype_get_glyph_bbox(void *key, struct dwrite_glyphbitmap *bitmap) static void CDECL freetype_get_glyph_bbox(font_object_handle object, struct dwrite_glyphbitmap *bitmap)
{ {
FTC_ImageTypeRec imagetype; FT_Face face = object;
FT_Glyph glyph = NULL;
FT_BBox bbox = { 0 }; FT_BBox bbox = { 0 };
BOOL needs_transform; BOOL needs_transform;
FT_Glyph glyph;
FT_Matrix m; FT_Matrix m;
FT_Size size;
RtlEnterCriticalSection(&freetype_cs); SetRectEmpty(&bitmap->bbox);
needs_transform = get_glyph_transform(key, bitmap, &m); if (!(size = freetype_set_face_size(face, bitmap->emsize)))
return;
imagetype.face_id = key; needs_transform = FT_IS_SCALABLE(face) && get_glyph_transform(bitmap, &m);
imagetype.width = 0;
imagetype.height = bitmap->emsize;
imagetype.flags = needs_transform ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT;
if (pFTC_ImageCache_Lookup(image_cache, &imagetype, bitmap->glyph, &glyph, NULL) == 0) { if (pFT_Load_Glyph(face, bitmap->glyph, needs_transform ? FT_LOAD_NO_BITMAP : 0))
if (needs_transform) { {
FT_Glyph glyph_copy; WARN("Failed to load glyph %u.\n", bitmap->glyph);
pFT_Done_Size(size);
return;
}
if (pFT_Glyph_Copy(glyph, &glyph_copy) == 0) { pFT_Get_Glyph(face->glyph, &glyph);
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_BOLD) if (needs_transform)
embolden_glyph(glyph_copy, bitmap->emsize); {
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_BOLD)
embolden_glyph(glyph, bitmap->emsize);
/* Includes oblique and user transform. */ /* Includes oblique and user transform. */
pFT_Glyph_Transform(glyph_copy, &m, NULL); pFT_Glyph_Transform(glyph, &m, NULL);
pFT_Glyph_Get_CBox(glyph_copy, FT_GLYPH_BBOX_PIXELS, &bbox);
pFT_Done_Glyph(glyph_copy);
}
}
else
pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
} }
RtlLeaveCriticalSection(&freetype_cs); pFT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
pFT_Done_Glyph(glyph);
pFT_Done_Size(size);
/* flip Y axis */ /* flip Y axis */
SetRect(&bitmap->bbox, bbox.xMin, -bbox.yMax, bbox.xMax, -bbox.yMin); SetRect(&bitmap->bbox, bbox.xMin, -bbox.yMax, bbox.xMax, -bbox.yMin);
...@@ -744,7 +746,7 @@ static BOOL CDECL freetype_get_glyph_bitmap(void *key, struct dwrite_glyphbitmap ...@@ -744,7 +746,7 @@ static BOOL CDECL freetype_get_glyph_bitmap(void *key, struct dwrite_glyphbitmap
RtlEnterCriticalSection(&freetype_cs); RtlEnterCriticalSection(&freetype_cs);
needs_transform = get_glyph_transform(key, bitmap, &m); needs_transform = is_face_scalable(key) && get_glyph_transform(bitmap, &m);
imagetype.face_id = key; imagetype.face_id = key;
imagetype.width = 0; imagetype.width = 0;
...@@ -865,7 +867,7 @@ static INT32 CDECL null_get_glyph_advance(font_object_handle object, float emsiz ...@@ -865,7 +867,7 @@ static INT32 CDECL null_get_glyph_advance(font_object_handle object, float emsiz
return 0; return 0;
} }
static void CDECL null_get_glyph_bbox(void *key, struct dwrite_glyphbitmap *bitmap) static void CDECL null_get_glyph_bbox(font_object_handle object, struct dwrite_glyphbitmap *bitmap)
{ {
SetRectEmpty(&bitmap->bbox); SetRectEmpty(&bitmap->bbox);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment