dwrite: Use current layout fallback when creating run font faces.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-02-14 19:05:10 +03:00 committed by Alexandre Julliard
parent 5d17404287
commit 7fc7f2f074
3 changed files with 91 additions and 40 deletions

View File

@ -1745,7 +1745,7 @@ static const struct fallback_mapping *find_fallback_mapping(struct dwrite_fontfa
return NULL;
}
static HRESULT create_matching_font(IDWriteFontCollection *collection, const WCHAR *name,
HRESULT create_matching_font(IDWriteFontCollection *collection, const WCHAR *name,
DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, IDWriteFont **font)
{
IDWriteFontFamily *family;

View File

@ -145,6 +145,8 @@ extern HRESULT create_colorglyphenum(FLOAT,FLOAT,const DWRITE_GLYPH_RUN*,const D
extern BOOL lb_is_newline_char(WCHAR) DECLSPEC_HIDDEN;
extern HRESULT create_system_fontfallback(IDWriteFactory2*,IDWriteFontFallback**) DECLSPEC_HIDDEN;
extern void release_system_fontfallback(IDWriteFontFallback*) DECLSPEC_HIDDEN;
extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
IDWriteFont**) DECLSPEC_HIDDEN;
/* Opentype font table functions */
struct dwrite_font_props {

View File

@ -696,39 +696,6 @@ static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const s
#define SCALE_FONT_METRIC(metric, emSize, metrics) ((FLOAT)(metric) * (emSize) / (FLOAT)(metrics)->designUnitsPerEm)
static HRESULT create_fontface_by_pos(struct dwrite_textlayout *layout, struct layout_range *range, IDWriteFontFace **fontface)
{
static DWRITE_GLYPH_RUN_DESCRIPTION descr = { 0 };
IDWriteFontFamily *family;
BOOL exists = FALSE;
IDWriteFont *font;
UINT32 index;
HRESULT hr;
*fontface = NULL;
hr = IDWriteFontCollection_FindFamilyName(range->collection, range->fontfamily, &index, &exists);
if (FAILED(hr) || !exists) {
WARN("%s: family %s not found in collection %p\n", debugstr_rundescr(&descr), debugstr_w(range->fontfamily), range->collection);
return hr;
}
hr = IDWriteFontCollection_GetFontFamily(range->collection, index, &family);
if (FAILED(hr))
return hr;
hr = IDWriteFontFamily_GetFirstMatchingFont(family, range->weight, range->stretch, range->style, &font);
IDWriteFontFamily_Release(family);
if (FAILED(hr)) {
WARN("%s: failed to get a matching font\n", debugstr_rundescr(&descr));
return hr;
}
hr = IDWriteFont_CreateFontFace(font, fontface);
IDWriteFont_Release(font);
return hr;
}
static void layout_get_font_metrics(struct dwrite_textlayout *layout, IDWriteFontFace *fontface, FLOAT emsize,
DWRITE_FONT_METRICS *fontmetrics)
{
@ -749,6 +716,7 @@ static void layout_get_font_height(FLOAT emsize, DWRITE_FONT_METRICS *fontmetric
static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
{
IDWriteFontFallback *fallback;
IDWriteTextAnalyzer *analyzer;
struct layout_range *range;
struct layout_run *r;
@ -808,6 +776,82 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
break;
}
if (layout->format.fallback) {
fallback = layout->format.fallback;
IDWriteFontFallback_AddRef(fallback);
}
else {
hr = IDWriteFactory2_GetSystemFontFallback(layout->factory, &fallback);
if (FAILED(hr))
return hr;
}
/* resolve run fonts */
LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
struct regular_layout_run *run = &r->u.regular;
UINT32 length;
if (r->kind == LAYOUT_RUN_INLINE)
continue;
range = get_layout_range_by_pos(layout, run->descr.textPosition);
length = run->descr.stringLength;
while (length) {
UINT32 mapped_length;
IDWriteFont *font;
FLOAT scale;
run = &r->u.regular;
hr = IDWriteFontFallback_MapCharacters(fallback,
(IDWriteTextAnalysisSource*)&layout->IDWriteTextAnalysisSource1_iface,
run->descr.textPosition,
run->descr.stringLength,
range->collection,
range->fontfamily,
range->weight,
range->style,
range->stretch,
&mapped_length,
&font,
&scale);
if (FAILED(hr)) {
WARN("%s: failed to map family %s, collection %p\n", debugstr_rundescr(&run->descr), debugstr_w(range->fontfamily), range->collection);
return hr;
}
hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
IDWriteFont_Release(font);
if (FAILED(hr))
return hr;
run->run.fontEmSize = range->fontsize * scale;
if (mapped_length < length) {
struct regular_layout_run *nextrun = &r->u.regular;
struct layout_run *nextr;
/* keep mapped part for current run, add another run for the rest */
nextr = alloc_layout_run(LAYOUT_RUN_REGULAR);
if (!nextr)
return E_OUTOFMEMORY;
*nextr = *r;
nextrun = &nextr->u.regular;
nextrun->descr.textPosition = run->descr.textPosition + mapped_length;
nextrun->descr.stringLength = run->descr.stringLength - mapped_length;
nextrun->descr.string = &layout->str[nextrun->descr.textPosition];
run->descr.stringLength = mapped_length;
list_add_after(&r->entry, &nextr->entry);
r = nextr;
}
length -= mapped_length;
}
}
IDWriteFontFallback_Release(fallback);
/* fill run info */
LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props = NULL;
@ -850,11 +894,6 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
}
range = get_layout_range_by_pos(layout, run->descr.textPosition);
hr = create_fontface_by_pos(layout, range, &run->run.fontFace);
if (FAILED(hr))
continue;
run->run.fontEmSize = range->fontsize;
run->descr.localeName = range->locale;
run->clustermap = heap_alloc(run->descr.stringLength*sizeof(UINT16));
@ -1606,10 +1645,20 @@ static HRESULT layout_set_dummy_line_metrics(struct dwrite_textlayout *layout, U
DWRITE_LINE_METRICS metrics;
struct layout_range *range;
IDWriteFontFace *fontface;
IDWriteFont *font;
HRESULT hr;
range = get_layout_range_by_pos(layout, pos);
hr = create_fontface_by_pos(layout, range, &fontface);
hr = create_matching_font(range->collection,
range->fontfamily,
range->weight,
range->style,
range->stretch,
&font);
if (FAILED(hr))
return hr;
hr = IDWriteFont_CreateFontFace(font, &fontface);
IDWriteFont_Release(font);
if (FAILED(hr))
return hr;