dwrite: Introduce interface to font backend.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-03-29 10:48:53 +03:00 committed by Alexandre Julliard
parent d77110a40c
commit ca08a5e722
4 changed files with 109 additions and 76 deletions

View file

@ -442,10 +442,9 @@ extern unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp,
/* BiDi helpers */
extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
/* FreeType integration */
struct dwrite_glyphbitmap
{
IDWriteFontFace4 *fontface;
void *key;
DWORD simulations;
float emsize;
BOOL nohint;
@ -486,18 +485,6 @@ extern int dwrite_outline_push_tag(struct dwrite_outline *outline, unsigned char
extern int dwrite_outline_push_points(struct dwrite_outline *outline, const D2D1_POINT_2F *points,
unsigned int count) DECLSPEC_HIDDEN;
extern HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph,
DWRITE_GLYPH_METRICS *metrics) DECLSPEC_HIDDEN;
extern void freetype_notify_cacheremove(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern int freetype_get_glyph_outline(IDWriteFontFace5 *fontface, float emSize, UINT16 glyph,
struct dwrite_outline *outline) DECLSPEC_HIDDEN;
extern UINT16 freetype_get_glyphcount(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap_desc) DECLSPEC_HIDDEN;
extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN;
extern INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emsize, UINT16 index,
DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours) DECLSPEC_HIDDEN;
extern void freetype_get_design_glyph_bbox(IDWriteFontFace4*,UINT16,UINT16,RECT*) DECLSPEC_HIDDEN;
/* Glyph shaping */
enum SCRIPT_JUSTIFY
{
@ -742,6 +729,21 @@ struct font_callback_funcs
void (CDECL *release_font_data)(struct font_data_context *context);
};
struct font_backend_funcs
{
void (CDECL *notify_release)(void *key);
int (CDECL *get_glyph_outline)(void *key, float em_size, UINT16 glyph, struct dwrite_outline *outline);
UINT16 (CDECL *get_glyph_count)(void *key);
INT32 (CDECL *get_glyph_advance)(void *key, float em_size, UINT16 index, DWRITE_MEASURING_MODE measuring_mode,
BOOL *has_contours);
void (CDECL *get_glyph_bbox)(struct dwrite_glyphbitmap *bitmap_desc);
BOOL (CDECL *get_glyph_bitmap)(struct dwrite_glyphbitmap *bitmap_desc);
void (CDECL *get_design_glyph_metrics)(void *key, UINT16 upem, UINT16 ascent, unsigned int simulations,
UINT16 glyph, DWRITE_GLYPH_METRICS *metrics);
};
extern NTSTATUS CDECL init_font_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out) DECLSPEC_HIDDEN;
extern void init_font_backend(void) DECLSPEC_HIDDEN;
extern void release_font_backend(void) DECLSPEC_HIDDEN;
extern void dwrite_fontface_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap) DECLSPEC_HIDDEN;

View file

