dwrite: Implement AddMapping().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2017-09-22 15:34:52 +03:00 committed by Alexandre Julliard
parent e1a41faf76
commit 8dc81ed2a4
2 changed files with 121 additions and 30 deletions

View File

@ -196,15 +196,33 @@ const char *debugstr_sa_script(UINT16 script)
/* system font falback configuration */
static const WCHAR meiryoW[] = {'M','e','i','r','y','o',0};
static const WCHAR *cjk_families[] = { meiryoW };
static const DWRITE_UNICODE_RANGE cjk_ranges[] =
{
{ 0x3000, 0x30ff }, /* CJK Symbols and Punctuation, Hiragana, Katakana */
{ 0x31f0, 0x31ff }, /* Katakana Phonetic Extensions */
{ 0x4e00, 0x9fff }, /* CJK Unified Ideographs */
};
struct fallback_mapping {
DWRITE_UNICODE_RANGE range;
const WCHAR *families[5];
DWRITE_UNICODE_RANGE *ranges;
UINT32 ranges_count;
WCHAR **families;
UINT32 families_count;
IDWriteFontCollection *collection;
WCHAR *locale;
FLOAT scale;
};
static const struct fallback_mapping fontfallback_neutral_data[] = {
{ { 0x3000, 0x30ff }, { meiryoW } }, /* CJK Symbols and Punctuation, Hiragana, Katakana */
{ { 0x31f0, 0x31ff }, { meiryoW } }, /* Katakana Phonetic Extensions */
{ { 0x4e00, 0x9fff }, { meiryoW } }, /* CJK Unified Ideographs */
#define MAPPING_RANGE(ranges, families) \
{ (DWRITE_UNICODE_RANGE *)ranges, sizeof(ranges)/sizeof(ranges[0]), \
(WCHAR **)families, sizeof(families)/sizeof(families[0]) }
MAPPING_RANGE(cjk_ranges, cjk_families),
#undef MAPPING_RANGE
};
struct dwrite_fontfallback {
@ -212,14 +230,17 @@ struct dwrite_fontfallback {
LONG ref;
IDWriteFactory5 *factory;
IDWriteFontCollection1 *systemcollection;
const struct fallback_mapping *mappings;
UINT32 count;
struct fallback_mapping *mappings;
UINT32 mappings_count;
};
struct dwrite_fontfallback_builder {
IDWriteFontFallbackBuilder IDWriteFontFallbackBuilder_iface;
LONG ref;
IDWriteFactory5 *factory;
struct fallback_mapping *mappings;
UINT32 mappings_count;
UINT32 mappings_capacity;
};
struct dwrite_numbersubstitution {
@ -1972,14 +1993,14 @@ static ULONG WINAPI fontfallback_Release(IDWriteFontFallback *iface)
return IDWriteFactory5_Release(fallback->factory);
}
static int compare_fallback_mapping(const void *a, const void *b)
static int compare_mapping_range(const void *a, const void *b)
{
UINT32 ch = *(UINT32*)a;
struct fallback_mapping *mapping = (struct fallback_mapping*)b;
UINT32 ch = *(UINT32 *)a;
DWRITE_UNICODE_RANGE *range = (DWRITE_UNICODE_RANGE *)b;
if (ch > mapping->range.last)
if (ch > range->last)
return 1;
else if (ch < mapping->range.first)
else if (ch < range->first)
return -1;
else
return 0;
@ -1987,8 +2008,17 @@ static int compare_fallback_mapping(const void *a, const void *b)
static const struct fallback_mapping *find_fallback_mapping(struct dwrite_fontfallback *fallback, UINT32 ch)
{
return bsearch(&ch, fallback->mappings, fallback->count, sizeof(*fallback->mappings),
compare_fallback_mapping);
UINT32 i;
for (i = 0; i < fallback->mappings_count; i++) {
struct fallback_mapping *mapping = &fallback->mappings[i];
if (bsearch(&ch, mapping->ranges, mapping->ranges_count, sizeof(*mapping->ranges),
compare_mapping_range) != NULL)
return mapping;
}
return NULL;
}
HRESULT create_matching_font(IDWriteFontCollection *collection, const WCHAR *name,
@ -2048,8 +2078,8 @@ static HRESULT fallback_get_fallback_font(struct dwrite_fontfallback *fallback,
IDWriteFont **mapped_font)
{
const struct fallback_mapping *mapping;
UINT32 i = 0;
HRESULT hr;
UINT32 i;
*mapped_font = NULL;
@ -2060,19 +2090,17 @@ static HRESULT fallback_get_fallback_font(struct dwrite_fontfallback *fallback,
}
/* Now let's see what fallback can handle. Pick first font that could be created. */
while (mapping->families[i]) {
for (i = 0; i < mapping->families_count; i++) {
hr = create_matching_font((IDWriteFontCollection *)fallback->systemcollection, mapping->families[i],
weight, style, stretch, mapped_font);
if (hr == S_OK) {
TRACE("Created fallback font for range [%#x, %#x], using family %s.\n", mapping->range.first,
mapping->range.last, debugstr_w(mapping->families[i]));
TRACE("Created fallback font using family %s.\n", debugstr_w(mapping->families[i]));
break;
}
i++;
}
if (!*mapped_font) {
WARN("Failed to create fallback font for range [%#x, %#x].\n", mapping->range.first, mapping->range.last);
WARN("Failed to create fallback font.\n");
return E_FAIL;
}
@ -2170,8 +2198,8 @@ HRESULT create_system_fontfallback(IDWriteFactory5 *factory, IDWriteFontFallback
fallback->IDWriteFontFallback_iface.lpVtbl = &fontfallbackvtbl;
fallback->factory = factory;
fallback->mappings = fontfallback_neutral_data;
fallback->count = sizeof(fontfallback_neutral_data)/sizeof(fontfallback_neutral_data[0]);
fallback->mappings = (struct fallback_mapping *)fontfallback_neutral_data;
fallback->mappings_count = sizeof(fontfallback_neutral_data) / sizeof(*fontfallback_neutral_data);
IDWriteFactory5_GetSystemFontCollection(fallback->factory, FALSE, &fallback->systemcollection, FALSE);
*ret = &fallback->IDWriteFontFallback_iface;
@ -2263,6 +2291,23 @@ static ULONG WINAPI fontfallbackbuilder_Release(IDWriteFontFallbackBuilder *ifac
TRACE("(%p)->(%d)\n", fallbackbuilder, ref);
if (!ref) {
UINT32 i;
for (i = 0; i < fallbackbuilder->mappings_count; i++) {
struct fallback_mapping *mapping = &fallbackbuilder->mappings[i];
UINT32 j;
for (j = 0; j < mapping->families_count; j++)
heap_free(mapping->families[i]);
heap_free(mapping->families);
if (mapping->collection)
IDWriteFontCollection_Release(mapping->collection);
heap_free(mapping->ranges);
heap_free(mapping->locale);
heap_free(mapping);
}
IDWriteFactory5_Release(fallbackbuilder->factory);
heap_free(fallbackbuilder);
}
@ -2275,11 +2320,52 @@ static HRESULT WINAPI fontfallbackbuilder_AddMapping(IDWriteFontFallbackBuilder
IDWriteFontCollection *collection, WCHAR const *locale, WCHAR const *base_family, FLOAT scale)
{
struct dwrite_fontfallback_builder *fallbackbuilder = impl_from_IDWriteFontFallbackBuilder(iface);
struct fallback_mapping *mapping;
UINT32 i;
FIXME("(%p)->(%p, %u, %p, %u, %p, %s, %s, %f): stub\n", fallbackbuilder, ranges, ranges_count, target_families,
TRACE("(%p)->(%p, %u, %p, %u, %p, %s, %s, %f)\n", fallbackbuilder, ranges, ranges_count, target_families,
families_count, collection, debugstr_w(locale), debugstr_w(base_family), scale);
return E_NOTIMPL;
if (!ranges || ranges_count == 0 || !target_families || families_count == 0 || scale < 0.0f)
return E_INVALIDARG;
if (base_family)
FIXME("base family ignored.\n");
if (fallbackbuilder->mappings_count == fallbackbuilder->mappings_capacity) {
struct fallback_mapping *mappings;
if (fallbackbuilder->mappings_capacity == 0) {
if ((mappings = heap_alloc(sizeof(*fallbackbuilder->mappings) * 16)))
fallbackbuilder->mappings_capacity = 16;
}
else {
if ((mappings = heap_realloc(fallbackbuilder->mappings, sizeof(*fallbackbuilder->mappings) *
fallbackbuilder->mappings_capacity * 2)))
fallbackbuilder->mappings_capacity *= 2;
}
if (!mappings)
return E_OUTOFMEMORY;
fallbackbuilder->mappings = mappings;
}
mapping = &fallbackbuilder->mappings[fallbackbuilder->mappings_count++];
mapping->ranges = heap_alloc(sizeof(*mapping->ranges) * ranges_count);
memcpy(mapping->ranges, ranges, sizeof(*mapping->ranges) * ranges_count);
mapping->ranges_count = ranges_count;
mapping->families = heap_alloc_zero(sizeof(*mapping->families) * families_count);
mapping->families_count = families_count;
for (i = 0; i < families_count; i++)
mapping->families[i] = heap_strdupW(target_families[i]);
mapping->collection = collection;
if (mapping->collection)
IDWriteFontCollection_AddRef(mapping->collection);
mapping->locale = heap_strdupW(locale);
mapping->scale = scale;
return S_OK;
}
static HRESULT WINAPI fontfallbackbuilder_AddMappings(IDWriteFontFallbackBuilder *iface, IDWriteFontFallback *fallback)
@ -2330,7 +2416,7 @@ HRESULT create_fontfallback_builder(IDWriteFactory5 *factory, IDWriteFontFallbac
*ret = NULL;
builder = heap_alloc(sizeof(*builder));
builder = heap_alloc_zero(sizeof(*builder));
if (!builder)
return E_OUTOFMEMORY;

View File

@ -4702,7 +4702,6 @@ static void test_FontFallbackBuilder(void)
ok(fallback != fallback2, "Unexpected fallback instance.\n");
IDWriteFontFallback_Release(fallback2);
todo_wine {
hr = IDWriteFontFallbackBuilder_AddMapping(builder, NULL, 0, NULL, 0, NULL, NULL, NULL, 0.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
@ -4714,12 +4713,21 @@ todo_wine {
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 0, NULL, 0, NULL, NULL, NULL, 1.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 0, &familyW, 1, NULL, NULL, NULL, 1.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteFontFallbackBuilder_AddMapping(builder, NULL, 0, &familyW, 1, NULL, NULL, NULL, 1.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
/* negative scaling factor */
range.first = range.last = 0;
familyW = g_blahfontW;
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, -1.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 0.0f);
ok(hr == S_OK, "Unexected hr %#x.\n", hr);
/* empty range */
range.first = range.last = 0;
familyW = g_blahfontW;
@ -4738,7 +4746,7 @@ todo_wine {
range.last = 'A';
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, NULL, NULL, NULL, 4.0f);
ok(hr == S_OK, "got 0x%08x\n", hr);
}
IDWriteFontFallback_Release(fallback);
if (0) /* crashes on native */
@ -4765,7 +4773,6 @@ todo_wine {
/* remap with custom collection */
range.first = range.last = 'A';
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, &fallbackcollection, NULL, NULL, 5.0f);
todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
@ -4791,7 +4798,6 @@ todo_wine {
range.first = 'B';
range.last = 'A';
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, &fallbackcollection, NULL, NULL, 6.0f);
todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);
@ -4818,7 +4824,6 @@ todo_wine {
range.first = 'A';
range.last = 'B';
hr = IDWriteFontFallbackBuilder_AddMapping(builder, &range, 1, &familyW, 1, &fallbackcollection, localeW, NULL, 6.0f);
todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFontFallbackBuilder_CreateFontFallback(builder, &fallback);