dwrite/layout: Use array allocation helper for line metrics.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0a3aef62d8
commit
1315098aef
|
@ -227,9 +227,11 @@ struct layout_cluster {
|
||||||
UINT32 position; /* relative to run, first cluster has 0 position */
|
UINT32 position; /* relative to run, first cluster has 0 position */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct layout_line {
|
struct layout_line
|
||||||
FLOAT height; /* height based on content */
|
{
|
||||||
FLOAT baseline; /* baseline based on content */
|
float height; /* height based on content */
|
||||||
|
float baseline; /* baseline based on content */
|
||||||
|
DWRITE_LINE_METRICS1 metrics;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum layout_recompute_mask {
|
enum layout_recompute_mask {
|
||||||
|
@ -276,8 +278,7 @@ struct dwrite_textlayout {
|
||||||
FLOAT minwidth;
|
FLOAT minwidth;
|
||||||
|
|
||||||
struct layout_line *lines;
|
struct layout_line *lines;
|
||||||
DWRITE_LINE_METRICS1 *linemetrics;
|
size_t lines_size;
|
||||||
UINT32 line_alloc;
|
|
||||||
|
|
||||||
DWRITE_TEXT_METRICS1 metrics;
|
DWRITE_TEXT_METRICS1 metrics;
|
||||||
DWRITE_OVERHANG_METRICS overhangs;
|
DWRITE_OVERHANG_METRICS overhangs;
|
||||||
|
@ -1364,16 +1365,16 @@ static void layout_apply_line_spacing(struct dwrite_textlayout *layout, UINT32 l
|
||||||
switch (layout->format.spacing.method)
|
switch (layout->format.spacing.method)
|
||||||
{
|
{
|
||||||
case DWRITE_LINE_SPACING_METHOD_DEFAULT:
|
case DWRITE_LINE_SPACING_METHOD_DEFAULT:
|
||||||
layout->linemetrics[line].height = layout->lines[line].height;
|
layout->lines[line].metrics.height = layout->lines[line].height;
|
||||||
layout->linemetrics[line].baseline = layout->lines[line].baseline;
|
layout->lines[line].metrics.baseline = layout->lines[line].baseline;
|
||||||
break;
|
break;
|
||||||
case DWRITE_LINE_SPACING_METHOD_UNIFORM:
|
case DWRITE_LINE_SPACING_METHOD_UNIFORM:
|
||||||
layout->linemetrics[line].height = layout->format.spacing.height;
|
layout->lines[line].metrics.height = layout->format.spacing.height;
|
||||||
layout->linemetrics[line].baseline = layout->format.spacing.baseline;
|
layout->lines[line].metrics.baseline = layout->format.spacing.baseline;
|
||||||
break;
|
break;
|
||||||
case DWRITE_LINE_SPACING_METHOD_PROPORTIONAL:
|
case DWRITE_LINE_SPACING_METHOD_PROPORTIONAL:
|
||||||
layout->linemetrics[line].height = layout->lines[line].height * layout->format.spacing.height;
|
layout->lines[line].metrics.height = layout->lines[line].height * layout->format.spacing.height;
|
||||||
layout->linemetrics[line].baseline = layout->lines[line].baseline * layout->format.spacing.baseline;
|
layout->lines[line].metrics.baseline = layout->lines[line].baseline * layout->format.spacing.baseline;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR("Unknown spacing method %u\n", layout->format.spacing.method);
|
ERR("Unknown spacing method %u\n", layout->format.spacing.method);
|
||||||
|
@ -1382,37 +1383,15 @@ static void layout_apply_line_spacing(struct dwrite_textlayout *layout, UINT32 l
|
||||||
|
|
||||||
static HRESULT layout_set_line_metrics(struct dwrite_textlayout *layout, DWRITE_LINE_METRICS1 *metrics)
|
static HRESULT layout_set_line_metrics(struct dwrite_textlayout *layout, DWRITE_LINE_METRICS1 *metrics)
|
||||||
{
|
{
|
||||||
UINT32 i = layout->metrics.lineCount;
|
size_t i = layout->metrics.lineCount;
|
||||||
|
|
||||||
if (!layout->line_alloc) {
|
if (!dwrite_array_reserve((void **)&layout->lines, &layout->lines_size, layout->metrics.lineCount + 1,
|
||||||
layout->line_alloc = 5;
|
sizeof(*layout->lines)))
|
||||||
layout->linemetrics = heap_calloc(layout->line_alloc, sizeof(*layout->linemetrics));
|
{
|
||||||
layout->lines = heap_calloc(layout->line_alloc, sizeof(*layout->lines));
|
return E_OUTOFMEMORY;
|
||||||
if (!layout->linemetrics || !layout->lines) {
|
|
||||||
heap_free(layout->linemetrics);
|
|
||||||
heap_free(layout->lines);
|
|
||||||
layout->linemetrics = NULL;
|
|
||||||
layout->lines = NULL;
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout->metrics.lineCount == layout->line_alloc) {
|
layout->lines[i].metrics = *metrics;
|
||||||
DWRITE_LINE_METRICS1 *metrics;
|
|
||||||
struct layout_line *lines;
|
|
||||||
|
|
||||||
if ((metrics = heap_realloc(layout->linemetrics, layout->line_alloc * 2 * sizeof(*layout->linemetrics))))
|
|
||||||
layout->linemetrics = metrics;
|
|
||||||
if ((lines = heap_realloc(layout->lines, layout->line_alloc * 2 * sizeof(*layout->lines))))
|
|
||||||
layout->lines = lines;
|
|
||||||
|
|
||||||
if (!metrics || !lines)
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
layout->line_alloc *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
layout->linemetrics[i] = *metrics;
|
|
||||||
layout->lines[i].height = metrics->height;
|
layout->lines[i].height = metrics->height;
|
||||||
layout->lines[i].baseline = metrics->baseline;
|
layout->lines[i].baseline = metrics->baseline;
|
||||||
|
|
||||||
|
@ -1674,8 +1653,9 @@ static void layout_apply_par_alignment(struct dwrite_textlayout *layout)
|
||||||
|
|
||||||
erun = layout_get_next_erun(layout, NULL);
|
erun = layout_get_next_erun(layout, NULL);
|
||||||
inrun = layout_get_next_inline_run(layout, NULL);
|
inrun = layout_get_next_inline_run(layout, NULL);
|
||||||
for (line = 0; line < layout->metrics.lineCount; line++) {
|
for (line = 0; line < layout->metrics.lineCount; line++)
|
||||||
FLOAT pos_y = origin_y + layout->linemetrics[line].baseline;
|
{
|
||||||
|
float pos_y = origin_y + layout->lines[line].metrics.baseline;
|
||||||
|
|
||||||
while (erun && erun->line == line) {
|
while (erun && erun->line == line) {
|
||||||
erun->origin.y = pos_y;
|
erun->origin.y = pos_y;
|
||||||
|
@ -1687,7 +1667,7 @@ static void layout_apply_par_alignment(struct dwrite_textlayout *layout)
|
||||||
inrun = layout_get_next_inline_run(layout, inrun);
|
inrun = layout_get_next_inline_run(layout, inrun);
|
||||||
}
|
}
|
||||||
|
|
||||||
origin_y += layout->linemetrics[line].height;
|
origin_y += layout->lines[line].metrics.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1992,8 +1972,9 @@ static void layout_set_line_positions(struct dwrite_textlayout *layout)
|
||||||
erun = layout_get_next_erun(layout, NULL);
|
erun = layout_get_next_erun(layout, NULL);
|
||||||
inrun = layout_get_next_inline_run(layout, NULL);
|
inrun = layout_get_next_inline_run(layout, NULL);
|
||||||
|
|
||||||
for (line = 0, origin_y = 0.0f; line < layout->metrics.lineCount; line++) {
|
for (line = 0, origin_y = 0.0f; line < layout->metrics.lineCount; line++)
|
||||||
FLOAT pos_y = origin_y + layout->linemetrics[line].baseline;
|
{
|
||||||
|
float pos_y = origin_y + layout->lines[line].metrics.baseline;
|
||||||
|
|
||||||
/* For all runs on this line */
|
/* For all runs on this line */
|
||||||
while (erun && erun->line == line) {
|
while (erun && erun->line == line) {
|
||||||
|
@ -2007,7 +1988,7 @@ static void layout_set_line_positions(struct dwrite_textlayout *layout)
|
||||||
inrun = layout_get_next_inline_run(layout, inrun);
|
inrun = layout_get_next_inline_run(layout, inrun);
|
||||||
}
|
}
|
||||||
|
|
||||||
origin_y += layout->linemetrics[line].height;
|
origin_y += layout->lines[line].metrics.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
layout->metrics.height = origin_y;
|
layout->metrics.height = origin_y;
|
||||||
|
@ -2862,7 +2843,6 @@ static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout3 *iface)
|
||||||
heap_free(This->actual_breakpoints);
|
heap_free(This->actual_breakpoints);
|
||||||
heap_free(This->clustermetrics);
|
heap_free(This->clustermetrics);
|
||||||
heap_free(This->clusters);
|
heap_free(This->clusters);
|
||||||
heap_free(This->linemetrics);
|
|
||||||
heap_free(This->lines);
|
heap_free(This->lines);
|
||||||
heap_free(This->str);
|
heap_free(This->str);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
|
@ -3574,23 +3554,25 @@ static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout3 *iface,
|
||||||
static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout3 *iface,
|
static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout3 *iface,
|
||||||
DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *count)
|
DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *count)
|
||||||
{
|
{
|
||||||
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout3(iface);
|
struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout3(iface);
|
||||||
|
unsigned int line_count;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
TRACE("(%p)->(%p %u %p)\n", This, metrics, max_count, count);
|
TRACE("%p, %p, %u, %p.\n", iface, metrics, max_count, count);
|
||||||
|
|
||||||
hr = layout_compute_effective_runs(This);
|
if (FAILED(hr = layout_compute_effective_runs(layout)))
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if (metrics) {
|
if (metrics)
|
||||||
UINT32 i, c = min(max_count, This->metrics.lineCount);
|
{
|
||||||
for (i = 0; i < c; i++)
|
line_count = min(max_count, layout->metrics.lineCount);
|
||||||
memcpy(metrics + i, This->linemetrics + i, sizeof(*metrics));
|
for (i = 0; i < line_count; ++i)
|
||||||
|
memcpy(&metrics[i], &layout->lines[i].metrics, sizeof(*metrics));
|
||||||
}
|
}
|
||||||
|
|
||||||
*count = This->metrics.lineCount;
|
*count = layout->metrics.lineCount;
|
||||||
return max_count >= This->metrics.lineCount ? S_OK : E_NOT_SUFFICIENT_BUFFER;
|
return max_count >= layout->metrics.lineCount ? S_OK : E_NOT_SUFFICIENT_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT layout_update_metrics(struct dwrite_textlayout *layout)
|
static HRESULT layout_update_metrics(struct dwrite_textlayout *layout)
|
||||||
|
@ -4061,20 +4043,25 @@ static HRESULT WINAPI dwritetextlayout3_GetLineSpacing(IDWriteTextLayout3 *iface
|
||||||
static HRESULT WINAPI dwritetextlayout3_GetLineMetrics(IDWriteTextLayout3 *iface, DWRITE_LINE_METRICS1 *metrics,
|
static HRESULT WINAPI dwritetextlayout3_GetLineMetrics(IDWriteTextLayout3 *iface, DWRITE_LINE_METRICS1 *metrics,
|
||||||
UINT32 max_count, UINT32 *count)
|
UINT32 max_count, UINT32 *count)
|
||||||
{
|
{
|
||||||
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout3(iface);
|
struct dwrite_textlayout *layout = impl_from_IDWriteTextLayout3(iface);
|
||||||
|
unsigned int line_count;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
TRACE("(%p)->(%p %u %p)\n", This, metrics, max_count, count);
|
TRACE("%p, %p, %u, %p.\n", iface, metrics, max_count, count);
|
||||||
|
|
||||||
hr = layout_compute_effective_runs(This);
|
if (FAILED(hr = layout_compute_effective_runs(layout)))
|
||||||
if (FAILED(hr))
|
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if (metrics)
|
if (metrics)
|
||||||
memcpy(metrics, This->linemetrics, sizeof(*metrics) * min(max_count, This->metrics.lineCount));
|
{
|
||||||
|
line_count = min(max_count, layout->metrics.lineCount);
|
||||||
|
for (i = 0; i < line_count; ++i)
|
||||||
|
metrics[i] = layout->lines[i].metrics;
|
||||||
|
}
|
||||||
|
|
||||||
*count = This->metrics.lineCount;
|
*count = layout->metrics.lineCount;
|
||||||
return max_count >= This->metrics.lineCount ? S_OK : E_NOT_SUFFICIENT_BUFFER;
|
return max_count >= layout->metrics.lineCount ? S_OK : E_NOT_SUFFICIENT_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const IDWriteTextLayout3Vtbl dwritetextlayoutvtbl = {
|
static const IDWriteTextLayout3Vtbl dwritetextlayoutvtbl = {
|
||||||
|
@ -4978,9 +4965,8 @@ static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite
|
||||||
layout->cluster_count = 0;
|
layout->cluster_count = 0;
|
||||||
layout->clustermetrics = NULL;
|
layout->clustermetrics = NULL;
|
||||||
layout->clusters = NULL;
|
layout->clusters = NULL;
|
||||||
layout->linemetrics = NULL;
|
|
||||||
layout->lines = NULL;
|
layout->lines = NULL;
|
||||||
layout->line_alloc = 0;
|
layout->lines_size = 0;
|
||||||
layout->minwidth = 0.0f;
|
layout->minwidth = 0.0f;
|
||||||
list_init(&layout->eruns);
|
list_init(&layout->eruns);
|
||||||
list_init(&layout->inlineobjects);
|
list_init(&layout->inlineobjects);
|
||||||
|
|
Loading…
Reference in New Issue