mirror of
https://github.com/reactos/wine.git
synced 2024-12-12 05:45:56 +00:00
dwrite: Fix cluster width and length calculation.
This commit is contained in:
parent
52df833a72
commit
0c116d7736
@ -362,14 +362,34 @@ static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout,
|
||||
|
||||
static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos);
|
||||
|
||||
static void init_cluster_metrics(const struct layout_run *run, DWRITE_CLUSTER_METRICS *metrics)
|
||||
static inline DWRITE_LINE_BREAKPOINT get_effective_breakpoint(const struct dwrite_textlayout *layout, UINT32 pos)
|
||||
{
|
||||
if (layout->actual_breakpoints)
|
||||
return layout->actual_breakpoints[pos];
|
||||
return layout->nominal_breakpoints[pos];
|
||||
}
|
||||
|
||||
static inline void init_cluster_metrics(const struct dwrite_textlayout *layout, const struct layout_run *run,
|
||||
UINT16 start_glyph, UINT16 stop_glyph, UINT32 stop_position, DWRITE_CLUSTER_METRICS *metrics)
|
||||
{
|
||||
UINT8 breakcondition;
|
||||
UINT16 j;
|
||||
|
||||
metrics->width = 0.0;
|
||||
metrics->length = 1;
|
||||
metrics->canWrapLineAfter = FALSE;
|
||||
metrics->isWhitespace = FALSE;
|
||||
metrics->isNewline = FALSE;
|
||||
metrics->isSoftHyphen = FALSE;
|
||||
for (j = start_glyph; j < stop_glyph; j++)
|
||||
metrics->width += run->run.glyphAdvances[j];
|
||||
metrics->length = 0;
|
||||
|
||||
if (stop_glyph == run->run.glyphCount)
|
||||
breakcondition = get_effective_breakpoint(layout, stop_position).breakConditionAfter;
|
||||
else
|
||||
breakcondition = get_effective_breakpoint(layout, stop_position).breakConditionBefore;
|
||||
|
||||
metrics->canWrapLineAfter = breakcondition == DWRITE_BREAK_CONDITION_CAN_BREAK ||
|
||||
breakcondition == DWRITE_BREAK_CONDITION_MUST_BREAK;
|
||||
metrics->isWhitespace = FALSE; /* FIXME */
|
||||
metrics->isNewline = FALSE; /* FIXME */
|
||||
metrics->isSoftHyphen = FALSE; /* FIXME */
|
||||
metrics->isRightToLeft = run->run.bidiLevel & 1;
|
||||
metrics->padding = 0;
|
||||
}
|
||||
@ -378,42 +398,34 @@ static void init_cluster_metrics(const struct layout_run *run, DWRITE_CLUSTER_ME
|
||||
|
||||
All clusters in a 'run' will be added to 'layout' data, starting at index pointed to by 'cluster'.
|
||||
On return 'cluster' is updated to point to next metrics struct to be filled in on next call.
|
||||
Note that there's no need to reallocate anything at this point as we allocate one cluster per
|
||||
codepoint initially.
|
||||
|
||||
*/
|
||||
static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const struct layout_run *run, UINT32 *cluster)
|
||||
{
|
||||
DWRITE_CLUSTER_METRICS *metrics = &layout->clusters[*cluster];
|
||||
UINT16 glyph;
|
||||
UINT32 i;
|
||||
|
||||
glyph = run->descr.clusterMap[0];
|
||||
init_cluster_metrics(run, metrics);
|
||||
UINT32 i, start = 0;
|
||||
|
||||
for (i = 0; i < run->descr.stringLength; i++) {
|
||||
BOOL newcluster = glyph != run->descr.clusterMap[i];
|
||||
BOOL end = i == run->descr.stringLength - 1;
|
||||
|
||||
/* add new cluster on starting glyph change or simply when run is over */
|
||||
if (newcluster || i == run->descr.stringLength - 1) {
|
||||
UINT8 breakcondition;
|
||||
UINT16 j;
|
||||
if (run->descr.clusterMap[start] != run->descr.clusterMap[i]) {
|
||||
init_cluster_metrics(layout, run, run->descr.clusterMap[start], run->descr.clusterMap[i], i, metrics);
|
||||
metrics->length = i - start;
|
||||
|
||||
for (j = glyph; j < run->descr.clusterMap[i]; j++)
|
||||
metrics->width += run->run.glyphAdvances[j];
|
||||
|
||||
/* FIXME: also set isWhitespace, isNewline and isSoftHyphen */
|
||||
breakcondition = newcluster ? layout->nominal_breakpoints[i].breakConditionBefore :
|
||||
layout->nominal_breakpoints[i].breakConditionAfter;
|
||||
metrics->canWrapLineAfter = breakcondition == DWRITE_BREAK_CONDITION_CAN_BREAK ||
|
||||
breakcondition == DWRITE_BREAK_CONDITION_MUST_BREAK;
|
||||
|
||||
/* advance to next cluster */
|
||||
glyph = run->descr.clusterMap[i];
|
||||
*cluster += 1;
|
||||
metrics++;
|
||||
init_cluster_metrics(run, metrics);
|
||||
start = i;
|
||||
}
|
||||
|
||||
if (end) {
|
||||
init_cluster_metrics(layout, run, run->descr.clusterMap[start], run->run.glyphCount, i, metrics);
|
||||
metrics->length = i - start + 1;
|
||||
|
||||
*cluster += 1;
|
||||
return;
|
||||
}
|
||||
else
|
||||
metrics->length++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,7 +595,7 @@ static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
|
||||
}
|
||||
|
||||
if (hr == S_OK)
|
||||
layout->clusters_count = cluster + 1;
|
||||
layout->clusters_count = cluster;
|
||||
|
||||
IDWriteTextAnalyzer_Release(analyzer);
|
||||
return hr;
|
||||
@ -613,6 +625,10 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout)
|
||||
0, layout->len, &layout->IDWriteTextAnalysisSink_iface);
|
||||
IDWriteTextAnalyzer_Release(analyzer);
|
||||
}
|
||||
if (layout->actual_breakpoints) {
|
||||
heap_free(layout->actual_breakpoints);
|
||||
layout->actual_breakpoints = NULL;
|
||||
}
|
||||
|
||||
hr = layout_compute_runs(layout);
|
||||
|
||||
|
@ -993,13 +993,13 @@ static void test_GetClusterMetrics(void)
|
||||
{
|
||||
static const WCHAR strW[] = {'a','b','c','d',0};
|
||||
DWRITE_INLINE_OBJECT_METRICS inline_metrics;
|
||||
DWRITE_CLUSTER_METRICS metrics;
|
||||
DWRITE_CLUSTER_METRICS metrics[4];
|
||||
IDWriteInlineObject *trimm;
|
||||
IDWriteTextFormat *format;
|
||||
IDWriteTextLayout *layout;
|
||||
DWRITE_TEXT_RANGE range;
|
||||
IDWriteFactory *factory;
|
||||
UINT32 count;
|
||||
UINT32 count, i;
|
||||
HRESULT hr;
|
||||
|
||||
factory = create_factory();
|
||||
@ -1016,6 +1016,16 @@ static void test_GetClusterMetrics(void)
|
||||
ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
|
||||
ok(count == 4, "got %u\n", count);
|
||||
|
||||
/* check every cluster width */
|
||||
count = 0;
|
||||
hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, sizeof(metrics)/sizeof(metrics[0]), &count);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(count == 4, "got %u\n", count);
|
||||
for (i = 0; i < count; i++) {
|
||||
ok(metrics[i].width > 0.0, "%u: got width %.2f\n", i, metrics[i].width);
|
||||
ok(metrics[i].length == 1, "%u: got length %u\n", i, metrics[i].length);
|
||||
}
|
||||
|
||||
hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &trimm);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
@ -1033,17 +1043,17 @@ todo_wine
|
||||
|
||||
count = 0;
|
||||
memset(&metrics, 0, sizeof(metrics));
|
||||
hr = IDWriteTextLayout_GetClusterMetrics(layout, &metrics, 1, &count);
|
||||
hr = IDWriteTextLayout_GetClusterMetrics(layout, metrics, 1, &count);
|
||||
ok(hr == E_NOT_SUFFICIENT_BUFFER, "got 0x%08x\n", hr);
|
||||
todo_wine
|
||||
todo_wine {
|
||||
ok(count == 3, "got %u\n", count);
|
||||
ok(metrics.length == 2, "got %u\n", metrics.length);
|
||||
|
||||
ok(metrics[0].length == 2, "got %u\n", metrics[0].length);
|
||||
}
|
||||
hr = IDWriteInlineObject_GetMetrics(trimm, &inline_metrics);
|
||||
todo_wine {
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(inline_metrics.width == metrics.width, "got %.2f, expected %.2f\n", inline_metrics.width,
|
||||
metrics.width);
|
||||
ok(inline_metrics.width == metrics[0].width, "got %.2f, expected %.2f\n", inline_metrics.width,
|
||||
metrics[0].width);
|
||||
}
|
||||
IDWriteInlineObject_Release(trimm);
|
||||
IDWriteTextLayout_Release(layout);
|
||||
|
Loading…
Reference in New Issue
Block a user