Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/font.c | 6 +- dlls/dwrite/main.c | 11 ++- dlls/dwrite/opentype.c | 149 +++++++++++++++++++++++++++++++++-- 4 files changed, 152 insertions(+), 16 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 6adba28280..e5ca5306c2 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -231,7 +231,7 @@ struct dwrite_fontface FONTSIGNATURE fontsig; UINT32 glyph_image_formats;
- IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME + 1]; + IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG + 1]; IDWriteLocalizedStrings *family_names; IDWriteLocalizedStrings *names;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 8bcbe11fcb..847070816b 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -82,7 +82,7 @@ struct dwrite_font_data struct dwrite_font_propvec propvec;
DWRITE_FONT_METRICS1 metrics; - IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME + 1]; + IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG + 1]; IDWriteLocalizedStrings *family_names; IDWriteLocalizedStrings *names;
@@ -1291,8 +1291,8 @@ static HRESULT get_font_info_strings(const struct file_stream_desc *stream_desc, *exists = FALSE; *ret = NULL;
- if (stringid > DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME - || stringid == DWRITE_INFORMATIONAL_STRING_NONE) + if (stringid > DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG + || stringid <= DWRITE_INFORMATIONAL_STRING_NONE) { return S_OK; } diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 283cccb76c..b940d0d801 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -446,10 +446,13 @@ HRESULT add_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *locale, struct localizedstrings *strings = impl_from_IDWriteLocalizedStrings(iface); size_t i, count = strings->count;
- /* make sure there's no duplicates */ - for (i = 0; i < count; i++) - if (!strcmpW(strings->data[i].locale, locale)) - return S_OK; + /* Make sure there's no duplicates, unless it's empty. This is used by dlng/slng entries of 'meta' table. */ + if (*locale) + { + for (i = 0; i < count; i++) + if (!strcmpW(strings->data[i].locale, locale)) + return S_OK; + }
if (!dwrite_array_reserve((void **)&strings->data, &strings->size, strings->count + 1, sizeof(*strings->data))) return E_OUTOFMEMORY; diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index fd420e4360..23d7669eb6 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -46,6 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p') #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C') #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p') +#define MS_META_TAG DWRITE_MAKE_OPENTYPE_TAG('m','e','t','a')
/* 'sbix' formats */ #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ') @@ -55,6 +56,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); #define MS_WOFF_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','F') #define MS_WOF2_TAG DWRITE_MAKE_OPENTYPE_TAG('w','O','F','2')
+/* 'meta' tags */ +#define MS_DLNG_TAG DWRITE_MAKE_OPENTYPE_TAG('d','l','n','g') +#define MS_SLNG_TAG DWRITE_MAKE_OPENTYPE_TAG('s','l','n','g') + #ifdef WORDS_BIGENDIAN #define GET_BE_WORD(x) (x) #define GET_BE_DWORD(x) (x) @@ -1164,6 +1169,22 @@ struct colr_layer_record USHORT palette_index; };
+struct meta_data_map +{ + DWORD tag; + DWORD offset; + DWORD length; +}; + +struct meta_header +{ + DWORD version; + DWORD flags; + DWORD reserved; + DWORD data_maps_count; + struct meta_data_map maps[1]; +}; + static const void *table_read_ensure(const struct dwrite_fonttable *table, unsigned int offset, unsigned int size) { if (size > table->size || offset > table->size - size) @@ -2109,23 +2130,135 @@ static HRESULT opentype_get_font_strings_from_id(const void *table_data, enum OP return exists ? S_OK : E_FAIL; }
-/* Provides a conversion from DWRITE to OpenType name ids, input id should be valid, it's not checked. */ -HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_desc, DWRITE_INFORMATIONAL_STRING_ID id, - IDWriteLocalizedStrings **strings) +static WCHAR *meta_get_lng_name(WCHAR *str, WCHAR **ctx) { - struct dwrite_fonttable name; + static const WCHAR delimW[] = {',',' ',0}; + WCHAR *ret; + + if (!str) str = *ctx; + while (*str && strchrW(delimW, *str)) str++; + if (!*str) return NULL; + ret = str++; + while (*str && !strchrW(delimW, *str)) str++; + if (*str) *str++ = 0; + *ctx = str; + + return ret; +} + +static HRESULT opentype_get_font_strings_from_meta(const struct file_stream_desc *stream_desc, + DWRITE_INFORMATIONAL_STRING_ID id, IDWriteLocalizedStrings **ret) +{ + static const WCHAR emptyW[] = { 0 }; + const struct meta_data_map *maps; + IDWriteLocalizedStrings *strings; + struct dwrite_fonttable meta; + DWORD version, i, count, tag; HRESULT hr;
- opentype_get_font_table(stream_desc, MS_NAME_TAG, &name); + *ret = NULL;
- hr = opentype_get_font_strings_from_id(name.data, dwriteid_to_opentypeid[id], strings); + hr = create_localizedstrings(&strings); + if (FAILED(hr)) + return hr;
- if (name.context) - IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context); + switch (id) + { + case DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG: + tag = MS_DLNG_TAG; + break; + case DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG: + tag = MS_SLNG_TAG; + break; + default: + WARN("Unexpected id %d.\n", id); + return S_OK; + } + + opentype_get_font_table(stream_desc, MS_META_TAG, &meta); + + if (meta.data) + { + version = table_read_be_dword(&meta, 0); + if (version != 1) + { + WARN("Unexpected meta table version %d.\n", version); + goto end; + } + + count = table_read_be_dword(&meta, FIELD_OFFSET(struct meta_header, data_maps_count)); + if (!(maps = table_read_ensure(&meta, FIELD_OFFSET(struct meta_header, maps), + count * sizeof(struct meta_data_map)))) + goto end; + + for (i = 0; i < count; ++i) + { + const char *data; + + if (maps[i].tag == tag && maps[i].length) + { + DWORD length = GET_BE_DWORD(maps[i].length), j; + + if ((data = table_read_ensure(&meta, GET_BE_DWORD(maps[i].offset), length))) + { + WCHAR *ptrW = heap_alloc((length + 1) * sizeof(WCHAR)), *ctx, *token; + + if (!ptrW) + { + hr = E_OUTOFMEMORY; + goto end; + } + + /* Data is stored in comma separated list, ASCII range only. */ + for (j = 0; j < length; ++j) + ptrW[j] = data[j]; + ptrW[length] = 0; + + token = meta_get_lng_name(ptrW, &ctx); + + while (token) + { + add_localizedstring(strings, emptyW, token); + token = meta_get_lng_name(NULL, &ctx); + } + + heap_free(ptrW); + } + } + } +end: + IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, meta.context); + } + + if (IDWriteLocalizedStrings_GetCount(strings)) + *ret = strings; + else + IDWriteLocalizedStrings_Release(strings);
return hr; }
+HRESULT opentype_get_font_info_strings(const struct file_stream_desc *stream_desc, DWRITE_INFORMATIONAL_STRING_ID id, + IDWriteLocalizedStrings **strings) +{ + struct dwrite_fonttable name; + + switch (id) + { + case DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG: + case DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG: + opentype_get_font_strings_from_meta(stream_desc, id, strings); + break; + default: + opentype_get_font_table(stream_desc, MS_NAME_TAG, &name); + opentype_get_font_strings_from_id(name.data, dwriteid_to_opentypeid[id], strings); + if (name.context) + IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, name.context); + } + + return S_OK; +} + /* FamilyName locating order is WWS Family Name -> Preferred Family Name -> Family Name. If font claims to have 'Preferred Family Name' in WWS format, then WWS name is not used. */ HRESULT opentype_get_font_familyname(struct file_stream_desc *stream_desc, IDWriteLocalizedStrings **names)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/font.c | 63 ++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 27 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 847070816b..a3af30afe5 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -295,6 +295,8 @@ static inline struct dwrite_font *impl_from_IDWriteFont3(IDWriteFont3 *iface) return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont3_iface); }
+static struct dwrite_font *unsafe_impl_from_IDWriteFont(IDWriteFont *iface); + static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface) { return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface); @@ -467,6 +469,29 @@ void fontface_detach_from_cache(IDWriteFontFace5 *iface) fontface->cached = NULL; }
+static BOOL is_same_fontfile(IDWriteFontFile *left, IDWriteFontFile *right) +{ + UINT32 left_key_size, right_key_size; + const void *left_key, *right_key; + HRESULT hr; + + if (left == right) + return TRUE; + + hr = IDWriteFontFile_GetReferenceKey(left, &left_key, &left_key_size); + if (FAILED(hr)) + return FALSE; + + hr = IDWriteFontFile_GetReferenceKey(right, &right_key, &right_key_size); + if (FAILED(hr)) + return FALSE; + + if (left_key_size != right_key_size) + return FALSE; + + return !memcmp(left_key, right_key, left_key_size); +} + static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace5 *iface, REFIID riid, void **obj) { struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); @@ -1814,11 +1839,18 @@ static HRESULT WINAPI dwritefont3_CreateFontFace(IDWriteFont3 *iface, IDWriteFon return get_fontface_from_font(font, (IDWriteFontFace5 **)fontface); }
-static BOOL WINAPI dwritefont3_Equals(IDWriteFont3 *iface, IDWriteFont *font) +static BOOL WINAPI dwritefont3_Equals(IDWriteFont3 *iface, IDWriteFont *other) { - struct dwrite_font *This = impl_from_IDWriteFont3(iface); - FIXME("(%p)->(%p): stub\n", This, font); - return FALSE; + struct dwrite_font *font = impl_from_IDWriteFont3(iface), *other_font; + + TRACE("%p, %p.\n", iface, other); + + if (!(other_font = unsafe_impl_from_IDWriteFont(other))) + return FALSE; + + return font->data->face_index == other_font->data->face_index + && font->data->simulations == other_font->data->simulations + && is_same_fontfile(font->data->file, other_font->data->file); }
static HRESULT WINAPI dwritefont3_GetFontFaceReference(IDWriteFont3 *iface, IDWriteFontFaceReference **reference) @@ -2687,29 +2719,6 @@ static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection3 return S_OK; }
-static BOOL is_same_fontfile(IDWriteFontFile *left, IDWriteFontFile *right) -{ - UINT32 left_key_size, right_key_size; - const void *left_key, *right_key; - HRESULT hr; - - if (left == right) - return TRUE; - - hr = IDWriteFontFile_GetReferenceKey(left, &left_key, &left_key_size); - if (FAILED(hr)) - return FALSE; - - hr = IDWriteFontFile_GetReferenceKey(right, &right_key, &right_key_size); - if (FAILED(hr)) - return FALSE; - - if (left_key_size != right_key_size) - return FALSE; - - return !memcmp(left_key, right_key, left_key_size); -} - static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3 *iface, IDWriteFontFace *face, IDWriteFont **font) {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/tests/font.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 19c6928dd7..cdc41ec5a1 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -2400,11 +2400,14 @@ static void test_system_fontcollection(void) IDWriteFontCollection *collection, *coll2; IDWriteLocalFontFileLoader *localloader; IDWriteFontCollection1 *collection1; + IDWriteFontCollection2 *collection2; IDWriteFontCollection3 *collection3; IDWriteFactory *factory, *factory2; + DWRITE_FONT_FAMILY_MODEL model; IDWriteFontFileLoader *loader; IDWriteFontFamily *family; IDWriteFontFace *fontface; + IDWriteFactory6 *factory6; IDWriteFontFile *file; IDWriteFont *font; HRESULT hr; @@ -2585,15 +2588,48 @@ static void test_system_fontcollection(void) todo_wine ok(!!event, "Expected event handle.\n");
+ model = IDWriteFontCollection3_GetFontFamilyModel(collection3); + ok(model == DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE, "Unexpected model.\n"); + IDWriteFontCollection3_Release(collection3); } else win_skip("IDWriteFontCollection3 is not supported.\n");
+ /* With specified family model. */ + hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory6, (void **)&factory6); + if (SUCCEEDED(hr)) + { + IDWriteFontCollection2 *c2; + + hr = IDWriteFactory6_GetSystemFontCollection(factory6, FALSE, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, + &collection2); + todo_wine + ok(hr == S_OK, "Failed to get collection, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IDWriteFactory6_GetSystemFontCollection(factory6, FALSE, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, &c2); + ok(hr == S_OK, "Failed to get collection, hr %#x.\n", hr); + ok(c2 == collection2 && collection != (IDWriteFontCollection *)c2, "Unexpected collection instance.\n"); + IDWriteFontCollection2_Release(c2); + IDWriteFontCollection2_Release(collection2); + + hr = IDWriteFactory6_GetSystemFontCollection(factory6, FALSE, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE, + &collection2); + ok(hr == S_OK, "Failed to get collection, hr %#x.\n", hr); + ok(collection == (IDWriteFontCollection *)collection2, "Unexpected instance.\n"); + IDWriteFontCollection2_Release(collection2); + } + + IDWriteFactory6_Release(factory6); + } + else + win_skip("IDWriteFactory6 is not supported.\n"); + ref = IDWriteFontCollection_Release(collection); - ok(ref == 0, "collection not released, %u\n", ref); + ok(!ref, "Collection wasn't released, %u.\n", ref); ref = IDWriteFactory_Release(factory); - ok(ref == 0, "factory not released, %u\n", ref); + ok(!ref, "Factory wasn't released, %u.\n", ref); }
static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/font.c | 26 +++++++++++++++++--------- dlls/dwrite/opentype.c | 30 +++++++++++++++++++----------- 3 files changed, 37 insertions(+), 21 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index e5ca5306c2..200a9d39ba 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -327,7 +327,7 @@ extern const void* get_fontface_table(IDWriteFontFace5 *fontface, UINT32 tag, extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,BOOL*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,UINT32*) DECLSPEC_HIDDEN; extern HRESULT opentype_try_get_font_table(const struct file_stream_desc *stream_desc, UINT32 tag, const void **data, void **context, UINT32 *size, BOOL *exists) DECLSPEC_HIDDEN; -extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *table, unsigned int max_count, +extern HRESULT opentype_cmap_get_unicode_ranges(const struct file_stream_desc *stream_desc, unsigned int max_count, DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN; extern void opentype_get_font_properties(struct file_stream_desc*,struct dwrite_font_props*) DECLSPEC_HIDDEN; extern void opentype_get_font_metrics(struct file_stream_desc*,DWRITE_FONT_METRICS1*,DWRITE_CARET_METRICS*) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index a3af30afe5..507099b24e 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -972,6 +972,7 @@ static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace5 *iface, DWRITE_UNICODE_RANGE *ranges, UINT32 *count) { struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface); + struct file_stream_desc stream_desc;
TRACE("%p, %u, %p, %p.\n", iface, max_count, ranges, count);
@@ -979,8 +980,10 @@ static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace5 *iface, if (max_count && !ranges) return E_INVALIDARG;
- get_fontface_table(iface, MS_CMAP_TAG, &fontface->cmap); - return opentype_cmap_get_unicode_ranges(&fontface->cmap, max_count, ranges, count); + stream_desc.stream = fontface->stream; + stream_desc.face_index = fontface->index; + stream_desc.face_type = fontface->type; + return opentype_cmap_get_unicode_ranges(&stream_desc, max_count, ranges, count); }
static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace5 *iface) @@ -1795,20 +1798,25 @@ static void WINAPI dwritefont1_GetPanose(IDWriteFont3 *iface, DWRITE_PANOSE *pan *panose = This->data->panose; }
-static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count) +static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, + UINT32 *count) { struct dwrite_font *font = impl_from_IDWriteFont3(iface); - IDWriteFontFace5 *fontface; + struct file_stream_desc stream_desc; HRESULT hr;
TRACE("%p, %u, %p, %p.\n", iface, max_count, ranges, count);
- hr = get_fontface_from_font(font, &fontface); - if (FAILED(hr)) - return hr; + *count = 0; + if (max_count && !ranges) + return E_INVALIDARG;
- hr = IDWriteFontFace5_GetUnicodeRanges(fontface, max_count, ranges, count); - IDWriteFontFace5_Release(fontface); + if (FAILED(hr = get_filestream_from_file(font->data->file, &stream_desc.stream))) + return hr; + stream_desc.face_index = font->data->face_index; + stream_desc.face_type = font->data->face_type; + hr = opentype_cmap_get_unicode_ranges(&stream_desc, max_count, ranges, count); + IDWriteFontFileStream_Release(stream_desc.stream); return hr; }
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 23d7669eb6..0aa1b10460 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -1521,22 +1521,28 @@ static unsigned int opentype_cmap_get_unicode_ranges_count(const struct dwrite_f return count; }
-HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, unsigned int max_count, +HRESULT opentype_cmap_get_unicode_ranges(const struct file_stream_desc *stream_desc, unsigned int max_count, DWRITE_UNICODE_RANGE *ranges, unsigned int *count) { unsigned int i, num_tables, k = 0; const struct cmap_header *header; + struct dwrite_fonttable cmap;
- if (!cmap->exists) + opentype_get_font_table(stream_desc, MS_CMAP_TAG, &cmap); + + if (!cmap.exists) return E_FAIL;
- *count = opentype_cmap_get_unicode_ranges_count(cmap); + *count = opentype_cmap_get_unicode_ranges_count(&cmap);
- num_tables = table_read_be_word(cmap, FIELD_OFFSET(struct cmap_header, num_tables)); - header = table_read_ensure(cmap, 0, FIELD_OFFSET(struct cmap_header, tables[num_tables])); + num_tables = table_read_be_word(&cmap, FIELD_OFFSET(struct cmap_header, num_tables)); + header = table_read_ensure(&cmap, 0, FIELD_OFFSET(struct cmap_header, tables[num_tables]));
if (!header) + { + IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context); return S_OK; + }
for (i = 0; i < num_tables && k < max_count; ++i) { @@ -1547,18 +1553,18 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, un
offset = GET_BE_DWORD(header->tables[i].offset);
- format = table_read_be_word(cmap, offset); + format = table_read_be_word(&cmap, offset); switch (format) { case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING: { - unsigned int segment_count = table_read_be_word(cmap, offset + + unsigned int segment_count = table_read_be_word(&cmap, offset + FIELD_OFFSET(struct cmap_segment_mapping, seg_count_x2)) / 2; - const UINT16 *start_code = table_read_ensure(cmap, offset, + const UINT16 *start_code = table_read_ensure(&cmap, offset, FIELD_OFFSET(struct cmap_segment_mapping, end_code[segment_count]) + 2 /* reservedPad */ + 2 * segment_count /* start code array */); - const UINT16 *end_code = table_read_ensure(cmap, offset, + const UINT16 *end_code = table_read_ensure(&cmap, offset, FIELD_OFFSET(struct cmap_segment_mapping, end_code[segment_count]));
if (!start_code || !end_code) @@ -1573,11 +1579,11 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, un } case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE: { - unsigned int num_groups = table_read_be_dword(cmap, offset + + unsigned int num_groups = table_read_be_dword(&cmap, offset + FIELD_OFFSET(struct cmap_segmented_coverage, num_groups)); const struct cmap_segmented_coverage *coverage;
- coverage = table_read_ensure(cmap, offset, + coverage = table_read_ensure(&cmap, offset, FIELD_OFFSET(struct cmap_segmented_coverage, groups[num_groups]));
for (j = 0; j < num_groups && k < max_count; j++, k++) @@ -1592,6 +1598,8 @@ HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *cmap, un } }
+ IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context); + return *count > max_count ? E_NOT_SUFFICIENT_BUFFER : S_OK; }