dwrite: Store character spacing layout settings.
This commit is contained in:
parent
e70b50d772
commit
b43850a363
|
@ -72,7 +72,8 @@ enum layout_range_attr_kind {
|
||||||
LAYOUT_RANGE_ATTR_PAIR_KERNING,
|
LAYOUT_RANGE_ATTR_PAIR_KERNING,
|
||||||
LAYOUT_RANGE_ATTR_FONTCOLL,
|
LAYOUT_RANGE_ATTR_FONTCOLL,
|
||||||
LAYOUT_RANGE_ATTR_LOCALE,
|
LAYOUT_RANGE_ATTR_LOCALE,
|
||||||
LAYOUT_RANGE_ATTR_FONTFAMILY
|
LAYOUT_RANGE_ATTR_FONTFAMILY,
|
||||||
|
LAYOUT_RANGE_ATTR_SPACING
|
||||||
};
|
};
|
||||||
|
|
||||||
struct layout_range_attr_value {
|
struct layout_range_attr_value {
|
||||||
|
@ -90,13 +91,15 @@ struct layout_range_attr_value {
|
||||||
IDWriteFontCollection *collection;
|
IDWriteFontCollection *collection;
|
||||||
const WCHAR *locale;
|
const WCHAR *locale;
|
||||||
const WCHAR *fontfamily;
|
const WCHAR *fontfamily;
|
||||||
|
FLOAT spacing[3]; /* in arguments order - leading, trailing, advance */
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum layout_range_kind {
|
enum layout_range_kind {
|
||||||
LAYOUT_RANGE_REGULAR,
|
LAYOUT_RANGE_REGULAR,
|
||||||
LAYOUT_RANGE_STRIKETHROUGH,
|
LAYOUT_RANGE_STRIKETHROUGH,
|
||||||
LAYOUT_RANGE_EFFECT
|
LAYOUT_RANGE_EFFECT,
|
||||||
|
LAYOUT_RANGE_SPACING
|
||||||
};
|
};
|
||||||
|
|
||||||
struct layout_range_header {
|
struct layout_range_header {
|
||||||
|
@ -129,6 +132,13 @@ struct layout_range_effect {
|
||||||
IUnknown *effect;
|
IUnknown *effect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct layout_range_spacing {
|
||||||
|
struct layout_range_header h;
|
||||||
|
FLOAT leading;
|
||||||
|
FLOAT trailing;
|
||||||
|
FLOAT min_advance;
|
||||||
|
};
|
||||||
|
|
||||||
enum layout_run_kind {
|
enum layout_run_kind {
|
||||||
LAYOUT_RUN_REGULAR,
|
LAYOUT_RUN_REGULAR,
|
||||||
LAYOUT_RUN_INLINE
|
LAYOUT_RUN_INLINE
|
||||||
|
@ -213,6 +223,7 @@ struct dwrite_textlayout {
|
||||||
FLOAT maxheight;
|
FLOAT maxheight;
|
||||||
struct list strike_ranges;
|
struct list strike_ranges;
|
||||||
struct list effects;
|
struct list effects;
|
||||||
|
struct list spacing;
|
||||||
struct list ranges;
|
struct list ranges;
|
||||||
struct list runs;
|
struct list runs;
|
||||||
/* lists ready to use by Draw() */
|
/* lists ready to use by Draw() */
|
||||||
|
@ -1109,6 +1120,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)
|
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_effect const *range_effect = (struct layout_range_effect*)h;
|
||||||
struct layout_range_bool const *range_bool = (struct layout_range_bool*)h;
|
struct layout_range_bool const *range_bool = (struct layout_range_bool*)h;
|
||||||
struct layout_range const *range = (struct layout_range*)h;
|
struct layout_range const *range = (struct layout_range*)h;
|
||||||
|
@ -1138,6 +1150,10 @@ static BOOL is_same_layout_attrvalue(struct layout_range_header const *h, enum l
|
||||||
return strcmpW(range->locale, value->u.locale) == 0;
|
return strcmpW(range->locale, value->u.locale) == 0;
|
||||||
case LAYOUT_RANGE_ATTR_FONTFAMILY:
|
case LAYOUT_RANGE_ATTR_FONTFAMILY:
|
||||||
return strcmpW(range->fontfamily, value->u.fontfamily) == 0;
|
return strcmpW(range->fontfamily, value->u.fontfamily) == 0;
|
||||||
|
case LAYOUT_RANGE_ATTR_SPACING:
|
||||||
|
return range_spacing->leading == value->u.spacing[0] &&
|
||||||
|
range_spacing->trailing == value->u.spacing[1] &&
|
||||||
|
range_spacing->min_advance == value->u.spacing[2];
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -1176,6 +1192,14 @@ static inline BOOL is_same_layout_attributes(struct layout_range_header const *h
|
||||||
struct layout_range_effect const *right = (struct layout_range_effect const*)hright;
|
struct layout_range_effect const *right = (struct layout_range_effect const*)hright;
|
||||||
return left->effect == right->effect;
|
return left->effect == right->effect;
|
||||||
}
|
}
|
||||||
|
case LAYOUT_RANGE_SPACING:
|
||||||
|
{
|
||||||
|
struct layout_range_spacing const *left = (struct layout_range_spacing const*)hleft;
|
||||||
|
struct layout_range_spacing const *right = (struct layout_range_spacing const*)hright;
|
||||||
|
return left->leading == right->leading &&
|
||||||
|
left->trailing == right->trailing &&
|
||||||
|
left->min_advance == right->min_advance;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("unknown range kind %d\n", hleft->kind);
|
FIXME("unknown range kind %d\n", hleft->kind);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1246,6 +1270,19 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
|
||||||
h = &range->h;
|
h = &range->h;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LAYOUT_RANGE_SPACING:
|
||||||
|
{
|
||||||
|
struct layout_range_spacing *range;
|
||||||
|
|
||||||
|
range = heap_alloc(sizeof(*range));
|
||||||
|
if (!range) return NULL;
|
||||||
|
|
||||||
|
range->leading = 0.0;
|
||||||
|
range->trailing = 0.0;
|
||||||
|
range->min_advance = 0.0;
|
||||||
|
h = &range->h;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("unknown range kind %d\n", kind);
|
FIXME("unknown range kind %d\n", kind);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1304,6 +1341,15 @@ static struct layout_range_header *alloc_layout_range_from(struct layout_range_h
|
||||||
ret = &effect->h;
|
ret = &effect->h;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LAYOUT_RANGE_SPACING:
|
||||||
|
{
|
||||||
|
struct layout_range_spacing *spacing = heap_alloc(sizeof(*spacing));
|
||||||
|
if (!spacing) return NULL;
|
||||||
|
|
||||||
|
*spacing = *(struct layout_range_spacing*)h;
|
||||||
|
ret = &spacing->h;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("unknown range kind %d\n", h->kind);
|
FIXME("unknown range kind %d\n", h->kind);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1363,6 +1409,11 @@ static void free_layout_ranges_list(struct dwrite_textlayout *layout)
|
||||||
list_remove(&cur->entry);
|
list_remove(&cur->entry);
|
||||||
free_layout_range(cur);
|
free_layout_range(cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->spacing, 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)
|
static struct layout_range_header *find_outer_range(struct list *ranges, const DWRITE_TEXT_RANGE *range)
|
||||||
|
@ -1412,6 +1463,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)
|
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_effect *dest_effect = (struct layout_range_effect*)h;
|
||||||
struct layout_range_bool *dest_bool = (struct layout_range_bool*)h;
|
struct layout_range_bool *dest_bool = (struct layout_range_bool*)h;
|
||||||
struct layout_range *dest = (struct layout_range*)h;
|
struct layout_range *dest = (struct layout_range*)h;
|
||||||
|
@ -1468,6 +1520,14 @@ static BOOL set_layout_range_attrval(struct layout_range_header *h, enum layout_
|
||||||
dest->fontfamily = heap_strdupW(value->u.fontfamily);
|
dest->fontfamily = heap_strdupW(value->u.fontfamily);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_RANGE_ATTR_SPACING:
|
||||||
|
changed = dest_spacing->leading != value->u.spacing[0] ||
|
||||||
|
dest_spacing->trailing != value->u.spacing[1] ||
|
||||||
|
dest_spacing->min_advance != value->u.spacing[2];
|
||||||
|
dest_spacing->leading = value->u.spacing[0];
|
||||||
|
dest_spacing->trailing = value->u.spacing[1];
|
||||||
|
dest_spacing->min_advance = value->u.spacing[2];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -1520,6 +1580,9 @@ static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layo
|
||||||
case LAYOUT_RANGE_ATTR_EFFECT:
|
case LAYOUT_RANGE_ATTR_EFFECT:
|
||||||
ranges = &layout->effects;
|
ranges = &layout->effects;
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_RANGE_ATTR_SPACING:
|
||||||
|
ranges = &layout->spacing;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
FIXME("unknown attr kind %d\n", attr);
|
FIXME("unknown attr kind %d\n", attr);
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
@ -2560,20 +2623,38 @@ static HRESULT WINAPI dwritetextlayout1_GetPairKerning(IDWriteTextLayout2 *iface
|
||||||
return return_range(&range->h, r);
|
return return_range(&range->h, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2 *iface, FLOAT leading_spacing, FLOAT trailing_spacing,
|
static HRESULT WINAPI dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2 *iface, FLOAT leading, FLOAT trailing,
|
||||||
FLOAT minimum_advance_width, DWRITE_TEXT_RANGE range)
|
FLOAT min_advance, DWRITE_TEXT_RANGE range)
|
||||||
{
|
{
|
||||||
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
|
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
|
||||||
FIXME("(%p)->(%f %f %f %s): stub\n", This, leading_spacing, trailing_spacing, minimum_advance_width, debugstr_range(&range));
|
struct layout_range_attr_value value;
|
||||||
return E_NOTIMPL;
|
|
||||||
|
TRACE("(%p)->(%.2f %.2f %.2f %s)\n", This, leading, trailing, min_advance, debugstr_range(&range));
|
||||||
|
|
||||||
|
if (min_advance < 0.0)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
value.range = range;
|
||||||
|
value.u.spacing[0] = leading;
|
||||||
|
value.u.spacing[1] = trailing;
|
||||||
|
value.u.spacing[2] = min_advance;
|
||||||
|
return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_SPACING, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2 *iface, UINT32 position, FLOAT* leading_spacing,
|
static HRESULT WINAPI dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2 *iface, UINT32 position, FLOAT *leading,
|
||||||
FLOAT* trailing_spacing, FLOAT* minimum_advance_width, DWRITE_TEXT_RANGE *range)
|
FLOAT *trailing, FLOAT *min_advance, DWRITE_TEXT_RANGE *r)
|
||||||
{
|
{
|
||||||
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
|
struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
|
||||||
FIXME("(%p)->(%u %p %p %p %p): stub\n", This, position, leading_spacing, trailing_spacing, minimum_advance_width, range);
|
struct layout_range_spacing *range;
|
||||||
return E_NOTIMPL;
|
|
||||||
|
TRACE("(%p)->(%u %p %p %p %p)\n", This, position, leading, trailing, min_advance, r);
|
||||||
|
|
||||||
|
range = (struct layout_range_spacing*)get_layout_range_header_by_pos(&This->spacing, position);
|
||||||
|
*leading = range->leading;
|
||||||
|
*trailing = range->trailing;
|
||||||
|
*min_advance = range->min_advance;
|
||||||
|
|
||||||
|
return return_range(&range->h, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI dwritetextlayout2_GetMetrics(IDWriteTextLayout2 *iface, DWRITE_TEXT_METRICS1 *metrics)
|
static HRESULT WINAPI dwritetextlayout2_GetMetrics(IDWriteTextLayout2 *iface, DWRITE_TEXT_METRICS1 *metrics)
|
||||||
|
@ -3315,7 +3396,7 @@ 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)
|
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;
|
struct layout_range_header *range, *strike, *effect, *spacing;
|
||||||
DWRITE_TEXT_RANGE r = { 0, ~0u };
|
DWRITE_TEXT_RANGE r = { 0, ~0u };
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -3344,6 +3425,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
|
||||||
list_init(&layout->ranges);
|
list_init(&layout->ranges);
|
||||||
list_init(&layout->strike_ranges);
|
list_init(&layout->strike_ranges);
|
||||||
list_init(&layout->effects);
|
list_init(&layout->effects);
|
||||||
|
list_init(&layout->spacing);
|
||||||
memset(&layout->format, 0, sizeof(layout->format));
|
memset(&layout->format, 0, sizeof(layout->format));
|
||||||
|
|
||||||
layout->gdicompatible = FALSE;
|
layout->gdicompatible = FALSE;
|
||||||
|
@ -3364,10 +3446,12 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
|
||||||
range = alloc_layout_range(layout, &r, LAYOUT_RANGE_REGULAR);
|
range = alloc_layout_range(layout, &r, LAYOUT_RANGE_REGULAR);
|
||||||
strike = alloc_layout_range(layout, &r, LAYOUT_RANGE_STRIKETHROUGH);
|
strike = alloc_layout_range(layout, &r, LAYOUT_RANGE_STRIKETHROUGH);
|
||||||
effect = alloc_layout_range(layout, &r, LAYOUT_RANGE_EFFECT);
|
effect = alloc_layout_range(layout, &r, LAYOUT_RANGE_EFFECT);
|
||||||
if (!range || !strike || !effect) {
|
spacing = alloc_layout_range(layout, &r, LAYOUT_RANGE_SPACING);
|
||||||
|
if (!range || !strike || !effect || !spacing) {
|
||||||
free_layout_range(range);
|
free_layout_range(range);
|
||||||
free_layout_range(strike);
|
free_layout_range(strike);
|
||||||
free_layout_range(effect);
|
free_layout_range(effect);
|
||||||
|
free_layout_range(spacing);
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -3375,6 +3459,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
|
||||||
list_add_head(&layout->ranges, &range->entry);
|
list_add_head(&layout->ranges, &range->entry);
|
||||||
list_add_head(&layout->strike_ranges, &strike->entry);
|
list_add_head(&layout->strike_ranges, &strike->entry);
|
||||||
list_add_head(&layout->effects, &effect->entry);
|
list_add_head(&layout->effects, &effect->entry);
|
||||||
|
list_add_head(&layout->spacing, &spacing->entry);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
|
@ -1536,17 +1536,23 @@ static void test_GetClusterMetrics(void)
|
||||||
DWRITE_TEXT_RANGE r;
|
DWRITE_TEXT_RANGE r;
|
||||||
|
|
||||||
leading = trailing = min_advance = 2.0;
|
leading = trailing = min_advance = 2.0;
|
||||||
hr = IDWriteTextLayout1_GetCharacterSpacing(layout1, 0, &leading, &trailing,
|
hr = IDWriteTextLayout1_GetCharacterSpacing(layout1, 500, &leading, &trailing,
|
||||||
&min_advance, NULL);
|
&min_advance, &r);
|
||||||
todo_wine {
|
|
||||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
ok(leading == 0.0 && trailing == 0.0 && min_advance == 0.0,
|
ok(leading == 0.0 && trailing == 0.0 && min_advance == 0.0,
|
||||||
"got %.2f, %.2f, %.2f\n", leading, trailing, min_advance);
|
"got %.2f, %.2f, %.2f\n", leading, trailing, min_advance);
|
||||||
}
|
ok(r.startPosition == 0 && r.length == ~0u, "got %u, %u\n", r.startPosition, r.length);
|
||||||
|
|
||||||
|
leading = trailing = min_advance = 2.0;
|
||||||
|
hr = IDWriteTextLayout1_GetCharacterSpacing(layout1, 0, &leading, &trailing,
|
||||||
|
&min_advance, NULL);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
ok(leading == 0.0 && trailing == 0.0 && min_advance == 0.0,
|
||||||
|
"got %.2f, %.2f, %.2f\n", leading, trailing, min_advance);
|
||||||
|
|
||||||
r.startPosition = 0;
|
r.startPosition = 0;
|
||||||
r.length = 4;
|
r.length = 4;
|
||||||
hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 10.0, 15.0, 0.0, r);
|
hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 10.0, 15.0, 0.0, r);
|
||||||
todo_wine
|
|
||||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -1564,9 +1570,14 @@ todo_wine
|
||||||
r.startPosition = 0;
|
r.startPosition = 0;
|
||||||
r.length = 4;
|
r.length = 4;
|
||||||
hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 0.0, 0.0, 0.0, r);
|
hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 0.0, 0.0, 0.0, r);
|
||||||
todo_wine
|
|
||||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
/* negative advance limit */
|
||||||
|
r.startPosition = 0;
|
||||||
|
r.length = 4;
|
||||||
|
hr = IDWriteTextLayout1_SetCharacterSpacing(layout1, 0.0, 0.0, -10.0, r);
|
||||||
|
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
IDWriteTextLayout1_Release(layout1);
|
IDWriteTextLayout1_Release(layout1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue