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

dwrite/layout: Use same logic for mapping both non-visual and visual runs.

Both non-visual and visual runs go through fallback mapping process, and could end up with hard coded default at the end if fallback was insufficient. Visual runs are using custom fallback and then the system one, non-visual ones are using only system fallback. Signed-off-by: 's avatarNikolay Sivov <nsivov@codeweavers.com>
parent 4f90e88d
......@@ -641,110 +641,52 @@ static HRESULT layout_itemize(struct dwrite_textlayout *layout)
return hr;
}
static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
static HRESULT layout_map_run_characters(struct dwrite_textlayout *layout, struct layout_run *r,
IDWriteFontCollection *system_collection, IDWriteFontFallback *fallback, struct layout_run **remaining)
{
IDWriteFontCollection *sys_collection, *collection;
IDWriteFontFallback *fallback = NULL;
struct layout_range *range;
struct layout_run *r;
HRESULT hr;
if (FAILED(hr = IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)layout->factory, FALSE,
(IDWriteFontCollection1 **)&sys_collection, FALSE))) {
WARN("Failed to get system collection, hr %#lx.\n", hr);
return hr;
}
if (layout->format.fallback) {
fallback = layout->format.fallback;
IDWriteFontFallback_AddRef(fallback);
}
else {
if (FAILED(hr = IDWriteFactory7_GetSystemFontFallback(layout->factory, &fallback))) {
WARN("Failed to get system fallback, hr %#lx.\n", hr);
goto fatal;
}
}
LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry) {
struct regular_layout_run *run = &r->u.regular;
IDWriteFont *font;
UINT32 length;
IDWriteFontCollection *collection;
struct layout_range *range;
unsigned int length;
HRESULT hr = S_OK;
if (r->kind == LAYOUT_RUN_INLINE)
continue;
*remaining = NULL;
range = get_layout_range_by_pos(layout, run->descr.textPosition);
collection = range->collection ? range->collection : sys_collection;
if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL)
{
if (FAILED(hr = create_matching_font(collection, range->fontfamily, range->weight, range->style,
range->stretch, &IID_IDWriteFont, (void **)&font)))
{
WARN("%s: failed to create matching font for non visual run, family %s, collection %p\n",
debugstr_rundescr(&run->descr), debugstr_w(range->fontfamily), range->collection);
break;
}
hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
IDWriteFont_Release(font);
if (FAILED(hr)) {
WARN("Failed to create font face, hr %#lx.\n", hr);
break;
}
run->run.fontEmSize = range->fontsize;
continue;
}
collection = range->collection ? range->collection : system_collection;
length = run->descr.stringLength;
while (length)
{
UINT32 mapped_length = 0;
FLOAT scale;
unsigned int mapped_length = 0;
IDWriteFont *font = NULL;
float scale = 0.0f;
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)) {
hr = IDWriteFontFallback_MapCharacters(fallback, (IDWriteTextAnalysisSource *)&layout->IDWriteTextAnalysisSource1_iface,
run->descr.textPosition, run->descr.stringLength, 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, hr %#lx.\n", debugstr_rundescr(&run->descr),
debugstr_w(range->fontfamily), range->collection, hr);
goto fatal;
debugstr_w(range->fontfamily), collection, hr);
return hr;
}
if (!font)
{
if (FAILED(create_matching_font(range->collection, range->fontfamily, range->weight, range->style,
range->stretch, &IID_IDWriteFont3, (void **)&font)))
{
if (FAILED(hr = create_matching_font(sys_collection, L"Tahoma", range->weight, range->style,
range->stretch, &IID_IDWriteFont3, (void **)&font)))
{
WARN("Failed to create last resort font, hr %#lx.\n", hr);
goto fatal;
}
}
mapped_length = run->descr.stringLength;
*remaining = r;
return S_OK;
}
hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
IDWriteFont_Release(font);
if (FAILED(hr)) {
WARN("Failed to create font face, hr %#lx.\n", hr);
goto fatal;
if (FAILED(hr))
{
WARN("Failed to create a font face, hr %#lx.\n", hr);
return hr;
}
run->run.fontEmSize = range->fontsize * scale;
......@@ -754,13 +696,14 @@ static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
struct regular_layout_run *nextrun;
struct layout_run *nextr;
/* keep mapped part for current run, add another run for the rest */
/* Keep mapped part for current run, add another run for the rest. */
if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, 0, &nextr)))
goto fatal;
return hr;
*nextr = *r;
nextr->start_position = run->descr.textPosition + mapped_length;
nextrun = &nextr->u.regular;
nextrun->run.fontFace = NULL;
nextrun->descr.textPosition = nextr->start_position;
nextrun->descr.stringLength = run->descr.stringLength - mapped_length;
nextrun->descr.string = &layout->str[nextrun->descr.textPosition];
......@@ -769,14 +712,105 @@ static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
r = nextr;
}
length -= mapped_length;
length -= min(length, mapped_length);
}
return hr;
}
static HRESULT layout_run_set_last_resort_font(struct dwrite_textlayout *layout, struct layout_run *r,
IDWriteFontCollection *system_collection)
{
struct regular_layout_run *run = &r->u.regular;
struct layout_range *range;
IDWriteFont *font;
HRESULT hr;
range = get_layout_range_by_pos(layout, run->descr.textPosition);
if (FAILED(create_matching_font(range->collection, range->fontfamily, range->weight, range->style,
range->stretch, &IID_IDWriteFont3, (void **)&font)))
{
if (FAILED(hr = create_matching_font(system_collection, L"Tahoma", range->weight, range->style,
range->stretch, &IID_IDWriteFont3, (void **)&font)))
{
WARN("Failed to create last resort font, hr %#lx.\n", hr);
return hr;
}
}
hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
IDWriteFont_Release(font);
if (FAILED(hr))
{
WARN("Failed to create last resort font face, hr %#lx.\n", hr);
return hr;
}
run->run.fontEmSize = range->fontsize;
return hr;
}
static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
{
IDWriteFontCollection *system_collection;
IDWriteFontFallback *system_fallback;
struct layout_run *r, *remaining;
HRESULT hr;
if (FAILED(hr = IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)layout->factory, FALSE,
(IDWriteFontCollection1 **)&system_collection, FALSE)))
{
WARN("Failed to get system collection, hr %#lx.\n", hr);
return hr;
}
if (FAILED(hr = IDWriteFactory7_GetSystemFontFallback(layout->factory, &system_fallback)))
{
WARN("Failed to get system fallback, hr %#lx.\n", hr);
IDWriteFontCollection_Release(system_collection);
return hr;
}
LIST_FOR_EACH_ENTRY(r, &layout->runs, struct layout_run, entry)
{
struct regular_layout_run *run = &r->u.regular;
if (r->kind == LAYOUT_RUN_INLINE)
continue;
/* For textual runs use both custom and system fallback. For non-visual ones only use the system fallback,
and no hard-coded names in assumption that support for missing control characters could be easily
added to bundled fonts. */
if (run->sa.shapes == DWRITE_SCRIPT_SHAPES_NO_VISUAL)
{
if (FAILED(hr = layout_map_run_characters(layout, r, system_collection, system_fallback, &remaining)))
{
WARN("Failed to map fonts for non-visual run, hr %#lx.\n", hr);
break;
}
}
else
{
if (layout->format.fallback)
hr = layout_map_run_characters(layout, r, system_collection, layout->format.fallback, &remaining);
else
remaining = r;
if (remaining)
hr = layout_map_run_characters(layout, remaining, system_collection, system_fallback, &remaining);
}
if (remaining)
hr = layout_run_set_last_resort_font(layout, remaining, system_collection);
if (FAILED(hr)) break;
}
fatal:
IDWriteFontCollection_Release(sys_collection);
if (fallback)
IDWriteFontFallback_Release(fallback);
IDWriteFontCollection_Release(system_collection);
IDWriteFontFallback_Release(system_fallback);
return hr;
}
......
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