[PATCH 2/7] dwrite: Store per-range typography property

Nikolay Sivov nsivov at codeweavers.com
Fri Dec 25 06:57:57 CST 2015


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/layout.c       | 101 +++++++++++++++++++++++++++++++--------------
 dlls/dwrite/tests/layout.c |  57 +++++++++++++++++++++++++
 2 files changed, 126 insertions(+), 32 deletions(-)

diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 22c36a3..66998b6 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -74,7 +74,8 @@ enum layout_range_attr_kind {
     LAYOUT_RANGE_ATTR_FONTCOLL,
     LAYOUT_RANGE_ATTR_LOCALE,
     LAYOUT_RANGE_ATTR_FONTFAMILY,
-    LAYOUT_RANGE_ATTR_SPACING
+    LAYOUT_RANGE_ATTR_SPACING,
+    LAYOUT_RANGE_ATTR_TYPOGRAPHY
 };
 
 struct layout_range_attr_value {
@@ -93,6 +94,7 @@ struct layout_range_attr_value {
         const WCHAR *locale;
         const WCHAR *fontfamily;
         FLOAT spacing[3]; /* in arguments order - leading, trailing, advance */
+        IDWriteTypography *typography;
     } u;
 };
 
@@ -100,7 +102,8 @@ enum layout_range_kind {
     LAYOUT_RANGE_REGULAR,
     LAYOUT_RANGE_STRIKETHROUGH,
     LAYOUT_RANGE_EFFECT,
-    LAYOUT_RANGE_SPACING
+    LAYOUT_RANGE_SPACING,
+    LAYOUT_RANGE_TYPOGRAPHY
 };
 
 struct layout_range_header {
@@ -128,9 +131,9 @@ struct layout_range_bool {
     BOOL value;
 };
 
-struct layout_range_effect {
+struct layout_range_iface {
     struct layout_range_header h;
-    IUnknown *effect;
+    IUnknown *iface;
 };
 
 struct layout_range_spacing {
@@ -229,6 +232,7 @@ struct dwrite_textlayout {
     UINT32 len;
     struct dwrite_textformat_data format;
     struct list strike_ranges;
+    struct list typographies;
     struct list effects;
     struct list spacing;
     struct list ranges;
@@ -961,7 +965,7 @@ static struct layout_range_header *get_layout_range_header_by_pos(struct list *r
 static inline IUnknown *layout_get_effect_from_pos(struct dwrite_textlayout *layout, UINT32 pos)
 {
     struct layout_range_header *h = get_layout_range_header_by_pos(&layout->effects, pos);
-    return ((struct layout_range_effect*)h)->effect;
+    return ((struct layout_range_iface*)h)->iface;
 }
 
 static inline BOOL layout_is_erun_rtl(const struct layout_effective_run *erun)
@@ -1557,7 +1561,7 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
 static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
 {
     struct layout_range_spacing const *range_spacing = (struct layout_range_spacing*)h;
-    struct layout_range_effect const *range_effect = (struct layout_range_effect*)h;
+    struct layout_range_iface const *range_iface = (struct layout_range_iface*)h;
     struct layout_range_bool const *range_bool = (struct layout_range_bool*)h;
     struct layout_range const *range = (struct layout_range*)h;
 
@@ -1573,7 +1577,7 @@ static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum l
     case LAYOUT_RANGE_ATTR_INLINE:
         return range->object == value->u.object;
     case LAYOUT_RANGE_ATTR_EFFECT:
-        return range_effect->effect == value->u.effect;
+        return range_iface->iface == value->u.effect;
     case LAYOUT_RANGE_ATTR_UNDERLINE:
         return range->underline == value->u.underline;
     case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
@@ -1590,6 +1594,8 @@ static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum l
         return range_spacing->leading == value->u.spacing[0] &&
                range_spacing->trailing == value->u.spacing[1] &&
                range_spacing->min_advance == value->u.spacing[2];
+    case LAYOUT_RANGE_ATTR_TYPOGRAPHY:
+        return range_iface->iface == (IUnknown*)value->u.typography;
     default:
         ;
     }
@@ -1623,10 +1629,11 @@ static inline BOOL is_same_layout_attributes(struct layout_range_header const *h
         return left->value == right->value;
     }
     case LAYOUT_RANGE_EFFECT:
+    case LAYOUT_RANGE_TYPOGRAPHY:
     {
-        struct layout_range_effect const *left = (struct layout_range_effect const*)hleft;
-        struct layout_range_effect const *right = (struct layout_range_effect const*)hright;
-        return left->effect == right->effect;
+        struct layout_range_iface const *left = (struct layout_range_iface const*)hleft;
+        struct layout_range_iface const *right = (struct layout_range_iface const*)hright;
+        return left->iface == right->iface;
     }
     case LAYOUT_RANGE_SPACING:
     {
@@ -1696,13 +1703,14 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
         break;
     }
     case LAYOUT_RANGE_EFFECT:
+    case LAYOUT_RANGE_TYPOGRAPHY:
     {
-        struct layout_range_effect *range;
+        struct layout_range_iface *range;
 
         range = heap_alloc(sizeof(*range));
         if (!range) return NULL;
 
-        range->effect = NULL;
+        range->iface = NULL;
         h = &range->h;
         break;
     }
@@ -1767,13 +1775,14 @@ static struct layout_range_header *alloc_layout_range_from(struct layout_range_h
         break;
     }
     case LAYOUT_RANGE_EFFECT:
+    case LAYOUT_RANGE_TYPOGRAPHY:
     {
-        struct layout_range_effect *effect = heap_alloc(sizeof(*effect));
+        struct layout_range_iface *effect = heap_alloc(sizeof(*effect));
         if (!effect) return NULL;
 
-        *effect = *(struct layout_range_effect*)h;
-        if (effect->effect)
-            IUnknown_AddRef(effect->effect);
+        *effect = *(struct layout_range_iface*)h;
+        if (effect->iface)
+            IUnknown_AddRef(effect->iface);
         ret = &effect->h;
         break;
     }
@@ -1814,10 +1823,11 @@ static void free_layout_range(struct layout_range_header *h)
         break;
     }
     case LAYOUT_RANGE_EFFECT:
+    case LAYOUT_RANGE_TYPOGRAPHY:
     {
-        struct layout_range_effect *effect = (struct layout_range_effect*)h;
-        if (effect->effect)
-            IUnknown_Release(effect->effect);
+        struct layout_range_iface *range = (struct layout_range_iface*)h;
+        if (range->iface)
+            IUnknown_Release(range->iface);
         break;
     }
     default:
@@ -1850,6 +1860,11 @@ static void free_layout_ranges_list(struct dwrite_textlayout *layout)
         list_remove(&cur->entry);
         free_layout_range(cur);
     }
+
+    LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->typographies, struct layout_range_header, entry) {
+        list_remove(&cur->entry);
+        free_layout_range(cur);
+    }
 }
 
 static struct layout_range_header *find_outer_range(struct list *ranges, const DWRITE_TEXT_RANGE *range)
@@ -1900,7 +1915,7 @@ static inline BOOL set_layout_range_iface_attr(IUnknown **dest, IUnknown *value)
 static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
 {
     struct layout_range_spacing *dest_spacing = (struct layout_range_spacing*)h;
-    struct layout_range_effect *dest_effect = (struct layout_range_effect*)h;
+    struct layout_range_iface *dest_iface = (struct layout_range_iface*)h;
     struct layout_range_bool *dest_bool = (struct layout_range_bool*)h;
     struct layout_range *dest = (struct layout_range*)h;
 
@@ -1927,7 +1942,7 @@ static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_
         changed = set_layout_range_iface_attr((IUnknown**)&dest->object, (IUnknown*)value->u.object);
         break;
     case LAYOUT_RANGE_ATTR_EFFECT:
-        changed = set_layout_range_iface_attr((IUnknown**)&dest_effect->effect, (IUnknown*)value->u.effect);
+        changed = set_layout_range_iface_attr((IUnknown**)&dest_iface->iface, (IUnknown*)value->u.effect);
         break;
     case LAYOUT_RANGE_ATTR_UNDERLINE:
         changed = dest->underline != value->u.underline;
@@ -1964,6 +1979,9 @@ static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_
         dest_spacing->trailing = value->u.spacing[1];
         dest_spacing->min_advance = value->u.spacing[2];
         break;
+    case LAYOUT_RANGE_ATTR_TYPOGRAPHY:
+        changed = set_layout_range_iface_attr((IUnknown**)&dest_iface->iface, (IUnknown*)value->u.typography);
+        break;
     default:
         ;
     }
@@ -2019,6 +2037,9 @@ static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layo
     case LAYOUT_RANGE_ATTR_SPACING:
         ranges = &layout->spacing;
         break;
+    case LAYOUT_RANGE_ATTR_TYPOGRAPHY:
+        ranges = &layout->typographies;
+        break;
     default:
         FIXME("unknown attr kind %d\n", attr);
         return E_FAIL;
@@ -2576,8 +2597,13 @@ static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout2 *iface
 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout2 *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
 {
     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
-    FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
-    return E_NOTIMPL;
+    struct layout_range_attr_value value;
+
+    TRACE("(%p)->(%p %s)\n", This, typography, debugstr_range(&range));
+
+    value.range = range;
+    value.u.typography = typography;
+    return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_TYPOGRAPHY, &value);
 }
 
 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout2 *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
