dwrite: Implement newer SetLineSpacing/GetLineSpacing.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2016-07-25 11:42:54 +03:00 committed by Alexandre Julliard
parent 0d57ff3d1f
commit 9ec714db5d
2 changed files with 165 additions and 55 deletions

View File

@ -47,12 +47,10 @@ struct dwrite_textformat_data {
BOOL last_line_wrapping;
DWRITE_TEXT_ALIGNMENT textalignment;
DWRITE_FLOW_DIRECTION flow;
DWRITE_LINE_SPACING_METHOD spacingmethod;
DWRITE_VERTICAL_GLYPH_ORIENTATION vertical_orientation;
DWRITE_OPTICAL_ALIGNMENT optical_alignment;
DWRITE_LINE_SPACING spacing;
FLOAT spacing;
FLOAT baseline;
FLOAT fontsize;
DWRITE_TRIMMING trimming;
@ -436,17 +434,16 @@ static inline HRESULT format_set_trimming(struct dwrite_textformat_data *format,
}
static inline HRESULT format_set_linespacing(struct dwrite_textformat_data *format,
DWRITE_LINE_SPACING_METHOD method, FLOAT spacing, FLOAT baseline, BOOL *changed)
DWRITE_LINE_SPACING const *spacing, BOOL *changed)
{
if (spacing < 0.0f || (UINT32)method > DWRITE_LINE_SPACING_METHOD_UNIFORM)
if (spacing->height < 0.0f || spacing->leadingBefore < 0.0f || spacing->leadingBefore > 1.0f ||
(UINT32)spacing->method > DWRITE_LINE_SPACING_METHOD_PROPORTIONAL)
return E_INVALIDARG;
if (changed) *changed = format->spacingmethod != method ||
format->spacing != spacing || format->baseline != baseline;
if (changed)
*changed = memcmp(spacing, &format->spacing, sizeof(*spacing));
format->spacingmethod = method;
format->spacing = spacing;
format->baseline = baseline;
format->spacing = *spacing;
return S_OK;
}
@ -3654,15 +3651,29 @@ static HRESULT WINAPI dwritetextlayout3_InvalidateLayout(IDWriteTextLayout3 *ifa
static HRESULT WINAPI dwritetextlayout3_SetLineSpacing(IDWriteTextLayout3 *iface, DWRITE_LINE_SPACING const *spacing)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout3(iface);
FIXME("(%p)->(%p): stub\n", This, spacing);
return E_NOTIMPL;
BOOL changed;
HRESULT hr;
TRACE("(%p)->(%p)\n", This, spacing);
hr = format_set_linespacing(&This->format, spacing, &changed);
if (FAILED(hr))
return hr;
if (changed)
This->recompute = RECOMPUTE_EVERYTHING;
return S_OK;
}
static HRESULT WINAPI dwritetextlayout3_GetLineSpacing(IDWriteTextLayout3 *iface, DWRITE_LINE_SPACING *spacing)
{
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout3(iface);
FIXME("(%p)->(%p): stub\n", This, spacing);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, spacing);
*spacing = This->format.spacing;
return S_OK;
}
static HRESULT WINAPI dwritetextlayout3_GetLineMetrics(IDWriteTextLayout3 *iface, DWRITE_LINE_METRICS1 *metrics,
@ -3896,22 +3907,18 @@ static HRESULT WINAPI dwritetextformat_layout_SetTrimming(IDWriteTextFormat1 *if
}
static HRESULT WINAPI dwritetextformat_layout_SetLineSpacing(IDWriteTextFormat1 *iface, DWRITE_LINE_SPACING_METHOD method,
FLOAT spacing, FLOAT baseline)
FLOAT height, FLOAT baseline)
{
struct dwrite_textlayout *This = impl_layout_from_IDWriteTextFormat1(iface);
BOOL changed;
HRESULT hr;
DWRITE_LINE_SPACING spacing;
TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
TRACE("(%p)->(%d %f %f)\n", This, method, height, baseline);
hr = format_set_linespacing(&This->format, method, spacing, baseline, &changed);
if (FAILED(hr))
return hr;
if (changed)
This->recompute = RECOMPUTE_EVERYTHING;
return S_OK;
spacing = This->format.spacing;
spacing.method = method;
spacing.height = height;
spacing.baseline = baseline;
return IDWriteTextLayout3_SetLineSpacing(&This->IDWriteTextLayout3_iface, &spacing);
}
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_layout_GetTextAlignment(IDWriteTextFormat1 *iface)
@ -3977,9 +3984,9 @@ static HRESULT WINAPI dwritetextformat_layout_GetLineSpacing(IDWriteTextFormat1
TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
*method = This->format.spacingmethod;
*spacing = This->format.spacing;
*baseline = This->format.baseline;
*method = This->format.spacing.method;
*spacing = This->format.spacing.height;
*baseline = This->format.spacing.baseline;
return S_OK;
}
@ -4462,8 +4469,10 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I
layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
layout->format.fallback = NULL;
hr = IDWriteTextFormat_GetLineSpacing(format, &layout->format.spacingmethod,
&layout->format.spacing, &layout->format.baseline);
layout->format.spacing.leadingBefore = 0.0f;
layout->format.spacing.fontLineGapUsage = DWRITE_FONT_LINE_GAP_USAGE_DEFAULT;
hr = IDWriteTextFormat_GetLineSpacing(format, &layout->format.spacing.method,
&layout->format.spacing.height, &layout->format.spacing.baseline);
if (FAILED(hr))
return hr;
@ -4495,9 +4504,17 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I
hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat1, (void**)&format1);
if (hr == S_OK) {
IDWriteTextFormat2 *format2;
layout->format.vertical_orientation = IDWriteTextFormat1_GetVerticalGlyphOrientation(format1);
layout->format.optical_alignment = IDWriteTextFormat1_GetOpticalAlignment(format1);
IDWriteTextFormat1_GetFontFallback(format1, &layout->format.fallback);
if (IDWriteTextFormat1_QueryInterface(format1, &IID_IDWriteTextFormat2, (void**)&format2) == S_OK) {
IDWriteTextFormat2_GetLineSpacing(format2, &layout->format.spacing);
IDWriteTextFormat2_Release(format2);
}
IDWriteTextFormat1_Release(format1);
}
else {
@ -4879,11 +4896,19 @@ static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat2 *iface, DW
}
static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING_METHOD method,
FLOAT spacing, FLOAT baseline)
FLOAT height, FLOAT baseline)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface);
TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
return format_set_linespacing(&This->format, method, spacing, baseline, NULL);
DWRITE_LINE_SPACING spacing;
TRACE("(%p)->(%d %f %f)\n", This, method, height, baseline);
spacing = This->format.spacing;
spacing.method = method;
spacing.height = height;
spacing.baseline = baseline;
return format_set_linespacing(&This->format, &spacing, NULL);
}
static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat2 *iface)
@ -4947,9 +4972,9 @@ static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat2 *iface,
struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface);
TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
*method = This->format.spacingmethod;
*spacing = This->format.spacing;
*baseline = This->format.baseline;
*method = This->format.spacing.method;
*spacing = This->format.spacing.height;
*baseline = This->format.spacing.baseline;
return S_OK;
}
@ -5097,15 +5122,18 @@ static HRESULT WINAPI dwritetextformat1_GetFontFallback(IDWriteTextFormat2 *ifac
static HRESULT WINAPI dwritetextformat2_SetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING const *spacing)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface);
FIXME("(%p)->(%p): stub\n", This, spacing);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, spacing);
return format_set_linespacing(&This->format, spacing, NULL);
}
static HRESULT WINAPI dwritetextformat2_GetLineSpacing(IDWriteTextFormat2 *iface, DWRITE_LINE_SPACING *spacing)
{
struct dwrite_textformat *This = impl_from_IDWriteTextFormat2(iface);
FIXME("(%p)->(%p): stub\n", This, spacing);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, spacing);
*spacing = This->format.spacing;
return S_OK;
}
static const IDWriteTextFormat2Vtbl dwritetextformatvtbl = {
@ -5192,10 +5220,12 @@ HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *colle
This->format.last_line_wrapping = TRUE;
This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
This->format.spacing.method = DWRITE_LINE_SPACING_METHOD_DEFAULT;
This->format.spacing.height = 0.0f;
This->format.spacing.baseline = 0.0f;
This->format.spacing.leadingBefore = 0.0f;
This->format.spacing.fontLineGapUsage = DWRITE_FONT_LINE_GAP_USAGE_DEFAULT;
This->format.vertical_orientation = DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
This->format.spacing = 0.0f;
This->format.baseline = 0.0f;
This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
This->format.trimming.delimiter = 0;
This->format.trimming.delimiterCount = 0;

View File

@ -1054,17 +1054,6 @@ if (0) /* crashes on native */
hr = IDWriteTextFormat_SetFlowDirection(format, DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0, 0.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0, -10.0);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, -10.0, 0.0);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL+1, 0.0, 0.0);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetTrimming(format, &trimming, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
@ -5002,6 +4991,96 @@ static void test_InvalidateLayout(void)
IDWriteFactory_Release(factory);
}
static void test_line_spacing(void)
{
static const WCHAR strW[] = {'a',0};
IDWriteTextFormat2 *format2;
IDWriteTextLayout *layout;
IDWriteTextFormat *format;
IDWriteFactory *factory;
HRESULT hr;
factory = create_factory();
hr = IDWriteFactory_CreateTextFormat(factory, tahomaW, NULL, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL, 10.0f, enusW, &format);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, 0.0f);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, -10.0f);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_DEFAULT, -10.0f, 0.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteTextFormat_SetLineSpacing(format, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL+1, 0.0f, 0.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteFactory_CreateTextLayout(factory, strW, 1, format, 1000.0f, 1000.0f, &layout);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, 0.0f);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, 0.0f, -10.0f);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_DEFAULT, -10.0f, 0.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = IDWriteTextLayout_SetLineSpacing(layout, DWRITE_LINE_SPACING_METHOD_PROPORTIONAL+1, 0.0f, 0.0f);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
if (IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat2, (void**)&format2) == S_OK) {
DWRITE_LINE_SPACING spacing;
hr = IDWriteTextFormat2_GetLineSpacing(format2, &spacing);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(spacing.method == DWRITE_LINE_SPACING_METHOD_DEFAULT, "got method %d\n", spacing.method);
ok(spacing.height == 0.0f, "got %f\n", spacing.height);
ok(spacing.baseline == -10.0f, "got %f\n", spacing.baseline);
ok(spacing.leadingBefore == 0.0f, "got %f\n", spacing.leadingBefore);
ok(spacing.fontLineGapUsage == DWRITE_FONT_LINE_GAP_USAGE_DEFAULT, "got %f\n", spacing.leadingBefore);
spacing.leadingBefore = -1.0f;
hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
spacing.leadingBefore = 1.1f;
hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
spacing.leadingBefore = 1.0f;
hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
ok(hr == S_OK, "got 0x%08x\n", hr);
spacing.method = DWRITE_LINE_SPACING_METHOD_PROPORTIONAL + 1;
hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
spacing.method = DWRITE_LINE_SPACING_METHOD_PROPORTIONAL;
spacing.fontLineGapUsage = DWRITE_FONT_LINE_GAP_USAGE_ENABLED + 1;
hr = IDWriteTextFormat2_SetLineSpacing(format2, &spacing);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteTextFormat2_GetLineSpacing(format2, &spacing);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(spacing.fontLineGapUsage == DWRITE_FONT_LINE_GAP_USAGE_ENABLED + 1, "got %d\n", spacing.fontLineGapUsage);
IDWriteTextFormat2_Release(format2);
}
IDWriteTextLayout_Release(layout);
IDWriteTextFormat_Release(format);
IDWriteFactory_Release(factory);
}
START_TEST(layout)
{
IDWriteFactory *factory;
@ -5050,6 +5129,7 @@ START_TEST(layout)
test_SetOpticalAlignment();
test_SetUnderline();
test_InvalidateLayout();
test_line_spacing();
IDWriteFactory_Release(factory);
}