@ -63,6 +63,13 @@ static const WCHAR demiW[] = {'d','e','m','i',0};
static const WCHAR spaceW[] = {' ',0};
static const WCHAR enusW[] = {'e','n','-','u','s',0};
static const struct font_backend_funcs *font_funcs;
void dwrite_fontface_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
{
font_funcs->get_glyph_bbox(bitmap);
}
struct dwrite_font_propvec {
FLOAT stretch;
FLOAT style;
@ -662,7 +669,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface)
for (i = 0; i < ARRAY_SIZE(fontface->glyphs); i++)
heap_free(fontface->glyphs[i]);
freetype_notify_cacheremove(iface);
font_funcs->notify_release(iface);
dwrite_cmap_release(&fontface->cmap);
IDWriteFactory7_Release(fontface->factory);
@ -743,7 +750,7 @@ static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace5 *iface)
{
TRACE("%p.\n", iface);
return freetype_get_glyphcount(iface);
return font_funcs->get_glyph_count(iface);
}
static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *iface,
@ -765,8 +772,10 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa
DWRITE_GLYPH_METRICS metrics;
hr = get_cached_glyph_metrics(fontface, glyphs[i], &metrics);
if (hr != S_OK) {
freetype_get_design_glyph_metrics(fontface, glyphs[i], &metrics);
if (hr != S_OK)
{
font_funcs->get_design_glyph_metrics(iface, fontface->metrics.designUnitsPerEm,
fontface->typo_metrics.ascent, fontface->simulations, glyphs[i], &metrics);
hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics);
if (FAILED(hr))
return hr;
@ -901,7 +910,7 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface,
for (i = 0; i < count; ++i)
{
outline.tags.count = outline.points.count = 0;
if (freetype_get_glyph_outline(iface, emSize, glyphs[i], &outline))
if (font_funcs->get_glyph_outline(iface, emSize, glyphs[i], &outline))
{
WARN("Failed to get glyph outline for glyph %u.\n", glyphs[i]);
continue;
@ -1049,7 +1058,7 @@ static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFac
if (FAILED(hr))
return hr;
ret->advanceWidth = freetype_get_glyph_advance(iface, size, glyphs[i], mode, &has_contours);
ret->advanceWidth = font_funcs->get_glyph_advance(iface, size, glyphs[i], mode, &has_contours);
if (has_contours)
ret->advanceWidth = round_metric(ret->advanceWidth * fontface->metrics.designUnitsPerEm / size + adjustment);
else
@ -1180,7 +1189,7 @@ static int fontface_get_design_advance(struct dwrite_fontface *fontface, DWRITE_
switch (measuring_mode)
{
case DWRITE_MEASURING_MODE_NATURAL:
advance = freetype_get_glyph_advance(&fontface->IDWriteFontFace5_iface, fontface->metrics.designUnitsPerEm,
advance = font_funcs->get_glyph_advance(&fontface->IDWriteFontFace5_iface, fontface->metrics.designUnitsPerEm,
glyph, measuring_mode, &has_contours);
if (has_contours)
advance += adjustment;
@ -1195,7 +1204,7 @@ static int fontface_get_design_advance(struct dwrite_fontface *fontface, DWRITE_
if (transform && memcmp(transform, &identity, sizeof(*transform)))
FIXME("Transform is not supported.\n");
advance = freetype_get_glyph_advance(&fontface->IDWriteFontFace5_iface, emsize, glyph, measuring_mode,
advance = font_funcs->get_glyph_advance(&fontface->IDWriteFontFace5_iface, emsize, glyph, measuring_mode,
&has_contours);
if (has_contours)
advance = round_metric(advance * fontface->metrics.designUnitsPerEm / emsize + adjustment);
@ -5709,7 +5718,7 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr);
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
glyph_bitmap.fontface = fontface;
glyph_bitmap.key = fontface;
glyph_bitmap.simulations = IDWriteFontFace4_GetSimulations(fontface);
glyph_bitmap.emsize = analysis->run.fontEmSize;
glyph_bitmap.nohint = is_natural_rendering_mode(analysis->rendering_mode);
@ -5721,7 +5730,7 @@ static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis *a
UINT32 bitmap_size;
glyph_bitmap.glyph = analysis->run.glyphIndices[i];
freetype_get_glyph_bbox(&glyph_bitmap);
font_funcs->get_glyph_bbox(&glyph_bitmap);
bitmap_size = get_glyph_bitmap_pitch(analysis->rendering_mode, bbox->right - bbox->left) *
(bbox->bottom - bbox->top);
@ -5799,7 +5808,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
origin.x = origin.y = 0.0f;
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
glyph_bitmap.fontface = fontface;
glyph_bitmap.key = fontface;
glyph_bitmap.simulations = IDWriteFontFace4_GetSimulations(fontface);
glyph_bitmap.emsize = analysis->run.fontEmSize;
glyph_bitmap.nohint = is_natural_rendering_mode(analysis->rendering_mode);
@ -5819,7 +5828,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
BOOL is_1bpp;
glyph_bitmap.glyph = analysis->run.glyphIndices[i];
freetype_get_glyph_bbox(&glyph_bitmap);
font_funcs->get_glyph_bbox(&glyph_bitmap);
if (IsRectEmpty(bbox))
continue;
@ -5829,7 +5838,7 @@ static HRESULT glyphrunanalysis_render(struct dwrite_glyphrunanalysis *analysis)
glyph_bitmap.pitch = get_glyph_bitmap_pitch(analysis->rendering_mode, width);
memset(src, 0, height * glyph_bitmap.pitch);
is_1bpp = freetype_get_glyph_bitmap(&glyph_bitmap);
is_1bpp = font_funcs->get_glyph_bitmap(&glyph_bitmap);
OffsetRect(bbox, analysis->origins[i].x, analysis->origins[i].y);
@ -8030,7 +8039,7 @@ struct font_callback_funcs callback_funcs =
void init_font_backend(void)
{
init_font_lib(dwrite_module, DLL_PROCESS_ATTACH, &callback_funcs, NULL);
init_font_lib(dwrite_module, DLL_PROCESS_ATTACH, &callback_funcs, &font_funcs);
}
void release_font_backend(void)

View file

@ -207,21 +207,22 @@ sym_not_found:
return FALSE;
}
void freetype_notify_cacheremove(IDWriteFontFace5 *fontface)
static void CDECL freetype_notify_release(void *key)
{
EnterCriticalSection(&freetype_cs);
pFTC_Manager_RemoveFaceID(cache_manager, fontface);
pFTC_Manager_RemoveFaceID(cache_manager, key);
LeaveCriticalSection(&freetype_cs);
}
HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
static void CDECL freetype_get_design_glyph_metrics(void *key, UINT16 upem, UINT16 ascent,
unsigned int simulations, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
{
FTC_ScalerRec scaler;
FT_Size size;
scaler.face_id = &fontface->IDWriteFontFace5_iface;
scaler.width = fontface->metrics.designUnitsPerEm;
scaler.height = fontface->metrics.designUnitsPerEm;
scaler.face_id = key;
scaler.width = upem;
scaler.height = upem;
scaler.pixel = 1;
scaler.x_res = 0;
scaler.y_res = 0;
@ -236,22 +237,20 @@ HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT
ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width;
ret->advanceHeight = metrics->vertAdvance;
ret->verticalOriginY = fontface->typo_metrics.ascent;
ret->topSideBearing = fontface->typo_metrics.ascent - metrics->horiBearingY;
ret->verticalOriginY = ascent;
ret->topSideBearing = ascent - metrics->horiBearingY;
ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing;
/* Adjust in case of bold simulation, glyphs without contours are ignored. */
if (fontface->simulations & DWRITE_FONT_SIMULATIONS_BOLD &&
if (simulations & DWRITE_FONT_SIMULATIONS_BOLD &&
size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && size->face->glyph->outline.n_contours)
{
if (ret->advanceWidth)
ret->advanceWidth += (fontface->metrics.designUnitsPerEm + 49) / 50;
ret->advanceWidth += (upem + 49) / 50;
}
}
}
LeaveCriticalSection(&freetype_cs);
return S_OK;
}
struct decompose_context
@ -437,9 +436,9 @@ static void embolden_glyph(FT_Glyph glyph, FLOAT emsize)
embolden_glyph_outline(&outline_glyph->outline, emsize);
}
int freetype_get_glyph_outline(IDWriteFontFace5 *fontface, float emSize, UINT16 glyph,
struct dwrite_outline *outline)
static int CDECL freetype_get_glyph_outline(void *key, float emSize, UINT16 glyph, struct dwrite_outline *outline)
{
IDWriteFontFace5 *fontface = key;
FTC_ScalerRec scaler;
USHORT simulations;
FT_Size size;
@ -480,13 +479,13 @@ int freetype_get_glyph_outline(IDWriteFontFace5 *fontface, float emSize, UINT16
return ret;
}
UINT16 freetype_get_glyphcount(IDWriteFontFace5 *fontface)
static UINT16 CDECL freetype_get_glyph_count(void *key)
{
UINT16 count = 0;
FT_Face face;
EnterCriticalSection(&freetype_cs);
if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0)
if (pFTC_Manager_LookupFace(cache_manager, key, &face) == 0)
count = face->num_glyphs;
LeaveCriticalSection(&freetype_cs);
@ -502,10 +501,10 @@ static inline void ft_matrix_from_dwrite_matrix(const DWRITE_MATRIX *m, FT_Matri
}
/* Should be used only while holding 'freetype_cs' */
static BOOL is_face_scalable(IDWriteFontFace4 *fontface)
static BOOL is_face_scalable(void *key)
{
FT_Face face;
if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0)
if (pFTC_Manager_LookupFace(cache_manager, key, &face) == 0)
return FT_IS_SCALABLE(face);
else
return FALSE;
@ -522,7 +521,7 @@ static BOOL get_glyph_transform(struct dwrite_glyphbitmap *bitmap, FT_Matrix *re
/* Some fonts provide mostly bitmaps and very few outlines, for example for .notdef.
Disable transform if that's the case. */
if (!is_face_scalable(bitmap->fontface) || (!bitmap->m && bitmap->simulations == 0))
if (!is_face_scalable(bitmap->key) || (!bitmap->m && bitmap->simulations == 0))
return FALSE;
if (bitmap->simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
@ -541,7 +540,7 @@ static BOOL get_glyph_transform(struct dwrite_glyphbitmap *bitmap, FT_Matrix *re
return TRUE;
}
void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
static void CDECL freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
{
FTC_ImageTypeRec imagetype;
FT_BBox bbox = { 0 };
@ -553,7 +552,7 @@ void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
needs_transform = get_glyph_transform(bitmap, &m);
imagetype.face_id = bitmap->fontface;
imagetype.face_id = bitmap->key;
imagetype.width = 0;
imagetype.height = bitmap->emsize;
imagetype.flags = needs_transform ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT;
@ -673,7 +672,7 @@ static BOOL freetype_get_aa_glyph_bitmap(struct dwrite_glyphbitmap *bitmap, FT_G
return ret;
}
BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
static BOOL CDECL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
{
FTC_ImageTypeRec imagetype;
BOOL needs_transform;
@ -685,7 +684,7 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
needs_transform = get_glyph_transform(bitmap, &m);
imagetype.face_id = bitmap->fontface;
imagetype.face_id = bitmap->key;
imagetype.width = 0;
imagetype.height = bitmap->emsize;
imagetype.flags = needs_transform ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT;
@ -720,14 +719,14 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
return ret;
}
INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode,
BOOL *has_contours)
static INT32 CDECL freetype_get_glyph_advance(void *key, float emSize, UINT16 index,
DWRITE_MEASURING_MODE mode, BOOL *has_contours)
{
FTC_ImageTypeRec imagetype;
FT_Glyph glyph;
INT32 advance;
imagetype.face_id = fontface;
imagetype.face_id = key;
imagetype.width = 0;
imagetype.height = emSize;
imagetype.flags = FT_LOAD_DEFAULT;
@ -748,10 +747,22 @@ INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emSize, UINT1
return advance;
}
const static struct font_backend_funcs freetype_funcs =
{
freetype_notify_release,
freetype_get_glyph_outline,
freetype_get_glyph_count,
freetype_get_glyph_advance,
freetype_get_glyph_bbox,
freetype_get_glyph_bitmap,
freetype_get_design_glyph_metrics,
};
static NTSTATUS init_freetype_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
{
callback_funcs = ptr_in;
if (!init_freetype()) return STATUS_DLL_NOT_FOUND;
*(const struct font_backend_funcs **)ptr_out = &freetype_funcs;
return STATUS_SUCCESS;
}
@ -764,45 +775,56 @@ static NTSTATUS release_freetype_lib(void)
#else /* HAVE_FREETYPE */
void freetype_notify_cacheremove(IDWriteFontFace5 *fontface)
static void CDECL null_notify_release(void *key)
{
}
HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
{
return E_NOTIMPL;
}
int freetype_get_glyph_outline(IDWriteFontFace5 *fontface, float emSize, UINT16 glyph,
struct dwrite_outline *outline)
static int CDECL null_get_glyph_outline(void *key, float emSize, UINT16 glyph, struct dwrite_outline *outline)
{
return 1;
}
UINT16 freetype_get_glyphcount(IDWriteFontFace5 *fontface)
static UINT16 CDECL null_get_glyph_count(void *key)
{
return 0;
}
void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
{
SetRectEmpty(&bitmap->bbox);
}
BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
{
return FALSE;
}
INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emSize, UINT16 index, DWRITE_MEASURING_MODE mode,
static INT32 CDECL null_get_glyph_advance(void *key, float emSize, UINT16 index, DWRITE_MEASURING_MODE mode,
BOOL *has_contours)
{
*has_contours = FALSE;
return 0;
}
static void CDECL null_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap)
{
SetRectEmpty(&bitmap->bbox);
}
static BOOL CDECL null_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
{
return FALSE;
}
static void CDECL null_get_design_glyph_metrics(void *key, UINT16 upem, UINT16 ascent, unsigned int simulations,
UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
{
}
const static struct font_backend_funcs null_funcs =
{
null_notify_release,
null_get_glyph_outline,
null_get_glyph_count,
null_get_glyph_advance,
null_get_glyph_bbox,
null_get_glyph_bitmap,
null_get_design_glyph_metrics,
};
static NTSTATUS init_freetype_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
{
*(const struct font_backend_funcs **)ptr_out = &null_funcs;
return STATUS_DLL_NOT_FOUND;
}

View file

@ -3936,7 +3936,7 @@ static void layout_get_erun_bbox(struct dwrite_textlayout *layout, struct layout
RECT *bbox;
memset(&glyph_bitmap, 0, sizeof(glyph_bitmap));
glyph_bitmap.fontface = (IDWriteFontFace4 *)glyph_run->fontFace;
glyph_bitmap.key = glyph_run->fontFace;
glyph_bitmap.simulations = IDWriteFontFace_GetSimulations(glyph_run->fontFace);
glyph_bitmap.emsize = glyph_run->fontEmSize;
glyph_bitmap.nohint = layout->measuringmode == DWRITE_MEASURING_MODE_NATURAL;
@ -3952,7 +3952,7 @@ static void layout_get_erun_bbox(struct dwrite_textlayout *layout, struct layout
origin.x -= glyph_run->glyphAdvances[i + start_glyph];
glyph_bitmap.glyph = glyph_run->glyphIndices[i + start_glyph];
freetype_get_glyph_bbox(&glyph_bitmap);
dwrite_fontface_get_glyph_bbox(&glyph_bitmap);
glyph_bbox.left = bbox->left;
glyph_bbox.top = bbox->top;