Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/analyzer.c | 209 ++++++++++++++++-------------------
dlls/dwrite/tests/analyzer.c | 158 +++++++++++++++++++-------
2 files changed, 215 insertions(+), 152 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index a1d9f25ad1..7ee3675d2e 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -1397,124 +1397,121 @@ static inline FLOAT get_cluster_advance(const FLOAT *advances, UINT32 start, UIN
return advance;
}
-static void apply_single_glyph_spacing(FLOAT leading_spacing, FLOAT trailing_spacing,
- FLOAT min_advance_width, UINT32 g, FLOAT const *advances, DWRITE_GLYPH_OFFSET const *offsets,
- DWRITE_SHAPING_GLYPH_PROPERTIES const *props, FLOAT *modified_advances, DWRITE_GLYPH_OFFSET *modified_offsets)
+static HRESULT apply_cluster_spacing(float leading_spacing, float trailing_spacing, float min_advance_width,
+ unsigned int start, unsigned int end, float const *advances, DWRITE_GLYPH_OFFSET const *offsets,
+ DWRITE_SHAPING_GLYPH_PROPERTIES const *glyph_props, float *modified_advances,
+ DWRITE_GLYPH_OFFSET *modified_offsets)
{
BOOL reduced = leading_spacing < 0.0f || trailing_spacing < 0.0f;
- FLOAT advance = advances[g];
- FLOAT origin = 0.0f;
+ unsigned int first_spacing, last_spacing, i;
+ float advance, origin = 0.0f, *deltas;
+ BOOL is_spacing_cluster = FALSE;
- if (props[g].isZeroWidthSpace) {
- modified_advances[g] = advances[g];
- modified_offsets[g] = offsets[g];
- return;
- }
+ if (modified_advances != advances)
+ memcpy(&modified_advances[start], &advances[start], (end - start + 1) * sizeof(*advances));
+ if (modified_offsets != offsets)
+ memcpy(&modified_offsets[start], &offsets[start], (end - start + 1) * sizeof(*offsets));
- /* first apply negative spacing and check if we hit minimum width */
- if (leading_spacing < 0.0f) {
- advance += leading_spacing;
- origin -= leading_spacing;
+ for (first_spacing = start; first_spacing <= end; ++first_spacing)
+ {
+ if ((is_spacing_cluster = !glyph_props[first_spacing].isZeroWidthSpace))
+ break;
}
- if (trailing_spacing < 0.0f)
- advance += trailing_spacing;
- if (advance < min_advance_width) {
- FLOAT half = (min_advance_width - advance) / 2.0f;
-
- if (!reduced)
- origin -= half;
- else if (leading_spacing < 0.0f && trailing_spacing < 0.0f)
- origin -= half;
- else if (leading_spacing < 0.0f)
- origin -= min_advance_width - advance;
+ /* Nothing to adjust if there is no spacing glyphs. */
+ if (!is_spacing_cluster)
+ return S_OK;
- advance = min_advance_width;
+ for (last_spacing = end; last_spacing >= start; --last_spacing)
+ {
+ if (!glyph_props[last_spacing].isZeroWidthSpace)
+ break;
}
- /* now apply positive spacing adjustments */
- if (leading_spacing > 0.0f) {
- advance += leading_spacing;
- origin -= leading_spacing;
- }
- if (trailing_spacing > 0.0f)
- advance += trailing_spacing;
+ deltas = heap_alloc((end - start + 1) * sizeof(*deltas));
+ if (!deltas)
+ return E_OUTOFMEMORY;
- modified_advances[g] = advance;
- modified_offsets[g].advanceOffset = offsets[g].advanceOffset - origin;
- /* ascender is never touched, it's orthogonal to reading direction and is not
- affected by advance adjustments */
- modified_offsets[g].ascenderOffset = offsets[g].ascenderOffset;
-}
+ /* Cluster advance, note that properties are ignored. */
+ origin = offsets[start].advanceOffset;
+ for (i = start, advance = 0.0f; i <= end; ++i)
+ {
+ float cur = advance + offsets[i].advanceOffset;
-static void apply_cluster_spacing(FLOAT leading_spacing, FLOAT trailing_spacing, FLOAT min_advance_width,
- UINT32 start, UINT32 end, FLOAT const *advances, DWRITE_GLYPH_OFFSET const *offsets,
- FLOAT *modified_advances, DWRITE_GLYPH_OFFSET *modified_offsets)
-{
- BOOL reduced = leading_spacing < 0.0f || trailing_spacing < 0.0f;
- FLOAT advance = get_cluster_advance(advances, start, end);
- FLOAT origin = 0.0f;
- UINT16 g;
+ deltas[i - start] = cur - origin;
- modified_advances[start] = advances[start];
- modified_advances[end-1] = advances[end-1];
+ advance += advances[i];
+ origin = cur;
+ }
- /* first apply negative spacing and check if we hit minimum width */
- if (leading_spacing < 0.0f) {
+ /* Negative spacing. */
+ if (leading_spacing < 0.0f)
+ {
advance += leading_spacing;
- modified_advances[start] += leading_spacing;
- origin -= leading_spacing;
+ modified_advances[first_spacing] += leading_spacing;
+ modified_offsets[first_spacing].advanceOffset += leading_spacing;
}
- if (trailing_spacing < 0.0f) {
+
+ if (trailing_spacing < 0.0f)
+ {
advance += trailing_spacing;
- modified_advances[end-1] += trailing_spacing;
+ modified_advances[last_spacing] += trailing_spacing;
}
+ /* Minimal advance. */
advance = min_advance_width - advance;
if (advance > 0.0f) {
- /* additional spacing is only applied to leading and trailing glyph */
- FLOAT half = advance / 2.0f;
+ /* Additional spacing is only applied to leading and trailing spacing glyphs. */
+ float half = advance / 2.0f;
- if (!reduced) {
- origin -= half;
- modified_advances[start] += half;
- modified_advances[end-1] += half;
+ if (!reduced)
+ {
+ modified_advances[first_spacing] += half;
+ modified_advances[last_spacing] += half;
+ modified_offsets[first_spacing].advanceOffset += half;
}
- else if (leading_spacing < 0.0f && trailing_spacing < 0.0f) {
- origin -= half;
- modified_advances[start] += half;
- modified_advances[end-1] += half;
+ else if (leading_spacing < 0.0f && trailing_spacing < 0.0f)
+ {
+ modified_advances[first_spacing] += half;
+ modified_advances[last_spacing] += half;
+ modified_offsets[first_spacing].advanceOffset += half;
}
- else if (leading_spacing < 0.0f) {
- origin -= advance;
- modified_advances[start] += advance;
+ else if (leading_spacing < 0.0f)
+ {
+ modified_advances[first_spacing] += advance;
+ modified_offsets[first_spacing].advanceOffset += advance;
}
else
- modified_advances[end-1] += advance;
+ modified_advances[last_spacing] += advance;
}
- /* now apply positive spacing adjustments */
- if (leading_spacing > 0.0f) {
- modified_advances[start] += leading_spacing;
- origin -= leading_spacing;
+ /* Positive spacing. */
+ if (leading_spacing > 0.0f)
+ {
+ modified_advances[first_spacing] += leading_spacing;
+ modified_offsets[first_spacing].advanceOffset += leading_spacing;
}
+
if (trailing_spacing > 0.0f)
- modified_advances[end-1] += trailing_spacing;
+ modified_advances[last_spacing] += trailing_spacing;
- for (g = start; g < end; g++) {
- if (g == start) {
- modified_offsets[g].advanceOffset = offsets[g].advanceOffset - origin;
- modified_offsets[g].ascenderOffset = offsets[g].ascenderOffset;
- }
- else if (g == end - 1)
- /* trailing glyph offset is not adjusted */
- modified_offsets[g] = offsets[g];
- else {
- /* for all glyphs within a cluster use original advances and offsets */
- modified_advances[g] = advances[g];
- modified_offsets[g] = offsets[g];
- }
+ /* Update offsets to preserve original relative positions within cluster. */
+ for (i = first_spacing; i > start; --i)
+ {
+ unsigned int cur = i - 1;
+ modified_offsets[cur].advanceOffset = modified_advances[cur] + modified_offsets[i].advanceOffset -
+ deltas[i - start];
+ }
+
+ for (i = first_spacing + 1; i <= end; ++i)
+ {
+ modified_offsets[i].advanceOffset = deltas[i - start] + modified_offsets[i - 1].advanceOffset -
+ modified_advances[i - 1];
}
+
+ heap_free(deltas);
+
+ return S_OK;
}
static inline UINT32 get_cluster_length(UINT16 const *clustermap, UINT32 start, UINT32 text_len)
@@ -1562,16 +1559,13 @@ static inline UINT32 get_cluster_length(UINT16 const *clustermap, UINT32 start,
It's known that isZeroWidthSpace property keeps initial advance from changing.
- TODO: test other properties; make isZeroWidthSpace work properly for clusters
- with more than one glyph.
-
*/
static HRESULT WINAPI dwritetextanalyzer1_ApplyCharacterSpacing(IDWriteTextAnalyzer2 *iface,
FLOAT leading_spacing, FLOAT trailing_spacing, FLOAT min_advance_width, UINT32 len,
UINT32 glyph_count, UINT16 const *clustermap, FLOAT const *advances, DWRITE_GLYPH_OFFSET const *offsets,
DWRITE_SHAPING_GLYPH_PROPERTIES const *props, FLOAT *modified_advances, DWRITE_GLYPH_OFFSET *modified_offsets)
{
- UINT16 start;
+ unsigned int i;
TRACE("(%.2f %.2f %.2f %u %u %p %p %p %p %p %p)\n", leading_spacing, trailing_spacing, min_advance_width,
len, glyph_count, clustermap, advances, offsets, props, modified_advances, modified_offsets);
@@ -1582,33 +1576,18 @@ static HRESULT WINAPI dwritetextanalyzer1_ApplyCharacterSpacing(IDWriteTextAnaly
return E_INVALIDARG;
}
- /* minimum advance is not applied if no adjustments were made */
- if (leading_spacing == 0.0f && trailing_spacing == 0.0f) {
- memmove(modified_advances, advances, glyph_count*sizeof(*advances));
- memmove(modified_offsets, offsets, glyph_count*sizeof(*offsets));
- return S_OK;
- }
-
- for (start = 0; start < len;) {
- UINT32 length = get_cluster_length(clustermap, start, len);
-
- if (length == 1) {
- UINT32 g = clustermap[start];
-
- apply_single_glyph_spacing(leading_spacing, trailing_spacing, min_advance_width,
- g, advances, offsets, props, modified_advances, modified_offsets);
- }
- else {
- UINT32 g_start, g_end;
+ for (i = 0; i < len;)
+ {
+ unsigned int length = get_cluster_length(clustermap, i, len);
+ unsigned int start, end;
- g_start = clustermap[start];
- g_end = (start + length < len) ? clustermap[start + length] : glyph_count;
+ start = clustermap[i];
+ end = i + length < len ? clustermap[i + length] : glyph_count;
- apply_cluster_spacing(leading_spacing, trailing_spacing, min_advance_width,
- g_start, g_end, advances, offsets, modified_advances, modified_offsets);
- }
+ apply_cluster_spacing(leading_spacing, trailing_spacing, min_advance_width, start, end - 1, advances,
+ offsets, props, modified_advances, modified_offsets);
- start += length;
+ i += length;
}
return S_OK;
diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c
index 77369a7ef9..251887f508 100644
--- a/dlls/dwrite/tests/analyzer.c
+++ b/dlls/dwrite/tests/analyzer.c
@@ -1738,7 +1738,17 @@ struct spacing_test {
DWRITE_SHAPING_GLYPH_PROPERTIES props[3];
};
-static const struct spacing_test spacing_tests[] = {
+static const struct spacing_test spacing_tests[] =
+{
+/* Default spacing glyph properties. */
+#define P_S { 0 }
+/* isZeroWidthSpace */
+#define P_Z { 0, 0, 0, 1, 0 }
+/* isDiacritic */
+#define P_D { 0, 0, 1, 0, 0 }
+/* isDiacritic + isZeroWidthSpace, that's how diacritics are shaped. */
+#define P_D_Z { 0, 0, 1, 1, 0 }
+
{ 0.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 } }, /* 0 */
{ 0.0, 0.0, 2.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 } },
{ 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 12.0 }, { 3.0, 4.0 } },
@@ -1756,9 +1766,9 @@ static const struct spacing_test spacing_tests[] = {
{ 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 } },
{ -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 6.0 }, { -1.0, -3.0 } }, /* 15 */
/* cluster of more than 1 glyph */
- { 0.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE },
- { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.5 }, { 11.0, 11.0 }, { 3.0, 3.5 }, TRUE },
- { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 12.0 }, { 3.0, 3.0 }, TRUE },
+ { 0.0f, 0.0f, 0.0f, { 10.0f, 11.0f }, { 2.0f, 3.0f }, { 10.0f, 11.0f }, { 2.0f, 3.0f }, TRUE },
+ { 1.0f, 0.0f, 0.0f, { 10.0f, 11.0f }, { 2.0f, 3.5f }, { 11.0f, 11.0f }, { 3.0f, 3.5f }, TRUE },
+ { 1.0f, 1.0f, 0.0f, { 10.0f, 11.0f }, { 2.0f, 3.0f }, { 11.0f, 12.0f }, { 3.0f, 3.0f }, TRUE },
{ 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 10.0 }, { 3.0, 3.0 }, TRUE },
{ 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, TRUE }, /* 20 */
{ 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, TRUE },
@@ -1770,35 +1780,106 @@ static const struct spacing_test spacing_tests[] = {
{ 1.0, -10.0, 5.0, { 2.0, 1.0, 10.0 }, { 2.0, 3.0, 4.0 }, { 3.0, 1.0, 2.0 }, { 3.0, 3.0, 4.0 }, TRUE },
{ -10.0, -10.0, 5.0, { 11.0, 1.0, 11.0 }, { 2.0, 3.0, 4.0 }, { 2.0, 1.0, 2.0 }, { -7.0, 3.0, 4.0 }, TRUE },
/* isZeroWidthSpace set */
- { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 12.0 }, { 2.0, 4.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0 } } },
- { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 13.0 }, { 2.0, 4.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0 } } }, /* 30 */
- { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } },
- { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0 } } },
- { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 11.0 }, { -1.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } },
- { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0 }} },
- { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 7.0, 2.0 }, { 6.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } }, /* 35 */
- { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 8.0, 2.0 }, { 6.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } },
- { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0 } } },
- { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { 3.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } },
- { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0 } } },
- { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 11.0 }, { 2.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } }, /* 40 */
- { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 0, 1, 0 }, { 0 } } },
- { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { -1.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } },
+ { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 12.0 }, { 2.0, 4.0 }, FALSE, { P_Z, P_S } },
+ { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 13.0 }, { 2.0, 4.0 }, FALSE, { P_Z, P_S } }, /* 30 */
+ { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 3.0 }, FALSE, { P_S, P_Z } },
+ { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, FALSE, { P_Z, P_S } },
+ { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 11.0 }, { -1.0, 3.0 }, FALSE, { P_S, P_Z } },
+ { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_Z, P_Z } },
+ { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 7.0, 2.0 }, { 6.0, 3.0 }, FALSE, { P_S, P_Z } }, /* 35 */
+ { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 8.0, 2.0 }, { 6.0, 3.0 }, FALSE, { P_S, P_Z } },
+ { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_Z, P_Z } },
+ { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { 3.0, 3.0 }, FALSE, { P_S, P_Z } },
+ { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_Z, P_Z } },
+ { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_S, P_Z } }, /* 40 */
+ { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, FALSE, { P_Z, P_S } },
+ { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { -1.0, 3.0 }, FALSE, { P_S, P_Z } },
/* isDiacritic */
- { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 12.0 }, { 3.0, 4.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0 } } },
- { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 12.0, 13.0 }, { 3.0, 4.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0 } } },
- { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 4.0 }, FALSE, { { 0 }, { 0, 0, 1, 0, 0 } } }, /* 45 */
- { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 1.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0 } } },
- { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 5.0 }, { -1.0, -0.5 }, FALSE, { { 0 }, { 0, 0, 1, 0, 0 } } },
- { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 5.0 }, { -0.5, 0.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0, 0, 1, 0, 0 }} },
- { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 7.0, 7.0 }, { 6.0, 6.5 }, FALSE, { { 0 }, { 0, 0, 1, 0, 0 } } },
- { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 8.0, 8.0 }, { 6.0, 6.5 }, FALSE, { { 0 }, { 0, 0, 1, 0, 0 } } }, /* 50 */
- { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 7.0, 7.0 }, { 4.0, 5.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0, 0, 1, 0, 0 } } },
- { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { 3.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 0, 1, 0 } } },
- { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 6.0 }, { -3.0, -3.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0, 0, 1, 0, 0 } } },
- { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 5.0 }, { 2.0, 3.0 }, FALSE, { { 0 }, { 0, 0, 1, 0, 0 } } },
- { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, FALSE, { { 0, 0, 1, 0, 0 }, { 0 } } }, /* 55 */
- { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 6.0 }, { -1.0, -3.0 }, FALSE, { { 0 }, { 0, 0, 1, 0, 0 } } },
+ { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 12.0 }, { 3.0, 4.0 }, FALSE, { P_D, P_S } },
+ { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 12.0, 13.0 }, { 3.0, 4.0 }, FALSE, { P_D, P_S } },
+ { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 4.0 }, FALSE, { P_S, P_D } }, /* 45 */
+ { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 1.0 }, { 2.0, 3.0 }, FALSE, { P_D, P_S } },
+ { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 5.0 }, { -1.0, -0.5 }, FALSE, { P_S, P_D } },
+ { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 5.0 }, { -0.5, 0.0 }, FALSE, { P_D, P_D } },
+ { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 7.0, 7.0 }, { 6.0, 6.5 }, FALSE, { P_S, P_D } },
+ { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 8.0, 8.0 }, { 6.0, 6.5 }, FALSE, { P_S, P_D } }, /* 50 */
+ { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 7.0, 7.0 }, { 4.0, 5.0 }, FALSE, { P_D, P_D } },
+ { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 6.0 }, { 3.0, 4.0 }, FALSE, { P_S, P_D } },
+ { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 6.0 }, { -3.0, -3.0 }, FALSE, { P_D, P_D } },
+ { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 5.0 }, { 2.0, 3.0 }, FALSE, { P_S, P_D } },
+ { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, FALSE, { P_D, P_S } }, /* 55 */
+ { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 6.0 }, { -1.0, -3.0 }, FALSE, { P_S, P_D } },
+ /* isZeroWidthSpace in a cluster */
+ { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 12.0 }, { 3.0, 4.0 }, TRUE, { P_Z, P_S } },
+ { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 13.0 }, { 3.0, 4.0 }, TRUE, { P_Z, P_S } },
+ { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 4.0 }, TRUE, { P_S, P_Z } },
+ { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, TRUE, { P_Z, P_S } }, /* 60 */
+ { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 1.0, 11.0 }, { -3.0, 7.0 }, TRUE, { P_S, P_Z } },
+ { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE, { P_Z, P_Z } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 3.0, 2.0 }, { 3.0, 2.0 }, TRUE, { P_S, P_Z } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0, 1.0 }, { 2.0, 3.0, 5.0 }, { 1.5, 2.0, 1.5 }, { 2.5, 3.0, 5.0 }, TRUE, { P_S, P_Z, P_S } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0, 1.0 }, { 2.0, 3.0, 5.0 }, { 1.5, 2.5, 1.0 }, { 2.5, 3.0, 4.5 }, TRUE, { P_S, P_S, P_Z } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0, 1.0 }, { 2.0, 3.0, 5.0 }, { 2.0, 2.0, 1.0 }, { 2.5, 2.5, 4.5 }, TRUE, { P_S, P_Z, P_Z } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0, 1.0 }, { 2.0, 3.0, 5.0 }, { 1.0, 2.0, 1.0 }, { 2.0, 3.0, 5.0 }, TRUE, { P_Z, P_Z, P_Z } },
+ { 2.0, 1.0, 1.0, { 1.0, 2.0, 3.0 }, { 2.0, 3.0, 4.0 }, { 3.0, 2.0, 4.0 }, { 4.0, 3.0, 4.0 }, TRUE, { P_S, P_Z, P_S } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 3.0, 2.0 }, { 3.0, 2.0 }, TRUE, { P_S, P_Z } },
+ { 0.0, 0.0, 5.0, { 1.0, 2.0, 6.0 }, { 2.0, 3.0, 4.0 }, { 1.0, 2.0, 6.0 }, { 2.0, 3.0, 4.0 }, TRUE, { P_S, P_Z, P_S } },
+ { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE, { P_Z, P_Z } }, /* 65 */
+ { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 1.0, 11.0 }, { 3.0, 13.0 }, TRUE, { P_S, P_Z } },
+ { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE, { P_Z, P_Z } },
+ { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 11.0 }, { 2.0, 13.0 }, TRUE, { P_S, P_Z } },
+ { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, TRUE, { P_Z, P_S } },
+ { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { -1.0, 11.0 }, { -8.0, 2.0 }, TRUE, { P_S, P_Z } }, /* 70 */
+ /* isDiacritic in a cluster */
+ { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 11.0 }, { 3.0, 3.0 }, TRUE, { P_D, P_S } },
+ { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 12.0 }, { 3.0, 3.0 }, TRUE, { P_D, P_S } },
+ { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 10.0 }, { 3.0, 3.0 }, TRUE, { P_S, P_D } },
+ { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, TRUE, { P_D, P_S } },
+ { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 7.0 }, { -3.0, 3.0 }, TRUE, { P_S, P_D } }, /* 75 */
+ { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 6.0 }, { -3.0, 3.0 }, TRUE, { P_D, P_D } },
+ { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 4.0, 3.0 }, { 5.0, 3.0 }, TRUE, { P_S, P_D } },
+ { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 4.0, 4.0 }, { 5.0, 3.0 }, TRUE, { P_S, P_D } },
+ { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 12.0, 1.0 }, { 4.0, 3.0 }, TRUE, { P_D, P_D } },
+ { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 11.0, 1.0 }, { 3.0, 3.0 }, TRUE, { P_S, P_D } }, /* 80 */
+ { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 12.0 }, { -8.0, 3.0 }, TRUE, { P_D, P_D } },
+ { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, TRUE, { P_S, P_D } },
+ { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, TRUE, { P_D, P_S } },
+ { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { -2.0, 12.0 }, { -8.0, 3.0 }, TRUE, { P_S, P_D } },
+ /* isZeroWidthSpace + isDiacritic */
+ { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 12.0 }, { 2.0, 4.0 }, FALSE, { P_D_Z, P_S } }, /* 85 */
+ { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 13.0 }, { 2.0, 4.0 }, FALSE, { P_D_Z, P_S } },
+ { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, FALSE, { P_D_Z, P_S } },
+ { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 11.0 }, { -1.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_D_Z, P_D_Z } }, /* 90 */
+ { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 7.0, 2.0 }, { 6.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 8.0, 2.0 }, { 6.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_D_Z, P_D_Z } },
+ { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { 3.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_D_Z, P_D_Z } }, /* 95 */
+ { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 5.0, 11.0 }, { 2.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, FALSE, { P_D_Z, P_S } },
+ { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { 6.0, 11.0 }, { -1.0, 3.0 }, FALSE, { P_S, P_D_Z } },
+ /* isZeroWidthSpace + isDiacritic in a cluster */
+ { 1.0, 0.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 12.0 }, { 3.0, 4.0 }, TRUE, { P_D_Z, P_S } },
+ { 1.0, 1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 13.0 }, { 3.0, 4.0 }, TRUE, { P_D_Z, P_S } }, /* 100 */
+ { 1.0, -1.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 3.0, 4.0 }, TRUE, { P_S, P_D_Z } },
+ { 0.0, -10.0, 0.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 1.0 }, { 2.0, 3.0 }, TRUE, { P_D_Z, P_S } },
+ { -5.0, -4.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 1.0, 11.0 }, { -3.0, 7.0 }, TRUE, { P_S, P_D_Z } },
+ { -5.0, -5.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE, { P_D_Z, P_D_Z } },
+ { 2.0, 0.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 5.0, 2.0 }, { 5.0, 2.0 }, TRUE, { P_S, P_D_Z } }, /* 105 */
+ { 2.0, 1.0, 5.0, { 1.0, 2.0 }, { 2.0, 3.0 }, { 6.0, 2.0 }, { 5.0, 1.0 }, TRUE, { P_S, P_D_Z } },
+ { 2.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE, { P_D_Z, P_D_Z } },
+ { 1.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 1.0, 11.0 }, { 3.0, 13.0 }, TRUE, { P_S, P_D_Z } },
+ { -10.0, 1.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 10.0, 11.0 }, { 2.0, 3.0 }, TRUE, { P_D_Z, P_D_Z } },
+ { 0.0, -10.0, 5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 11.0 }, { 2.0, 13.0 }, TRUE, { P_S, P_D_Z } }, /* 110 */
+ { 1.0, -10.0, -5.0, { 10.0, 11.0 }, { 2.0, 3.0 }, { 0.0, 0.0 }, { 2.0, 3.0 }, TRUE, { P_D_Z, P_S } },
+ { -10.0, 1.0, 5.0, { 8.0, 11.0 }, { 2.0, 3.0 }, { -1.0, 11.0 }, { -8.0, 2.0 }, TRUE, { P_S, P_D_Z } },
+
+#undef P_S
+#undef P_D
+#undef P_Z
+#undef P_D_Z
};
static void test_ApplyCharacterSpacing(void)
@@ -1835,20 +1916,23 @@ static void test_ApplyCharacterSpacing(void)
offsets[1].ascenderOffset = 32.0;
offsets[2].ascenderOffset = 31.0;
+ advances[0] = advances[1] = 123.45f;
+ memcpy(props, ptr->props, sizeof(props));
glyph_count = ptr->advances[2] > 0.0 ? 3 : 2;
- if (ptr->single_cluster) {
+ if (ptr->single_cluster)
+ {
clustermap[0] = 0;
clustermap[1] = 0;
+ props[0].isClusterStart = 1;
}
- else {
+ else
+ {
/* trivial case with one glyph per cluster */
clustermap[0] = 0;
clustermap[1] = 1;
+ props[0].isClusterStart = props[1].isClusterStart = 1;
}
- advances[0] = advances[1] = 123.45;
- memcpy(props, ptr->props, sizeof(props));
-
hr = IDWriteTextAnalyzer1_ApplyCharacterSpacing(analyzer1,
ptr->leading,
ptr->trailing,
--
2.20.1