@@ -2735,12 +2761,12 @@ static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2 *ifac
     UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
 {
     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
-    struct layout_range_effect *range;
+    struct layout_range_iface *range;
 
     TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
 
-    range = (struct layout_range_effect*)get_layout_range_header_by_pos(&This->effects, position);
-    *effect = range->effect;
+    range = (struct layout_range_iface*)get_layout_range_header_by_pos(&This->effects, position);
+    *effect = range->iface;
     if (*effect)
         IUnknown_AddRef(*effect);
 
@@ -2767,11 +2793,19 @@ static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout2 *iface
 }
 
 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout2 *iface,
-    UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
+    UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *r)
 {
     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
-    FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
-    return E_NOTIMPL;
+    struct layout_range_iface *range;
+
+    TRACE("(%p)->(%u %p %p)\n", This, position, typography, r);
+
+    range = (struct layout_range_iface*)get_layout_range_header_by_pos(&This->typographies, position);
+    *typography = (IDWriteTypography*)range->iface;
+    if (*typography)
+        IDWriteTypography_AddRef(*typography);
+
+    return return_range(&range->h, r);
 }
 
 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2 *iface,
@@ -3921,8 +3955,8 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I
 
 static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, struct dwrite_textlayout *layout)
 {
-    struct layout_range_header *range, *strike, *effect, *spacing;
-    DWRITE_TEXT_RANGE r = { 0, ~0u };
+    struct layout_range_header *range, *strike, *effect, *spacing, *typography;
+    static const DWRITE_TEXT_RANGE r = { 0, ~0u };
     HRESULT hr;
 
     layout->IDWriteTextLayout2_iface.lpVtbl = &dwritetextlayoutvtbl;
@@ -3948,6 +3982,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
     list_init(&layout->strike_ranges);
     list_init(&layout->effects);
     list_init(&layout->spacing);
+    list_init(&layout->typographies);
     memset(&layout->format, 0, sizeof(layout->format));
     memset(&layout->metrics, 0, sizeof(layout->metrics));
     layout->metrics.layoutWidth = maxwidth;
@@ -3971,7 +4006,8 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
     strike = alloc_layout_range(layout, &r, LAYOUT_RANGE_STRIKETHROUGH);
     effect = alloc_layout_range(layout, &r, LAYOUT_RANGE_EFFECT);
     spacing = alloc_layout_range(layout, &r, LAYOUT_RANGE_SPACING);
-    if (!range || !strike || !effect || !spacing) {
+    typography = alloc_layout_range(layout, &r, LAYOUT_RANGE_TYPOGRAPHY);
+    if (!range || !strike || !effect || !spacing || !typography) {
         free_layout_range(range);
         free_layout_range(strike);
         free_layout_range(effect);
@@ -3984,6 +4020,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
     list_add_head(&layout->strike_ranges, &strike->entry);
     list_add_head(&layout->effects, &effect->entry);
     list_add_head(&layout->spacing, &spacing->entry);
+    list_add_head(&layout->typographies, &typography->entry);
     return S_OK;
 
 fail:
diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c
index 5e38a07..186e257 100644
--- a/dlls/dwrite/tests/layout.c
+++ b/dlls/dwrite/tests/layout.c
@@ -4074,6 +4074,62 @@ if (0) /* crashes on native */
     IDWriteFactory2_Release(factory2);
 }
 
+static void test_SetTypography(void)
+{
+    static const WCHAR strW[] = {'a','f','i','b',0};
+    IDWriteTypography *typography, *typography2;
+    IDWriteTextFormat *format;
+    IDWriteTextLayout *layout;
+    DWRITE_TEXT_RANGE range;
+    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.0, enusW, &format);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IDWriteFactory_CreateTextLayout(factory, strW, 4, format, 1000.0, 1000.0, &layout);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IDWriteTextFormat_Release(format);
+
+    hr = IDWriteFactory_CreateTypography(factory, &typography);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    EXPECT_REF(typography, 1);
+    range.startPosition = 0;
+    range.length = 2;
+    hr = IDWriteTextLayout_SetTypography(layout, typography, range);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    EXPECT_REF(typography, 2);
+
+    hr = IDWriteTextLayout_GetTypography(layout, 0, &typography2, NULL);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(typography2 == typography, "got %p, expected %p\n", typography2, typography);
+    IDWriteTypography_Release(typography2);
+    IDWriteTypography_Release(typography);
+
+    hr = IDWriteFactory_CreateTypography(factory, &typography2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    range.startPosition = 0;
+    range.length = 1;
+    hr = IDWriteTextLayout_SetTypography(layout, typography2, range);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    EXPECT_REF(typography2, 2);
+    IDWriteTypography_Release(typography2);
+
+    hr = IDWriteTextLayout_GetTypography(layout, 0, &typography, &range);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(range.length == 1, "got %u\n", range.length);
+
+    IDWriteTypography_Release(typography);
+
+    IDWriteTextLayout_Release(layout);
+    IDWriteFactory_Release(factory);
+}
+
 START_TEST(layout)
 {
     static const WCHAR ctrlstrW[] = {0x202a,0};
@@ -4121,6 +4177,7 @@ START_TEST(layout)
     test_SetWordWrapping();
     test_MapCharacters();
     test_FontFallbackBuilder();
+    test_SetTypography();
 
     IDWriteFactory_Release(factory);
 }
-- 
2.6.4




More information about the wine-patches mailing list