Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 7 +- dlls/dwrite/font.c | 18 +--- dlls/dwrite/opentype.c | 188 ++++++++++++++--------------------- 3 files changed, 81 insertions(+), 132 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 2a8a4d47414..a9fbb260e35 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -198,6 +198,8 @@ enum font_flags struct dwrite_cmap;
typedef UINT16 (*p_cmap_get_glyph_func)(const struct dwrite_cmap *cmap, unsigned int ch); +typedef unsigned int (*p_cmap_get_ranges_func)(const struct dwrite_cmap *cmap, unsigned int max_count, + DWRITE_UNICODE_RANGE *ranges);
struct dwrite_cmap { @@ -226,6 +228,7 @@ struct dwrite_cmap } format12_13; } u; p_cmap_get_glyph_func get_glyph; + p_cmap_get_ranges_func get_ranges; unsigned short symbol : 1; IDWriteFontFileStream *stream; void *table_context; @@ -235,6 +238,8 @@ extern void dwrite_cmap_init(struct dwrite_cmap *cmap, IDWriteFontFile *file, un DWRITE_FONT_FACE_TYPE face_type) DECLSPEC_HIDDEN; extern void dwrite_cmap_release(struct dwrite_cmap *cmap) DECLSPEC_HIDDEN; extern UINT16 opentype_cmap_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch) DECLSPEC_HIDDEN; +extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, unsigned int max_count, + DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN;
struct dwrite_fontface { @@ -387,8 +392,6 @@ struct ot_gsubgpos_table 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 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; extern void opentype_get_font_typo_metrics(struct file_stream_desc *stream_desc, unsigned int *ascent, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 7f5cce4e4b2..ab60d4368c7 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1005,7 +1005,6 @@ 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);
@@ -1013,10 +1012,8 @@ static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace5 *iface, if (max_count && !ranges) return E_INVALIDARG;
- 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); + dwrite_cmap_init(&fontface->cmap, NULL, fontface->index, fontface->type); + return opentype_cmap_get_unicode_ranges(&fontface->cmap, max_count, ranges, count); }
static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace5 *iface) @@ -2000,8 +1997,6 @@ static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 m UINT32 *count) { struct dwrite_font *font = impl_from_IDWriteFont3(iface); - struct file_stream_desc stream_desc; - HRESULT hr;
TRACE("%p, %u, %p, %p.\n", iface, max_count, ranges, count);
@@ -2009,13 +2004,8 @@ static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 m if (max_count && !ranges) return E_INVALIDARG;
- 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; + dwrite_cmap_init(&font->data->cmap, font->data->file, font->data->face_index, font->data->face_type); + return opentype_cmap_get_unicode_ranges(&font->data->cmap, max_count, ranges, count); }
static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface) diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 563154992ab..d8bfa3f7f6d 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -1571,6 +1571,18 @@ static UINT16 opentype_cmap_format0_get_glyph(const struct dwrite_cmap *cmap, un return (ch < 0xff) ? glyphs[ch] : 0; }
+static unsigned int opentype_cmap_format0_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, + DWRITE_UNICODE_RANGE *ranges) +{ + if (count > 0) + { + ranges->first = 0; + ranges->last = 255; + } + + return 1; +} + struct cmap_format4_compare_context { const struct dwrite_cmap *cmap; @@ -1627,6 +1639,22 @@ static UINT16 opentype_cmap_format4_get_glyph(const struct dwrite_cmap *cmap, un return glyph & 0xffff; }
+static unsigned int opentype_cmap_format4_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, + DWRITE_UNICODE_RANGE *ranges) +{ + unsigned int i; + + count = min(count, cmap->u.format4.seg_count); + + for (i = 0; i < count; ++i) + { + ranges[i].first = GET_BE_WORD(cmap->u.format4.starts[i]); + ranges[i].last = GET_BE_WORD(cmap->u.format4.ends[i]); + } + + return cmap->u.format4.seg_count; +} + static UINT16 opentype_cmap_format6_10_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch) { const UINT16 *glyphs = cmap->data; @@ -1634,6 +1662,18 @@ static UINT16 opentype_cmap_format6_10_get_glyph(const struct dwrite_cmap *cmap, return glyphs[ch - cmap->u.format6_10.first]; }
+static unsigned int opentype_cmap_format6_10_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, + DWRITE_UNICODE_RANGE *ranges) +{ + if (count > 0) + { + ranges->first = cmap->u.format6_10.first; + ranges->last = cmap->u.format6_10.last; + } + + return 1; +} + static int cmap_format12_13_compare_group(const void *a, const void *b) { const unsigned int *ch = a; @@ -1661,6 +1701,23 @@ static UINT16 opentype_cmap_format12_get_glyph(const struct dwrite_cmap *cmap, u GET_BE_DWORD(group_found[2]) + (ch - GET_BE_DWORD(group_found[0])) : 0; }
+static unsigned int opentype_cmap_format12_13_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, + DWRITE_UNICODE_RANGE *ranges) +{ + unsigned int i, group_count = cmap->u.format12_13.group_count; + const UINT32 *groups = cmap->data; + + count = min(count, group_count); + + for (i = 0; i < count; ++i) + { + ranges[i].first = GET_BE_DWORD(groups[3 * i]); + ranges[i].last = GET_BE_DWORD(groups[3 * i + 1]); + } + + return group_count; +} + static UINT16 opentype_cmap_format13_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch) { const UINT32 *groups = cmap->data; @@ -1678,6 +1735,12 @@ static UINT16 opentype_cmap_dummy_get_glyph(const struct dwrite_cmap *cmap, unsi return 0; }
+static unsigned int opentype_cmap_dummy_get_ranges(const struct dwrite_cmap *cmap, unsigned int count, + DWRITE_UNICODE_RANGE *ranges) +{ + return 0; +} + UINT16 opentype_cmap_get_glyph(const struct dwrite_cmap *cmap, unsigned int ch) { UINT16 glyph; @@ -1771,6 +1834,7 @@ void dwrite_cmap_init(struct dwrite_cmap *cmap, IDWriteFontFile *file, unsigned case 0: cmap->data = table_read_ensure(&table, offset + 6, 256); cmap->get_glyph = opentype_cmap_format0_get_glyph; + cmap->get_ranges = opentype_cmap_format0_get_ranges; break; case 4: length = table_read_be_word(&table, offset + 2); @@ -1782,6 +1846,7 @@ void dwrite_cmap_init(struct dwrite_cmap *cmap, IDWriteFontFile *file, unsigned cmap->u.format4.glyph_id_array = cmap->data = cmap->u.format4.id_range_offset + count; cmap->u.format4.glyph_id_array_len = (length - 16 - 8 * count) / 2; cmap->get_glyph = opentype_cmap_format4_get_glyph; + cmap->get_ranges = opentype_cmap_format4_get_ranges; break; case 6: case 10: @@ -1792,12 +1857,14 @@ void dwrite_cmap_init(struct dwrite_cmap *cmap, IDWriteFontFile *file, unsigned cmap->u.format6_10.last = cmap->u.format6_10.first + count; cmap->data = table_read_ensure(&table, offset + f * 10, count * 2); cmap->get_glyph = opentype_cmap_format6_10_get_glyph; + cmap->get_ranges = opentype_cmap_format6_10_get_ranges; break; case 12: case 13: cmap->u.format12_13.group_count = count = table_read_be_dword(&table, offset + 12); cmap->data = table_read_ensure(&table, offset + 16, count * 3 * 4); cmap->get_glyph = format == 12 ? opentype_cmap_format12_get_glyph : opentype_cmap_format13_get_glyph; + cmap->get_ranges = opentype_cmap_format12_13_get_ranges; break; default: WARN("Unhandled subtable format %u.\n", format); @@ -1810,6 +1877,7 @@ failed: /* Dummy implementation, returns 0 unconditionally. */ cmap->data = cmap; cmap->get_glyph = opentype_cmap_dummy_get_glyph; + cmap->get_ranges = opentype_cmap_dummy_get_ranges; } }
@@ -1824,125 +1892,13 @@ void dwrite_cmap_release(struct dwrite_cmap *cmap) cmap->stream = NULL; }
-static unsigned int opentype_cmap_get_unicode_ranges_count(const struct dwrite_fonttable *cmap) +HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, unsigned int max_count, DWRITE_UNICODE_RANGE *ranges, + unsigned int *count) { - unsigned int i, num_tables, count = 0; - const struct cmap_header *header; - - 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) - return 0; - - for (i = 0; i < num_tables; ++i) - { - unsigned int format, offset; - - if (GET_BE_WORD(header->tables[i].platformID) != 3) - continue; - - offset = GET_BE_DWORD(header->tables[i].offset); - format = table_read_be_word(cmap, offset); - - switch (format) - { - case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING: - { - count += table_read_be_word(cmap, offset + FIELD_OFFSET(struct cmap_segment_mapping, seg_count_x2)) / 2; - break; - } - case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE: - { - count += table_read_be_dword(cmap, offset + FIELD_OFFSET(struct cmap_segmented_coverage, num_groups)); - break; - } - default: - FIXME("table format %u is not supported.\n", format); - } - } - - return 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; - - opentype_get_font_table(stream_desc, MS_CMAP_TAG, &cmap); - - if (!cmap.exists) + if (!cmap->data) return E_FAIL;
- *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])); - - if (!header) - { - IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context); - return S_OK; - } - - for (i = 0; i < num_tables && k < max_count; ++i) - { - unsigned int j, offset, format; - - if (GET_BE_WORD(header->tables[i].platformID) != 3) - continue; - - offset = GET_BE_DWORD(header->tables[i].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 + - FIELD_OFFSET(struct cmap_segment_mapping, seg_count_x2)) / 2; - 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, - FIELD_OFFSET(struct cmap_segment_mapping, end_code[segment_count])); - - if (!start_code || !end_code) - continue; - - for (j = 0; j < segment_count && GET_BE_WORD(end_code[j]) != 0xffff && k < max_count; ++j, ++k) - { - ranges[k].first = GET_BE_WORD(start_code[j]); - ranges[k].last = GET_BE_WORD(end_code[j]); - } - break; - } - case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE: - { - 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, - FIELD_OFFSET(struct cmap_segmented_coverage, groups[num_groups])); - - for (j = 0; j < num_groups && k < max_count; j++, k++) - { - ranges[k].first = GET_BE_DWORD(coverage->groups[j].startCharCode); - ranges[k].last = GET_BE_DWORD(coverage->groups[j].endCharCode); - } - break; - } - default: - FIXME("table format %u unhandled.\n", format); - } - } - - IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context); + *count = cmap->get_ranges(cmap, max_count, ranges);
return *count > max_count ? E_NOT_SUFFICIENT_BUFFER : S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 ++ dlls/dwrite/font.c | 8 +++-- dlls/dwrite/opentype.c | 60 ++++++++++++++++++++++++++++++++++++ dlls/dwrite/tests/font.c | 43 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index a9fbb260e35..e53b4dba0bb 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -642,6 +642,8 @@ extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *co extern BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsigned int script_index, unsigned int language_index, struct shaping_feature *feature, unsigned int glyph_count, const UINT16 *glyphs, UINT8 *feature_applies) DECLSPEC_HIDDEN; +extern HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count, + const UINT16 *nominal_glyphs, UINT16 *glyphs) DECLSPEC_HIDDEN;
extern HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned int *scripts) DECLSPEC_HIDDEN; extern HRESULT shape_get_positions(struct scriptshaping_context *context, const unsigned int *scripts) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index ab60d4368c7..2d7a97594fc 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1166,11 +1166,13 @@ static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFac }
static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5 *iface, UINT32 glyph_count, - const UINT16 *nominal_indices, UINT16 *vertical_indices) + const UINT16 *nominal_glyphs, UINT16 *glyphs) { - FIXME("%p, %u, %p, %p: stub\n", iface, glyph_count, nominal_indices, vertical_indices); + struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
- return E_NOTIMPL; + TRACE("%p, %u, %p, %p.\n", iface, glyph_count, nominal_glyphs, glyphs); + + return opentype_get_vertical_glyph_variants(fontface, glyph_count, nominal_glyphs, glyphs); }
static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5 *iface) diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index d8bfa3f7f6d..1f0174ad72a 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -6214,3 +6214,63 @@ BOOL opentype_layout_check_feature(struct scriptshaping_context *context, unsign
return ret; } + +HRESULT opentype_get_vertical_glyph_variants(struct dwrite_fontface *fontface, unsigned int glyph_count, + const UINT16 *nominal_glyphs, UINT16 *glyphs) +{ + struct shaping_features features = { 0 }; + struct shaping_feature vert_feature = { 0 }; + struct scriptshaping_context context = { 0 }; + struct lookups lookups = { 0 }; + unsigned int i; + + memcpy(glyphs, nominal_glyphs, glyph_count * sizeof(*glyphs)); + + if (!(fontface->flags & FONTFACE_HAS_VERTICAL_VARIANTS)) + return S_OK; + + context.cache = fontface_get_shaping_cache(fontface); + context.u.subst.glyphs = glyphs; + context.u.subst.glyph_props = heap_calloc(glyph_count, sizeof(*context.u.subst.glyph_props)); + context.u.subst.max_glyph_count = glyph_count; + context.u.subst.capacity = glyph_count; + context.glyph_infos = heap_alloc_zero(sizeof(*context.glyph_infos) * glyph_count); + context.table = &context.cache->gsub; + + vert_feature.tag = DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t'); + vert_feature.flags = FEATURE_GLOBAL | FEATURE_GLOBAL_SEARCH; + vert_feature.max_value = 1; + vert_feature.default_value = 1; + + features.features = &vert_feature; + features.count = features.capacity = 1; + + opentype_layout_collect_lookups(&context, ~0u, ~0u, &features, context.table, &lookups); + opentype_layout_set_glyph_masks(&context, &features); + + for (i = 0; i < lookups.count; ++i) + { + const struct lookup *lookup = &lookups.lookups[i]; + + if (lookup->type != GSUB_LOOKUP_SINGLE_SUBST) + continue; + + context.cur = 0; + while (context.cur < context.glyph_count) + { + BOOL ret = FALSE; + + if (lookup_is_glyph_match(&context, context.cur, lookup->flags)) + ret = opentype_layout_apply_gsub_lookup(&context, lookup); + + if (!ret) + context.cur++; + } + } + + heap_free(context.u.subst.glyph_props); + heap_free(context.glyph_infos); + heap_free(lookups.lookups); + + return S_OK; +} diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 7c48a57eab6..f8abbf9e4b4 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -9736,6 +9736,48 @@ static void test_IsColorFont(void) ok(refcount == 0, "Factory not released, refcount %u.\n", refcount); }
+static void test_GetVerticalGlyphVariants(void) +{ + UINT16 glyphs[1], glyph_variants[1]; + IDWriteFontFace1 *fontface1; + IDWriteFontFace *fontface; + IDWriteFactory *factory; + unsigned int ch; + ULONG refcount; + HRESULT hr; + BOOL ret; + + factory = create_factory(); + + fontface = create_fontface(factory); + hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void **)&fontface1); + IDWriteFontFace_Release(fontface); + if (FAILED(hr)) + { + win_skip("GetVerticalGlyphVariants() is not supported.\n"); + IDWriteFactory_Release(factory); + return; + } + + ch = 'A'; + *glyphs = 0; + hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &ch, 1, glyphs); + ok(hr == S_OK, "Failed to get glyph, hr %#x.\n", hr); + ok(!!*glyphs, "Unexpected glyph %u.\n", glyphs[0]); + + memset(glyph_variants, 0, sizeof(glyph_variants)); + hr = IDWriteFontFace1_GetVerticalGlyphVariants(fontface1, 1, glyphs, glyph_variants); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(glyphs[0] == glyph_variants[0], "Unexpected glyph.\n"); + + ret = IDWriteFontFace1_HasVerticalGlyphVariants(fontface1); + ok(!ret, "Unexpected flag.\n"); + + IDWriteFontFace1_Release(fontface1); + refcount = IDWriteFactory_Release(factory); + ok(!refcount, "Factory not released, refcount %u.\n", refcount); +} + START_TEST(font) { IDWriteFactory *factory; @@ -9805,6 +9847,7 @@ START_TEST(font) test_fontsetbuilder(); test_font_resource(); test_IsColorFont(); + test_GetVerticalGlyphVariants();
IDWriteFactory_Release(factory); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/font.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 2d7a97594fc..d8d892c9ef1 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1545,7 +1545,10 @@ static HRESULT WINAPI dwritefontface5_GetFontAxisValues(IDWriteFontFace5 *iface,
static BOOL WINAPI dwritefontface5_HasVariations(IDWriteFontFace5 *iface) { - FIXME("%p: stub\n", iface); + static int once; + + if (!once++) + FIXME("%p: stub\n", iface);
return FALSE; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/font.c | 4 ++-- dlls/dwrite/main.c | 3 ++- dlls/dwrite/tests/font.c | 20 ++++++++------------ include/dwrite_3.idl | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index e53b4dba0bb..38863b85bd6 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -343,7 +343,7 @@ extern HRESULT create_gdiinterop(IDWriteFactory7 *factory, IDWriteGdiInterop1 ** extern void fontface_detach_from_cache(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN; extern void factory_lock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN; extern void factory_unlock(IDWriteFactory7 *factory) DECLSPEC_HIDDEN; -extern HRESULT create_inmemory_fileloader(IDWriteFontFileLoader**) DECLSPEC_HIDDEN; +extern HRESULT create_inmemory_fileloader(IDWriteInMemoryFontFileLoader **loader) DECLSPEC_HIDDEN; extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *file, UINT32 face_index, IDWriteFontResource **resource) DECLSPEC_HIDDEN;
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index d8d892c9ef1..baee8d1e491 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -6832,7 +6832,7 @@ static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl = inmemoryfontfileloader_GetFileCount, };
-HRESULT create_inmemory_fileloader(IDWriteFontFileLoader **ret) +HRESULT create_inmemory_fileloader(IDWriteInMemoryFontFileLoader **ret) { struct dwrite_inmemory_fileloader *loader;
@@ -6845,7 +6845,7 @@ HRESULT create_inmemory_fileloader(IDWriteFontFileLoader **ret) loader->IDWriteInMemoryFontFileLoader_iface.lpVtbl = &inmemoryfontfileloadervtbl; loader->ref = 1;
- *ret = (IDWriteFontFileLoader *)&loader->IDWriteInMemoryFontFileLoader_iface; + *ret = &loader->IDWriteInMemoryFontFileLoader_iface;
return S_OK; } diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index b940d0d801e..a96874b2c2c 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1627,7 +1627,8 @@ static HRESULT WINAPI dwritefactory5_CreateFontSetBuilder(IDWriteFactory7 *iface return E_NOTIMPL; }
-static HRESULT WINAPI dwritefactory5_CreateInMemoryFontFileLoader(IDWriteFactory7 *iface, IDWriteFontFileLoader **loader) +static HRESULT WINAPI dwritefactory5_CreateInMemoryFontFileLoader(IDWriteFactory7 *iface, + IDWriteInMemoryFontFileLoader **loader) { TRACE("%p, %p.\n", iface, loader);
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index f8abbf9e4b4..07baf112eed 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -8696,8 +8696,9 @@ static void testowner_init(struct testowner_object *object) static void test_inmemory_file_loader(void) { IDWriteFontFileStream *stream, *stream2, *stream3; - IDWriteFontFileLoader *loader, *loader2; + IDWriteInMemoryFontFileLoader *loader, *loader2; IDWriteInMemoryFontFileLoader *inmemory; + IDWriteFontFileLoader *fileloader; struct testowner_object ownerobject; const void *key, *data, *frag_start; UINT64 file_size, size, writetime; @@ -8727,12 +8728,9 @@ static void test_inmemory_file_loader(void) hr = IDWriteFactory5_CreateInMemoryFontFileLoader(factory, &loader2); ok(hr == S_OK, "got %#x\n", hr); ok(loader != loader2, "unexpected pointer\n"); - IDWriteFontFileLoader_Release(loader2); + IDWriteInMemoryFontFileLoader_Release(loader2);
- hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteInMemoryFontFileLoader, (void **)&inmemory); - ok(hr == S_OK, "got %#x\n", hr); - IDWriteFontFileLoader_Release(loader); - EXPECT_REF(inmemory, 1); + inmemory = loader;
count = IDWriteInMemoryFontFileLoader_GetFileCount(inmemory); ok(!count, "Unexpected file count %u.\n", count); @@ -8742,15 +8740,15 @@ static void test_inmemory_file_loader(void) hr = IDWriteFontFace_GetFiles(fontface, &count, &file); ok(hr == S_OK, "got %#x\n", hr);
- hr = IDWriteFontFile_GetLoader(file, &loader); + hr = IDWriteFontFile_GetLoader(file, &fileloader); ok(hr == S_OK, "got %#x\n", hr);
hr = IDWriteFontFile_GetReferenceKey(file, &key, &key_size); ok(hr == S_OK, "got %#x\n", hr);
- hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, key, key_size, &stream); + hr = IDWriteFontFileLoader_CreateStreamFromKey(fileloader, key, key_size, &stream); ok(hr == S_OK, "got %#x\n", hr); - IDWriteFontFileLoader_Release(loader); + IDWriteFontFileLoader_Release(fileloader); IDWriteFontFile_Release(file);
hr = IDWriteFontFileStream_GetFileSize(stream, &file_size); @@ -8848,9 +8846,7 @@ static void test_inmemory_file_loader(void) hr = IDWriteFactory5_CreateInMemoryFontFileLoader(factory, &loader); ok(hr == S_OK, "Failed to create loader, hr %#x.\n", hr);
- hr = IDWriteFontFileLoader_QueryInterface(loader, &IID_IDWriteInMemoryFontFileLoader, (void **)&inmemory); - ok(hr == S_OK, "Failed to get in-memory interface, hr %#x.\n", hr); - IDWriteFontFileLoader_Release(loader); + inmemory = loader;
hr = IDWriteFactory5_RegisterFontFileLoader(factory, (IDWriteFontFileLoader *)inmemory); ok(hr == S_OK, "Failed to register loader, hr %#x.\n", hr); diff --git a/include/dwrite_3.idl b/include/dwrite_3.idl index 54d204f39fb..f5ee6157cd7 100644 --- a/include/dwrite_3.idl +++ b/include/dwrite_3.idl @@ -923,7 +923,7 @@ interface IDWriteInMemoryFontFileLoader : IDWriteFontFileLoader interface IDWriteFactory5 : IDWriteFactory4 { HRESULT CreateFontSetBuilder(IDWriteFontSetBuilder1 **fontset_builder); - HRESULT CreateInMemoryFontFileLoader(IDWriteFontFileLoader **loader); + HRESULT CreateInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader **loader); HRESULT CreateHttpFontFileLoader( WCHAR const *referrer_url, WCHAR const *extra_headers,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/opentype.c | 26 ++++++++++++++++++++++---- dlls/dwrite/tests/layout.c | 16 ++++++---------- 2 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index 1f0174ad72a..72cc6f4c93c 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -5834,13 +5834,23 @@ static unsigned int opentype_is_default_ignorable(unsigned int codepoint) (codepoint >= 0x180b && codepoint <= 0x180e) || (codepoint >= 0x200b && codepoint <= 0x200f); }
+static unsigned int opentype_is_diacritic(unsigned int codepoint) +{ + WCHAR ch = codepoint; + WORD type = 0; + /* Ignore higher planes for now. */ + if (codepoint > 0xffff) return 0; + GetStringTypeW(CT_CTYPE3, &ch, 1, &type); + return !!(type & C3_DIACRITIC); +} + static void opentype_get_nominal_glyphs(struct scriptshaping_context *context, const struct shaping_features *features) { unsigned int rtlm_mask = shaping_features_get_mask(features, DWRITE_MAKE_OPENTYPE_TAG('r','t','l','m'), NULL); const struct shaping_font_ops *font = context->cache->font; + unsigned int i, g, c, codepoint, cluster_start_idx = 0; UINT16 *clustermap = context->u.subst.clustermap; const WCHAR *text = context->text; - unsigned int i, g, c, codepoint; BOOL bmp;
memset(context->u.subst.glyph_props, 0, context->u.subst.max_glyph_count * sizeof(*context->u.subst.glyph_props)); @@ -5873,17 +5883,25 @@ static void opentype_get_nominal_glyphs(struct scriptshaping_context *context, c
context->u.buffer.glyphs[g] = font->get_glyph(context->cache->context, codepoint); context->u.buffer.glyph_props[g].justification = SCRIPT_JUSTIFY_CHARACTER; - context->u.buffer.glyph_props[g].isClusterStart = 1; opentype_set_subst_glyph_props(context, g); + + /* Group diacritics with preceding base. Glyph class is ignored here. */ + if (!g || !opentype_is_diacritic(codepoint)) + { + context->u.buffer.glyph_props[g].isClusterStart = 1; + cluster_start_idx = g; + } + if (opentype_is_default_ignorable(codepoint)) context->u.buffer.glyph_props[g].isZeroWidthSpace = 1; context->u.buffer.glyph_props[g].components = 1; context->glyph_count++;
- clustermap[i] = i; + /* Set initial cluster map here, it's used for setting user features masks. */ + clustermap[i] = cluster_start_idx; if (!bmp) { - clustermap[i + 1] = i; + clustermap[i + 1] = cluster_start_idx; ++i; } } diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c index d19f91311db..2e309f14b73 100644 --- a/dlls/dwrite/tests/layout.c +++ b/dlls/dwrite/tests/layout.c @@ -2630,13 +2630,11 @@ if (0) { /* crashes on native */ count = 0; hr = IDWriteTextLayout1_GetClusterMetrics(layout1, clusters, 4, &count); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine - ok(count == 3, "got %u\n", count); -if (count == 3) { + ok(count == 3, "Unexpected cluster count %u.\n", count); ok(clusters[0].length == 1, "got %u\n", clusters[0].length); ok(clusters[1].length == 2, "got %u\n", clusters[1].length); ok(clusters[2].length == 1, "got %u\n", clusters[2].length); -} + /* pair kerning flag participates in itemization - combining characters breaks */ range.startPosition = 0; @@ -5235,9 +5233,8 @@ static void test_SetUnderline(void)
count = 0; hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, ARRAY_SIZE(clusters), &count); - ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine - ok(count == 3, "got %u\n", count); + ok(hr == S_OK, "Failed to get cluster metrics, hr %#x.\n", hr); + ok(count == 3, "Unexpected cluster count %u.\n", count);
range.startPosition = 0; range.length = 2; @@ -5246,9 +5243,8 @@ todo_wine
count = 0; hr = IDWriteTextLayout_GetClusterMetrics(layout, clusters, ARRAY_SIZE(clusters), &count); - ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine - ok(count == 3, "got %u\n", count); + ok(hr == S_OK, "Failed to get cluster metrics, hr %#x.\n", hr); + ok(count == 3, "Unexpected cluster count %u.\n", count);
flush_sequence(sequences, RENDERER_ID); hr = IDWriteTextLayout_Draw(layout, NULL, &testrenderer, 0.0, 0.0);