[PATCH 1/4] dwrite: Implement newer SetLineSpacing/GetLineSpacing

Nikolay Sivov nsivov at codeweavers.com
Mon Jul 25 03:42:54 CDT 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/layout.c       | 118 ++++++++++++++++++++++++++++-----------------
 dlls/dwrite/tests/layout.c | 102 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 165 insertions(+), 55 deletions(-)

diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 6f10ce4..67f6fe2 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -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;
diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c
index 4134a97..03038d8 100644
--- a/dlls/dwrite/tests/layout.c
+++ b/dlls/dwrite/tests/layout.c
@@ -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);
 }
-- 
2.8.1




More information about the wine-patches mailing list