mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
dwrite/layout: Add support for character spacing attributes.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f18acbfef3
commit
8dac512e8c
2 changed files with 81 additions and 2 deletions
|
@ -1144,6 +1144,82 @@ static HRESULT layout_shape_get_glyphs(struct dwrite_textlayout *layout, struct
|
|||
return hr;
|
||||
}
|
||||
|
||||
static struct layout_range_spacing *layout_get_next_spacing_range(struct dwrite_textlayout *layout,
|
||||
struct layout_range_spacing *cur)
|
||||
{
|
||||
return (struct layout_range_spacing *)LIST_ENTRY(list_next(&layout->spacing, &cur->h.entry),
|
||||
struct layout_range_header, entry);
|
||||
}
|
||||
|
||||
static HRESULT layout_shape_apply_character_spacing(struct dwrite_textlayout *layout, struct shaping_context *context)
|
||||
{
|
||||
struct regular_layout_run *run = context->run;
|
||||
struct layout_range_spacing *first = NULL, *last = NULL, *cur;
|
||||
unsigned int i, length, pos, start, end, g0, glyph_count;
|
||||
struct layout_range_header *h;
|
||||
UINT16 *clustermap;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(h, &layout->spacing, struct layout_range_header, entry)
|
||||
{
|
||||
if ((h->range.startPosition >= run->descr.textPosition &&
|
||||
h->range.startPosition <= run->descr.textPosition + run->descr.stringLength) ||
|
||||
(run->descr.textPosition >= h->range.startPosition &&
|
||||
run->descr.textPosition <= h->range.startPosition + h->range.length))
|
||||
{
|
||||
if (!first) first = last = (struct layout_range_spacing *)h;
|
||||
}
|
||||
else if (last) break;
|
||||
}
|
||||
if (!first) return S_OK;
|
||||
|
||||
if (!(clustermap = heap_calloc(run->descr.stringLength, sizeof(*clustermap)))) return E_OUTOFMEMORY;
|
||||
|
||||
pos = run->descr.textPosition;
|
||||
|
||||
for (cur = first;; cur = layout_get_next_spacing_range(layout, cur))
|
||||
{
|
||||
float leading, trailing;
|
||||
|
||||
/* The range current spacing settings apply to. */
|
||||
start = max(pos, cur->h.range.startPosition);
|
||||
pos = end = min(pos + run->descr.stringLength, cur->h.range.startPosition + cur->h.range.length);
|
||||
|
||||
/* Back to run-relative index. */
|
||||
start -= run->descr.textPosition;
|
||||
end -= run->descr.textPosition;
|
||||
|
||||
length = end - start;
|
||||
|
||||
g0 = run->descr.clusterMap[start];
|
||||
|
||||
for (i = 0; i < length; ++i)
|
||||
clustermap[i] = run->descr.clusterMap[start + i] - run->descr.clusterMap[start];
|
||||
|
||||
glyph_count = (end < run->descr.stringLength ? run->descr.clusterMap[end] + 1 : run->glyphcount) - g0;
|
||||
|
||||
/* There is no direction argument for spacing interface, we have to swap arguments here to get desired output. */
|
||||
if (run->run.bidiLevel & 1)
|
||||
{
|
||||
leading = cur->trailing;
|
||||
trailing = cur->leading;
|
||||
}
|
||||
else
|
||||
{
|
||||
leading = cur->leading;
|
||||
trailing = cur->trailing;
|
||||
}
|
||||
IDWriteTextAnalyzer2_ApplyCharacterSpacing(context->analyzer, leading, trailing, cur->min_advance,
|
||||
length, glyph_count, clustermap, &run->advances[g0], &run->offsets[g0], &context->glyph_props[g0],
|
||||
&run->advances[g0], &run->offsets[g0]);
|
||||
|
||||
if (cur == last) break;
|
||||
}
|
||||
|
||||
heap_free(clustermap);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, struct shaping_context *context)
|
||||
{
|
||||
struct regular_layout_run *run = context->run;
|
||||
|
@ -1176,6 +1252,9 @@ static HRESULT layout_shape_get_positions(struct dwrite_textlayout *layout, stru
|
|||
WARN("%s: failed to get glyph placement info, hr %#x.\n", debugstr_rundescr(&run->descr), hr);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
hr = layout_shape_apply_character_spacing(layout, context);
|
||||
|
||||
run->run.glyphAdvances = run->advances;
|
||||
run->run.glyphOffsets = run->offsets;
|
||||
|
||||
|
|
|
@ -2121,8 +2121,8 @@ static void test_GetClusterMetrics(void)
|
|||
hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics2, ARRAY_SIZE(metrics2), &count);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(count == 4, "got %u\n", count);
|
||||
for (i = 0; i < count; i++) {
|
||||
todo_wine
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
ok(metrics2[i].width > metrics[i].width, "%u: got width %.2f, was %.2f\n", i, metrics2[i].width,
|
||||
metrics[i].width);
|
||||
ok(metrics2[i].length == 1, "%u: got length %u\n", i, metrics2[i].length);
|
||||
|
|
Loading…
Reference in a new issue