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);