mscoree: Implement CorBindToCurrentRuntime.
[wine/multimedia.git] / dlls / dwrite / layout.c
blob82525d8a72d5c56b61a63bb18e22832c002250cb
1 /*
2 * Text format and layout
4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "dwrite.h"
29 #include "dwrite_private.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
34 struct dwrite_textformat_data {
35 WCHAR *family_name;
36 UINT32 family_len;
37 WCHAR *locale;
38 UINT32 locale_len;
40 DWRITE_FONT_WEIGHT weight;
41 DWRITE_FONT_STYLE style;
42 DWRITE_FONT_STRETCH stretch;
44 DWRITE_PARAGRAPH_ALIGNMENT paralign;
45 DWRITE_READING_DIRECTION readingdir;
46 DWRITE_WORD_WRAPPING wrapping;
47 DWRITE_TEXT_ALIGNMENT textalignment;
48 DWRITE_FLOW_DIRECTION flow;
49 DWRITE_LINE_SPACING_METHOD spacingmethod;
51 FLOAT spacing;
52 FLOAT baseline;
53 FLOAT fontsize;
55 DWRITE_TRIMMING trimming;
56 IDWriteInlineObject *trimmingsign;
58 IDWriteFontCollection *collection;
61 enum layout_range_attr_kind {
62 LAYOUT_RANGE_ATTR_WEIGHT,
63 LAYOUT_RANGE_ATTR_STYLE,
64 LAYOUT_RANGE_ATTR_STRETCH,
65 LAYOUT_RANGE_ATTR_FONTSIZE,
66 LAYOUT_RANGE_ATTR_EFFECT,
67 LAYOUT_RANGE_ATTR_INLINE,
68 LAYOUT_RANGE_ATTR_UNDERLINE,
69 LAYOUT_RANGE_ATTR_STRIKETHROUGH,
70 LAYOUT_RANGE_ATTR_FONTCOLL
73 struct layout_range_attr_value {
74 DWRITE_TEXT_RANGE range;
75 union {
76 DWRITE_FONT_WEIGHT weight;
77 DWRITE_FONT_STYLE style;
78 DWRITE_FONT_STRETCH stretch;
79 FLOAT fontsize;
80 IDWriteInlineObject *object;
81 IUnknown *effect;
82 BOOL underline;
83 BOOL strikethrough;
84 IDWriteFontCollection *collection;
85 } u;
88 struct layout_range {
89 struct list entry;
90 DWRITE_TEXT_RANGE range;
91 DWRITE_FONT_WEIGHT weight;
92 DWRITE_FONT_STYLE style;
93 FLOAT fontsize;
94 DWRITE_FONT_STRETCH stretch;
95 IDWriteInlineObject *object;
96 IUnknown *effect;
97 BOOL underline;
98 BOOL strikethrough;
99 IDWriteFontCollection *collection;
102 struct dwrite_textlayout {
103 IDWriteTextLayout IDWriteTextLayout_iface;
104 LONG ref;
106 WCHAR *str;
107 UINT32 len;
108 struct dwrite_textformat_data format;
109 FLOAT maxwidth;
110 FLOAT maxheight;
111 struct list ranges;
114 struct dwrite_textformat {
115 IDWriteTextFormat IDWriteTextFormat_iface;
116 LONG ref;
117 struct dwrite_textformat_data format;
120 struct dwrite_trimmingsign {
121 IDWriteInlineObject IDWriteInlineObject_iface;
122 LONG ref;
125 static const IDWriteTextFormatVtbl dwritetextformatvtbl;
127 static void release_format_data(struct dwrite_textformat_data *data)
129 if (data->collection) IDWriteFontCollection_Release(data->collection);
130 if (data->trimmingsign) IDWriteInlineObject_Release(data->trimmingsign);
131 heap_free(data->family_name);
132 heap_free(data->locale);
135 static inline struct dwrite_textlayout *impl_from_IDWriteTextLayout(IDWriteTextLayout *iface)
137 return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextLayout_iface);
140 static inline struct dwrite_textformat *impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
142 return CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat_iface);
145 static inline struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
147 return iface->lpVtbl == &dwritetextformatvtbl ? impl_from_IDWriteTextFormat(iface) : NULL;
150 static inline struct dwrite_trimmingsign *impl_from_IDWriteInlineObject(IDWriteInlineObject *iface)
152 return CONTAINING_RECORD(iface, struct dwrite_trimmingsign, IDWriteInlineObject_iface);
155 /* To be used in IDWriteTextLayout methods to validate and fix passed range */
156 static inline BOOL validate_text_range(struct dwrite_textlayout *layout, DWRITE_TEXT_RANGE *r)
158 if (r->startPosition >= layout->len)
159 return FALSE;
161 if (r->startPosition + r->length > layout->len)
162 r->length = layout->len - r->startPosition;
164 return TRUE;
167 static BOOL is_same_layout_attrvalue(struct layout_range const *range, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
169 switch (attr) {
170 case LAYOUT_RANGE_ATTR_WEIGHT:
171 return range->weight == value->u.weight;
172 case LAYOUT_RANGE_ATTR_STYLE:
173 return range->style == value->u.style;
174 case LAYOUT_RANGE_ATTR_STRETCH:
175 return range->stretch == value->u.stretch;
176 case LAYOUT_RANGE_ATTR_FONTSIZE:
177 return range->fontsize == value->u.fontsize;
178 case LAYOUT_RANGE_ATTR_INLINE:
179 return range->object == value->u.object;
180 case LAYOUT_RANGE_ATTR_EFFECT:
181 return range->effect == value->u.effect;
182 case LAYOUT_RANGE_ATTR_UNDERLINE:
183 return range->underline == value->u.underline;
184 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
185 return range->strikethrough == value->u.strikethrough;
186 case LAYOUT_RANGE_ATTR_FONTCOLL:
187 return range->collection == value->u.collection;
188 default:
192 return FALSE;
195 static inline BOOL is_same_layout_attributes(struct layout_range const *left, struct layout_range const *right)
197 return left->weight == right->weight &&
198 left->style == right->style &&
199 left->stretch == right->stretch &&
200 left->fontsize == right->fontsize &&
201 left->object == right->object &&
202 left->effect == right->effect &&
203 left->underline == right->underline &&
204 left->strikethrough == right->strikethrough &&
205 left->collection == right->collection;
208 static inline BOOL is_same_text_range(const DWRITE_TEXT_RANGE *left, const DWRITE_TEXT_RANGE *right)
210 return left->startPosition == right->startPosition && left->length == right->length;
213 /* Allocates range and inits it with default values from text format. */
214 static struct layout_range *alloc_layout_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *r)
216 struct layout_range *range;
218 range = heap_alloc(sizeof(*range));
219 if (!range) return NULL;
221 range->range = *r;
222 range->weight = layout->format.weight;
223 range->style = layout->format.style;
224 range->stretch = layout->format.stretch;
225 range->fontsize = layout->format.fontsize;
226 range->object = NULL;
227 range->effect = NULL;
228 range->underline = FALSE;
229 range->strikethrough = FALSE;
230 range->collection = layout->format.collection;
231 if (range->collection)
232 IDWriteFontCollection_AddRef(range->collection);
234 return range;
237 static struct layout_range *alloc_layout_range_from(struct layout_range *from, const DWRITE_TEXT_RANGE *r)
239 struct layout_range *range;
241 range = heap_alloc(sizeof(*range));
242 if (!range) return NULL;
244 *range = *from;
245 range->range = *r;
247 /* update refcounts */
248 if (range->object)
249 IDWriteInlineObject_AddRef(range->object);
250 if (range->effect)
251 IUnknown_AddRef(range->effect);
252 if (range->collection)
253 IDWriteFontCollection_AddRef(range->collection);
255 return range;
258 static void free_layout_range(struct layout_range *range)
260 if (range->object)
261 IDWriteInlineObject_Release(range->object);
262 if (range->effect)
263 IUnknown_Release(range->effect);
264 if (range->collection)
265 IDWriteFontCollection_Release(range->collection);
266 heap_free(range);
269 static void free_layout_ranges_list(struct dwrite_textlayout *layout)
271 struct layout_range *cur, *cur2;
272 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->ranges, struct layout_range, entry) {
273 list_remove(&cur->entry);
274 free_layout_range(cur);
278 static struct layout_range *find_outer_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *range)
280 struct layout_range *cur;
282 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
284 if (cur->range.startPosition > range->startPosition)
285 return NULL;
287 if ((cur->range.startPosition + cur->range.length < range->startPosition + range->length) &&
288 (range->startPosition < cur->range.startPosition + cur->range.length))
289 return NULL;
290 if (cur->range.startPosition + cur->range.length >= range->startPosition + range->length)
291 return cur;
294 return NULL;
297 static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos)
299 struct layout_range *cur;
301 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
302 DWRITE_TEXT_RANGE *r = &cur->range;
303 if (r->startPosition <= pos && pos < r->startPosition + r->length)
304 return cur;
307 return NULL;
310 static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
312 BOOL changed = FALSE;
314 switch (attr) {
315 case LAYOUT_RANGE_ATTR_WEIGHT:
316 changed = dest->weight != value->u.weight;
317 dest->weight = value->u.weight;
318 break;
319 case LAYOUT_RANGE_ATTR_STYLE:
320 changed = dest->style != value->u.style;
321 dest->style = value->u.style;
322 break;
323 case LAYOUT_RANGE_ATTR_STRETCH:
324 changed = dest->stretch != value->u.stretch;
325 dest->stretch = value->u.stretch;
326 break;
327 case LAYOUT_RANGE_ATTR_FONTSIZE:
328 changed = dest->fontsize != value->u.fontsize;
329 dest->fontsize = value->u.fontsize;
330 break;
331 case LAYOUT_RANGE_ATTR_INLINE:
332 changed = dest->object != value->u.object;
333 if (changed && dest->object)
334 IDWriteInlineObject_Release(dest->object);
335 dest->object = value->u.object;
336 if (dest->object)
337 IDWriteInlineObject_AddRef(dest->object);
338 break;
339 case LAYOUT_RANGE_ATTR_EFFECT:
340 changed = dest->effect != value->u.effect;
341 if (changed && dest->effect)
342 IUnknown_Release(dest->effect);
343 dest->effect = value->u.effect;
344 if (dest->effect)
345 IUnknown_AddRef(dest->effect);
346 break;
347 case LAYOUT_RANGE_ATTR_UNDERLINE:
348 changed = dest->underline != value->u.underline;
349 dest->underline = value->u.underline;
350 break;
351 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
352 changed = dest->strikethrough != value->u.strikethrough;
353 dest->strikethrough = value->u.strikethrough;
354 break;
355 case LAYOUT_RANGE_ATTR_FONTCOLL:
356 changed = dest->collection != value->u.collection;
357 if (changed && dest->collection)
358 IDWriteFontCollection_Release(dest->collection);
359 dest->collection = value->u.collection;
360 if (dest->collection)
361 IDWriteFontCollection_AddRef(dest->collection);
362 break;
363 default:
367 return changed;
370 static inline BOOL is_in_layout_range(const DWRITE_TEXT_RANGE *outer, const DWRITE_TEXT_RANGE *inner)
372 return (inner->startPosition >= outer->startPosition) &&
373 (inner->startPosition + inner->length <= outer->startPosition + outer->length);
376 static inline HRESULT return_range(const struct layout_range *range, DWRITE_TEXT_RANGE *r)
378 if (r) *r = range->range;
379 return S_OK;
382 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
383 static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
385 struct layout_range *outer, *right, *left, *cur;
386 struct list *ranges = &layout->ranges;
387 BOOL changed = FALSE;
388 DWRITE_TEXT_RANGE r;
390 /* If new range is completely within existing range, split existing range in two */
391 if ((outer = find_outer_range(layout, &value->range))) {
393 /* no need to add same range */
394 if (is_same_layout_attrvalue(outer, attr, value))
395 return S_OK;
397 /* for matching range bounds just replace data */
398 if (is_same_text_range(&outer->range, &value->range)) {
399 changed = set_layout_range_attrval(outer, attr, value);
400 goto done;
403 /* add new range to the left */
404 if (value->range.startPosition == outer->range.startPosition) {
405 left = alloc_layout_range_from(outer, &value->range);
406 if (!left) return E_OUTOFMEMORY;
408 changed = set_layout_range_attrval(left, attr, value);
409 list_add_before(&outer->entry, &left->entry);
410 outer->range.startPosition += value->range.length;
411 outer->range.length -= value->range.length;
412 goto done;
415 /* add new range to the right */
416 if (value->range.startPosition + value->range.length == outer->range.startPosition + outer->range.length) {
417 right = alloc_layout_range_from(outer, &value->range);
418 if (!right) return E_OUTOFMEMORY;
420 changed = set_layout_range_attrval(right, attr, value);
421 list_add_after(&outer->entry, &right->entry);
422 outer->range.length -= value->range.length;
423 goto done;
426 r.startPosition = value->range.startPosition + value->range.length;
427 r.length = outer->range.length + outer->range.startPosition - r.startPosition;
429 /* right part */
430 right = alloc_layout_range_from(outer, &r);
431 /* new range in the middle */
432 cur = alloc_layout_range_from(outer, &value->range);
433 if (!right || !cur) {
434 free_layout_range(right);
435 free_layout_range(cur);
436 return E_OUTOFMEMORY;
439 /* reuse container range as a left part */
440 outer->range.length = value->range.startPosition - outer->range.startPosition;
442 /* new part */
443 set_layout_range_attrval(cur, attr, value);
445 list_add_after(&outer->entry, &cur->entry);
446 list_add_after(&cur->entry, &right->entry);
448 return S_OK;
451 /* Now it's only possible that given range contains some existing ranges, fully or partially.
452 Update all of them. */
453 left = get_layout_range_by_pos(layout, value->range.startPosition);
454 if (left->range.startPosition == value->range.startPosition)
455 changed = set_layout_range_attrval(left, attr, value);
456 else /* need to split */ {
457 r.startPosition = value->range.startPosition;
458 r.length = left->range.length - value->range.startPosition + left->range.startPosition;
459 left->range.length -= r.length;
460 cur = alloc_layout_range_from(left, &r);
461 changed = set_layout_range_attrval(cur, attr, value);
462 list_add_after(&left->entry, &cur->entry);
464 cur = LIST_ENTRY(list_next(ranges, &left->entry), struct layout_range, entry);
466 /* for all existing ranges covered by new one update value */
467 while (is_in_layout_range(&value->range, &cur->range)) {
468 changed = set_layout_range_attrval(cur, attr, value);
469 cur = LIST_ENTRY(list_next(ranges, &cur->entry), struct layout_range, entry);
472 /* it's possible rightmost range intersects */
473 if (cur && (cur->range.startPosition < value->range.startPosition + value->range.length)) {
474 r.startPosition = cur->range.startPosition;
475 r.length = value->range.startPosition + value->range.length - cur->range.startPosition;
476 left = alloc_layout_range_from(cur, &r);
477 changed = set_layout_range_attrval(left, attr, value);
478 cur->range.startPosition += left->range.length;
479 cur->range.length -= left->range.length;
480 list_add_before(&cur->entry, &left->entry);
483 done:
484 if (changed) {
485 struct list *next, *i;
487 i = list_head(ranges);
488 while ((next = list_next(ranges, i))) {
489 struct layout_range *next_range = LIST_ENTRY(next, struct layout_range, entry);
491 cur = LIST_ENTRY(i, struct layout_range, entry);
492 if (is_same_layout_attributes(cur, next_range)) {
493 /* remove similar range */
494 cur->range.length += next_range->range.length;
495 list_remove(next);
496 free_layout_range(next_range);
498 else
499 i = list_next(ranges, i);
503 return S_OK;
506 static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout *iface, REFIID riid, void **obj)
508 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
510 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
512 if (IsEqualIID(riid, &IID_IUnknown) ||
513 IsEqualIID(riid, &IID_IDWriteTextFormat) ||
514 IsEqualIID(riid, &IID_IDWriteTextLayout))
516 *obj = iface;
517 IDWriteTextLayout_AddRef(iface);
518 return S_OK;
521 *obj = NULL;
523 return E_NOINTERFACE;
526 static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout *iface)
528 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
529 ULONG ref = InterlockedIncrement(&This->ref);
530 TRACE("(%p)->(%d)\n", This, ref);
531 return ref;
534 static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout *iface)
536 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
537 ULONG ref = InterlockedDecrement(&This->ref);
539 TRACE("(%p)->(%d)\n", This, ref);
541 if (!ref) {
542 free_layout_ranges_list(This);
543 release_format_data(&This->format);
544 heap_free(This->str);
545 heap_free(This);
548 return ref;
551 static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout *iface, DWRITE_TEXT_ALIGNMENT alignment)
553 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
554 FIXME("(%p)->(%d): stub\n", This, alignment);
555 return E_NOTIMPL;
558 static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
560 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
561 FIXME("(%p)->(%d): stub\n", This, alignment);
562 return E_NOTIMPL;
565 static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout *iface, DWRITE_WORD_WRAPPING wrapping)
567 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
568 FIXME("(%p)->(%d): stub\n", This, wrapping);
569 return E_NOTIMPL;
572 static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout *iface, DWRITE_READING_DIRECTION direction)
574 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
575 FIXME("(%p)->(%d): stub\n", This, direction);
576 return E_NOTIMPL;
579 static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout *iface, DWRITE_FLOW_DIRECTION direction)
581 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
582 FIXME("(%p)->(%d): stub\n", This, direction);
583 return E_NOTIMPL;
586 static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout *iface, FLOAT tabstop)
588 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
589 FIXME("(%p)->(%f): stub\n", This, tabstop);
590 return E_NOTIMPL;
593 static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING const *trimming,
594 IDWriteInlineObject *trimming_sign)
596 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
597 FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
598 return E_NOTIMPL;
601 static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD spacing,
602 FLOAT line_spacing, FLOAT baseline)
604 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
605 FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
606 return E_NOTIMPL;
609 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout *iface)
611 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
612 TRACE("(%p)\n", This);
613 return This->format.textalignment;
616 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout *iface)
618 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
619 TRACE("(%p)\n", This);
620 return This->format.paralign;
623 static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout *iface)
625 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
626 FIXME("(%p): stub\n", This);
627 return This->format.wrapping;
630 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout *iface)
632 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
633 TRACE("(%p)\n", This);
634 return This->format.readingdir;
637 static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout *iface)
639 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
640 TRACE("(%p)\n", This);
641 return This->format.flow;
644 static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout *iface)
646 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
647 FIXME("(%p): stub\n", This);
648 return 0.0;
651 static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING *options,
652 IDWriteInlineObject **trimming_sign)
654 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
656 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
658 *options = This->format.trimming;
659 *trimming_sign = This->format.trimmingsign;
660 if (*trimming_sign)
661 IDWriteInlineObject_AddRef(*trimming_sign);
662 return S_OK;
665 static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD *method,
666 FLOAT *spacing, FLOAT *baseline)
668 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
670 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
672 *method = This->format.spacingmethod;
673 *spacing = This->format.spacing;
674 *baseline = This->format.baseline;
675 return S_OK;
678 static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection **collection)
680 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
682 TRACE("(%p)->(%p)\n", This, collection);
684 *collection = This->format.collection;
685 if (*collection)
686 IDWriteFontCollection_AddRef(*collection);
687 return S_OK;
690 static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout *iface)
692 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
693 TRACE("(%p)\n", This);
694 return This->format.family_len;
697 static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
699 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
701 TRACE("(%p)->(%p %u)\n", This, name, size);
703 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
704 strcpyW(name, This->format.family_name);
705 return S_OK;
708 static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout *iface)
710 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
711 TRACE("(%p)\n", This);
712 return This->format.weight;
715 static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout *iface)
717 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
718 TRACE("(%p)\n", This);
719 return This->format.style;
722 static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout *iface)
724 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
725 TRACE("(%p)\n", This);
726 return This->format.stretch;
729 static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout *iface)
731 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
732 TRACE("(%p)\n", This);
733 return This->format.fontsize;
736 static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout *iface)
738 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
739 TRACE("(%p)\n", This);
740 return This->format.locale_len;
743 static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
745 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
747 TRACE("(%p)->(%p %u)\n", This, name, size);
749 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
750 strcpyW(name, This->format.locale);
751 return S_OK;
754 static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout *iface, FLOAT maxWidth)
756 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
757 TRACE("(%p)->(%.1f)\n", This, maxWidth);
758 This->maxwidth = maxWidth;
759 return S_OK;
762 static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout *iface, FLOAT maxHeight)
764 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
765 TRACE("(%p)->(%.1f)\n", This, maxHeight);
766 This->maxheight = maxHeight;
767 return S_OK;
770 static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
772 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
773 struct layout_range_attr_value value;
775 TRACE("(%p)->(%p %s)\n", This, collection, debugstr_range(&range));
777 if (!validate_text_range(This, &range))
778 return S_OK;
780 value.range = range;
781 value.u.collection = collection;
782 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTCOLL, &value);
785 static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
787 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
788 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_range(&range));
789 return E_NOTIMPL;
792 static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
794 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
795 struct layout_range_attr_value value;
797 TRACE("(%p)->(%d %s)\n", This, weight, debugstr_range(&range));
799 if (!validate_text_range(This, &range))
800 return S_OK;
802 value.range = range;
803 value.u.weight = weight;
804 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_WEIGHT, &value);
807 static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
809 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
810 struct layout_range_attr_value value;
812 TRACE("(%p)->(%d %s)\n", This, style, debugstr_range(&range));
814 if (!validate_text_range(This, &range))
815 return S_OK;
817 value.range = range;
818 value.u.style = style;
819 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STYLE, &value);
822 static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
824 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
825 struct layout_range_attr_value value;
827 TRACE("(%p)->(%d %s)\n", This, stretch, debugstr_range(&range));
829 if (!validate_text_range(This, &range))
830 return S_OK;
832 value.range = range;
833 value.u.stretch = stretch;
834 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRETCH, &value);
837 static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout *iface, FLOAT size, DWRITE_TEXT_RANGE range)
839 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
840 struct layout_range_attr_value value;
842 TRACE("(%p)->(%.2f %s)\n", This, size, debugstr_range(&range));
844 if (!validate_text_range(This, &range))
845 return S_OK;
847 value.range = range;
848 value.u.fontsize = size;
849 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTSIZE, &value);
852 static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout *iface, BOOL underline, DWRITE_TEXT_RANGE range)
854 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
855 struct layout_range_attr_value value;
857 TRACE("(%p)->(%d %s)\n", This, underline, debugstr_range(&range));
859 if (!validate_text_range(This, &range))
860 return S_OK;
862 value.range = range;
863 value.u.underline = underline;
864 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_UNDERLINE, &value);
867 static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
869 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
870 struct layout_range_attr_value value;
872 TRACE("(%p)->(%d %s)\n", This, strikethrough, debugstr_range(&range));
874 if (!validate_text_range(This, &range))
875 return S_OK;
877 value.range = range;
878 value.u.underline = strikethrough;
879 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRIKETHROUGH, &value);
882 static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
884 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
885 struct layout_range_attr_value value;
887 TRACE("(%p)->(%p %s)\n", This, effect, debugstr_range(&range));
889 if (!validate_text_range(This, &range))
890 return S_OK;
892 value.range = range;
893 value.u.effect = effect;
894 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_EFFECT, &value);
897 static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE r)
899 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
900 struct layout_range_attr_value attr;
902 TRACE("(%p)->(%p %s)\n", This, object, debugstr_range(&r));
904 if (!validate_text_range(This, &r))
905 return S_OK;
907 attr.range = r;
908 attr.u.object = object;
910 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_INLINE, &attr);
913 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
915 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
916 FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
917 return E_NOTIMPL;
920 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
922 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
923 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(locale), debugstr_range(&range));
924 return E_NOTIMPL;
927 static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout *iface)
929 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
930 TRACE("(%p)\n", This);
931 return This->maxwidth;
934 static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout *iface)
936 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
937 TRACE("(%p)\n", This);
938 return This->maxheight;
941 static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout *iface, UINT32 position,
942 IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *r)
944 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
945 struct layout_range *range;
947 TRACE("(%p)->(%u %p %p)\n", This, position, collection, r);
949 range = get_layout_range_by_pos(This, position);
950 *collection = range ? range->collection : NULL;
951 if (*collection)
952 IDWriteFontCollection_AddRef(*collection);
954 return return_range(range, r);
957 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout *iface,
958 UINT32 pos, UINT32* len, DWRITE_TEXT_RANGE *range)
960 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
961 FIXME("(%p)->(%d %p %p): stub\n", This, pos, len, range);
962 return E_NOTIMPL;
965 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout *iface,
966 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
968 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
969 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
970 return E_NOTIMPL;
973 static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout *iface,
974 UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
976 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
977 struct layout_range *range;
979 TRACE("(%p)->(%u %p %p)\n", This, position, weight, r);
981 if (position >= This->len)
982 return S_OK;
984 range = get_layout_range_by_pos(This, position);
985 *weight = range->weight;
987 return return_range(range, r);
990 static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout *iface,
991 UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
993 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
994 struct layout_range *range;
996 TRACE("(%p)->(%u %p %p)\n", This, position, style, r);
998 if (position >= This->len)
999 return S_OK;
1001 range = get_layout_range_by_pos(This, position);
1002 *style = range->style;
1004 return return_range(range, r);
1007 static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout *iface,
1008 UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *r)
1010 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1011 struct layout_range *range;
1013 TRACE("(%p)->(%u %p %p)\n", This, position, stretch, r);
1015 if (position >= This->len)
1016 return S_OK;
1018 range = get_layout_range_by_pos(This, position);
1019 *stretch = range->stretch;
1021 return return_range(range, r);
1024 static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout *iface,
1025 UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *r)
1027 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1028 struct layout_range *range;
1030 TRACE("(%p)->(%u %p %p)\n", This, position, size, r);
1032 if (position >= This->len)
1033 return S_OK;
1035 range = get_layout_range_by_pos(This, position);
1036 *size = range->fontsize;
1038 return return_range(range, r);
1041 static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout *iface,
1042 UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
1044 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1045 struct layout_range *range;
1047 TRACE("(%p)->(%u %p %p)\n", This, position, underline, r);
1049 if (position >= This->len)
1050 return S_OK;
1052 range = get_layout_range_by_pos(This, position);
1053 *underline = range->underline;
1055 return return_range(range, r);
1058 static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout *iface,
1059 UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
1061 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1062 struct layout_range *range;
1064 TRACE("(%p)->(%u %p %p)\n", This, position, strikethrough, r);
1066 if (position >= This->len)
1067 return S_OK;
1069 range = get_layout_range_by_pos(This, position);
1070 *strikethrough = range->strikethrough;
1072 return return_range(range, r);
1075 static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout *iface,
1076 UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
1078 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1079 struct layout_range *range;
1081 TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
1083 if (position >= This->len)
1084 return S_OK;
1086 range = get_layout_range_by_pos(This, position);
1087 *effect = range->effect;
1088 if (*effect)
1089 IUnknown_AddRef(*effect);
1091 return return_range(range, r);
1094 static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout *iface,
1095 UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
1097 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1098 struct layout_range *range;
1100 TRACE("(%p)->(%u %p %p)\n", This, position, object, r);
1102 range = get_layout_range_by_pos(This, position);
1103 *object = range ? range->object : NULL;
1104 if (*object)
1105 IDWriteInlineObject_AddRef(*object);
1107 return return_range(range, r);
1110 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout *iface,
1111 UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
1113 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1114 FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
1115 return E_NOTIMPL;
1118 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout *iface,
1119 UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *range)
1121 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1122 FIXME("(%p)->(%u %p %p): stub\n", This, position, length, range);
1123 return E_NOTIMPL;
1126 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout *iface,
1127 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
1129 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1130 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
1131 return E_NOTIMPL;
1134 static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout *iface,
1135 void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
1137 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1138 FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
1139 return E_NOTIMPL;
1142 static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout *iface,
1143 DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
1145 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1146 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
1147 return E_NOTIMPL;
1150 static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout *iface, DWRITE_TEXT_METRICS *metrics)
1152 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1153 FIXME("(%p)->(%p): stub\n", This, metrics);
1154 return E_NOTIMPL;
1157 static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout *iface, DWRITE_OVERHANG_METRICS *overhangs)
1159 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1160 FIXME("(%p)->(%p): stub\n", This, overhangs);
1161 return E_NOTIMPL;
1164 static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout *iface,
1165 DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32* act_count)
1167 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1168 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, act_count);
1169 return E_NOTIMPL;
1172 static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout *iface, FLOAT* min_width)
1174 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1175 FIXME("(%p)->(%p): stub\n", This, min_width);
1176 return E_NOTIMPL;
1179 static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout *iface,
1180 FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
1182 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1183 FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
1184 return E_NOTIMPL;
1187 static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout *iface,
1188 UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
1190 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1191 FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
1192 return E_NOTIMPL;
1195 static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout *iface,
1196 UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
1197 DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
1199 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1200 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
1201 max_metricscount, actual_metricscount);
1202 return E_NOTIMPL;
1205 static const IDWriteTextLayoutVtbl dwritetextlayoutvtbl = {
1206 dwritetextlayout_QueryInterface,
1207 dwritetextlayout_AddRef,
1208 dwritetextlayout_Release,
1209 dwritetextlayout_SetTextAlignment,
1210 dwritetextlayout_SetParagraphAlignment,
1211 dwritetextlayout_SetWordWrapping,
1212 dwritetextlayout_SetReadingDirection,
1213 dwritetextlayout_SetFlowDirection,
1214 dwritetextlayout_SetIncrementalTabStop,
1215 dwritetextlayout_SetTrimming,
1216 dwritetextlayout_SetLineSpacing,
1217 dwritetextlayout_GetTextAlignment,
1218 dwritetextlayout_GetParagraphAlignment,
1219 dwritetextlayout_GetWordWrapping,
1220 dwritetextlayout_GetReadingDirection,
1221 dwritetextlayout_GetFlowDirection,
1222 dwritetextlayout_GetIncrementalTabStop,
1223 dwritetextlayout_GetTrimming,
1224 dwritetextlayout_GetLineSpacing,
1225 dwritetextlayout_GetFontCollection,
1226 dwritetextlayout_GetFontFamilyNameLength,
1227 dwritetextlayout_GetFontFamilyName,
1228 dwritetextlayout_GetFontWeight,
1229 dwritetextlayout_GetFontStyle,
1230 dwritetextlayout_GetFontStretch,
1231 dwritetextlayout_GetFontSize,
1232 dwritetextlayout_GetLocaleNameLength,
1233 dwritetextlayout_GetLocaleName,
1234 dwritetextlayout_SetMaxWidth,
1235 dwritetextlayout_SetMaxHeight,
1236 dwritetextlayout_SetFontCollection,
1237 dwritetextlayout_SetFontFamilyName,
1238 dwritetextlayout_SetFontWeight,
1239 dwritetextlayout_SetFontStyle,
1240 dwritetextlayout_SetFontStretch,
1241 dwritetextlayout_SetFontSize,
1242 dwritetextlayout_SetUnderline,
1243 dwritetextlayout_SetStrikethrough,
1244 dwritetextlayout_SetDrawingEffect,
1245 dwritetextlayout_SetInlineObject,
1246 dwritetextlayout_SetTypography,
1247 dwritetextlayout_SetLocaleName,
1248 dwritetextlayout_GetMaxWidth,
1249 dwritetextlayout_GetMaxHeight,
1250 dwritetextlayout_layout_GetFontCollection,
1251 dwritetextlayout_layout_GetFontFamilyNameLength,
1252 dwritetextlayout_layout_GetFontFamilyName,
1253 dwritetextlayout_layout_GetFontWeight,
1254 dwritetextlayout_layout_GetFontStyle,
1255 dwritetextlayout_layout_GetFontStretch,
1256 dwritetextlayout_layout_GetFontSize,
1257 dwritetextlayout_GetUnderline,
1258 dwritetextlayout_GetStrikethrough,
1259 dwritetextlayout_GetDrawingEffect,
1260 dwritetextlayout_GetInlineObject,
1261 dwritetextlayout_GetTypography,
1262 dwritetextlayout_layout_GetLocaleNameLength,
1263 dwritetextlayout_layout_GetLocaleName,
1264 dwritetextlayout_Draw,
1265 dwritetextlayout_GetLineMetrics,
1266 dwritetextlayout_GetMetrics,
1267 dwritetextlayout_GetOverhangMetrics,
1268 dwritetextlayout_GetClusterMetrics,
1269 dwritetextlayout_DetermineMinWidth,
1270 dwritetextlayout_HitTestPoint,
1271 dwritetextlayout_HitTestTextPosition,
1272 dwritetextlayout_HitTestTextRange
1275 static void layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
1277 struct dwrite_textformat *f;
1279 memset(&layout->format, 0, sizeof(layout->format));
1281 if ((f = unsafe_impl_from_IDWriteTextFormat(format)))
1283 layout->format = f->format;
1284 layout->format.locale = heap_strdupW(f->format.locale);
1285 layout->format.family_name = heap_strdupW(f->format.family_name);
1286 if (layout->format.trimmingsign)
1287 IDWriteInlineObject_AddRef(layout->format.trimmingsign);
1289 else
1291 UINT32 locale_len, family_len;
1293 layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
1294 layout->format.style = IDWriteTextFormat_GetFontStyle(format);
1295 layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
1296 layout->format.fontsize= IDWriteTextFormat_GetFontSize(format);
1297 layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
1298 layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
1299 layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
1300 layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
1301 layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
1302 IDWriteTextFormat_GetLineSpacing(format,
1303 &layout->format.spacingmethod,
1304 &layout->format.spacing,
1305 &layout->format.baseline
1307 IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
1309 /* locale name and length */
1310 locale_len = IDWriteTextFormat_GetLocaleNameLength(format);
1311 layout->format.locale = heap_alloc((locale_len+1)*sizeof(WCHAR));
1312 IDWriteTextFormat_GetLocaleName(format, layout->format.locale, locale_len+1);
1313 layout->format.locale_len = locale_len;
1315 /* font family name and length */
1316 family_len = IDWriteTextFormat_GetFontFamilyNameLength(format);
1317 layout->format.family_name = heap_alloc((family_len+1)*sizeof(WCHAR));
1318 IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, family_len+1);
1319 layout->format.family_len = family_len;
1322 IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
1325 HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, IDWriteTextLayout **layout)
1327 struct dwrite_textlayout *This;
1328 struct layout_range *range;
1329 DWRITE_TEXT_RANGE r = { 0, len };
1331 *layout = NULL;
1333 This = heap_alloc(sizeof(struct dwrite_textlayout));
1334 if (!This) return E_OUTOFMEMORY;
1336 This->IDWriteTextLayout_iface.lpVtbl = &dwritetextlayoutvtbl;
1337 This->ref = 1;
1338 This->str = heap_strdupnW(str, len);
1339 This->len = len;
1340 This->maxwidth = maxwidth;
1341 This->maxheight = maxheight;
1342 layout_format_from_textformat(This, format);
1344 list_init(&This->ranges);
1345 range = alloc_layout_range(This, &r);
1346 if (!range) {
1347 IDWriteTextLayout_Release(&This->IDWriteTextLayout_iface);
1348 return E_OUTOFMEMORY;
1350 list_add_head(&This->ranges, &range->entry);
1352 *layout = &This->IDWriteTextLayout_iface;
1354 return S_OK;
1357 static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
1359 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1361 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1363 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
1364 *obj = iface;
1365 IDWriteInlineObject_AddRef(iface);
1366 return S_OK;
1369 *obj = NULL;
1370 return E_NOINTERFACE;
1374 static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
1376 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1377 ULONG ref = InterlockedIncrement(&This->ref);
1378 TRACE("(%p)->(%d)\n", This, ref);
1379 return ref;
1382 static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
1384 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1385 ULONG ref = InterlockedDecrement(&This->ref);
1387 TRACE("(%p)->(%d)\n", This, ref);
1389 if (!ref)
1390 heap_free(This);
1392 return ref;
1395 static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
1396 FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
1398 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1399 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This, context, renderer, originX, originY, is_sideways, is_rtl, drawing_effect);
1400 return E_NOTIMPL;
1403 static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
1405 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1406 FIXME("(%p)->(%p): stub\n", This, metrics);
1407 return E_NOTIMPL;
1410 static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
1412 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1413 FIXME("(%p)->(%p): stub\n", This, overhangs);
1414 return E_NOTIMPL;
1417 static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
1418 DWRITE_BREAK_CONDITION *after)
1420 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1422 TRACE("(%p)->(%p %p)\n", This, before, after);
1424 *before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
1425 return S_OK;
1428 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
1429 dwritetrimmingsign_QueryInterface,
1430 dwritetrimmingsign_AddRef,
1431 dwritetrimmingsign_Release,
1432 dwritetrimmingsign_Draw,
1433 dwritetrimmingsign_GetMetrics,
1434 dwritetrimmingsign_GetOverhangMetrics,
1435 dwritetrimmingsign_GetBreakConditions
1438 HRESULT create_trimmingsign(IDWriteInlineObject **sign)
1440 struct dwrite_trimmingsign *This;
1442 *sign = NULL;
1444 This = heap_alloc(sizeof(struct dwrite_trimmingsign));
1445 if (!This) return E_OUTOFMEMORY;
1447 This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
1448 This->ref = 1;
1450 *sign = &This->IDWriteInlineObject_iface;
1452 return S_OK;
1455 static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat *iface, REFIID riid, void **obj)
1457 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1459 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1461 if (IsEqualIID(riid, &IID_IUnknown) ||
1462 IsEqualIID(riid, &IID_IDWriteTextFormat))
1464 *obj = iface;
1465 IDWriteTextFormat_AddRef(iface);
1466 return S_OK;
1469 *obj = NULL;
1471 return E_NOINTERFACE;
1474 static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat *iface)
1476 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1477 ULONG ref = InterlockedIncrement(&This->ref);
1478 TRACE("(%p)->(%d)\n", This, ref);
1479 return ref;
1482 static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat *iface)
1484 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1485 ULONG ref = InterlockedDecrement(&This->ref);
1487 TRACE("(%p)->(%d)\n", This, ref);
1489 if (!ref)
1491 release_format_data(&This->format);
1492 heap_free(This);
1495 return ref;
1498 static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat *iface, DWRITE_TEXT_ALIGNMENT alignment)
1500 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1501 TRACE("(%p)->(%d)\n", This, alignment);
1502 This->format.textalignment = alignment;
1503 return S_OK;
1506 static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
1508 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1509 TRACE("(%p)->(%d)\n", This, alignment);
1510 This->format.paralign = alignment;
1511 return S_OK;
1514 static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat *iface, DWRITE_WORD_WRAPPING wrapping)
1516 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1517 TRACE("(%p)->(%d)\n", This, wrapping);
1518 This->format.wrapping = wrapping;
1519 return S_OK;
1522 static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat *iface, DWRITE_READING_DIRECTION direction)
1524 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1525 TRACE("(%p)->(%d)\n", This, direction);
1526 This->format.readingdir = direction;
1527 return S_OK;
1530 static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat *iface, DWRITE_FLOW_DIRECTION direction)
1532 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1533 TRACE("(%p)->(%d)\n", This, direction);
1534 This->format.flow = direction;
1535 return S_OK;
1538 static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat *iface, FLOAT tabstop)
1540 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1541 FIXME("(%p)->(%f): stub\n", This, tabstop);
1542 return E_NOTIMPL;
1545 static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING const *trimming,
1546 IDWriteInlineObject *trimming_sign)
1548 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1549 TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign);
1551 This->format.trimming = *trimming;
1552 if (This->format.trimmingsign)
1553 IDWriteInlineObject_Release(This->format.trimmingsign);
1554 This->format.trimmingsign = trimming_sign;
1555 if (This->format.trimmingsign)
1556 IDWriteInlineObject_AddRef(This->format.trimmingsign);
1557 return S_OK;
1560 static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD method,
1561 FLOAT spacing, FLOAT baseline)
1563 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1564 TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
1565 This->format.spacingmethod = method;
1566 This->format.spacing = spacing;
1567 This->format.baseline = baseline;
1568 return S_OK;
1571 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat *iface)
1573 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1574 TRACE("(%p)\n", This);
1575 return This->format.textalignment;
1578 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat *iface)
1580 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1581 TRACE("(%p)\n", This);
1582 return This->format.paralign;
1585 static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat *iface)
1587 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1588 TRACE("(%p)\n", This);
1589 return This->format.wrapping;
1592 static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat *iface)
1594 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1595 TRACE("(%p)\n", This);
1596 return This->format.readingdir;
1599 static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat *iface)
1601 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1602 TRACE("(%p)\n", This);
1603 return This->format.flow;
1606 static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat *iface)
1608 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1609 FIXME("(%p): stub\n", This);
1610 return 0.0;
1613 static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING *options,
1614 IDWriteInlineObject **trimming_sign)
1616 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1617 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
1619 *options = This->format.trimming;
1620 if ((*trimming_sign = This->format.trimmingsign))
1621 IDWriteInlineObject_AddRef(*trimming_sign);
1623 return S_OK;
1626 static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD *method,
1627 FLOAT *spacing, FLOAT *baseline)
1629 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1630 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
1632 *method = This->format.spacingmethod;
1633 *spacing = This->format.spacing;
1634 *baseline = This->format.baseline;
1635 return S_OK;
1638 static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat *iface, IDWriteFontCollection **collection)
1640 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1642 TRACE("(%p)->(%p)\n", This, collection);
1644 *collection = This->format.collection;
1645 IDWriteFontCollection_AddRef(*collection);
1647 return S_OK;
1650 static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat *iface)
1652 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1653 TRACE("(%p)\n", This);
1654 return This->format.family_len;
1657 static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1659 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1661 TRACE("(%p)->(%p %u)\n", This, name, size);
1663 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
1664 strcpyW(name, This->format.family_name);
1665 return S_OK;
1668 static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat *iface)
1670 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1671 TRACE("(%p)\n", This);
1672 return This->format.weight;
1675 static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat *iface)
1677 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1678 TRACE("(%p)\n", This);
1679 return This->format.style;
1682 static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat *iface)
1684 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1685 TRACE("(%p)\n", This);
1686 return This->format.stretch;
1689 static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat *iface)
1691 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1692 TRACE("(%p)\n", This);
1693 return This->format.fontsize;
1696 static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat *iface)
1698 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1699 TRACE("(%p)\n", This);
1700 return This->format.locale_len;
1703 static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1705 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1707 TRACE("(%p)->(%p %u)\n", This, name, size);
1709 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
1710 strcpyW(name, This->format.locale);
1711 return S_OK;
1714 static const IDWriteTextFormatVtbl dwritetextformatvtbl = {
1715 dwritetextformat_QueryInterface,
1716 dwritetextformat_AddRef,
1717 dwritetextformat_Release,
1718 dwritetextformat_SetTextAlignment,
1719 dwritetextformat_SetParagraphAlignment,
1720 dwritetextformat_SetWordWrapping,
1721 dwritetextformat_SetReadingDirection,
1722 dwritetextformat_SetFlowDirection,
1723 dwritetextformat_SetIncrementalTabStop,
1724 dwritetextformat_SetTrimming,
1725 dwritetextformat_SetLineSpacing,
1726 dwritetextformat_GetTextAlignment,
1727 dwritetextformat_GetParagraphAlignment,
1728 dwritetextformat_GetWordWrapping,
1729 dwritetextformat_GetReadingDirection,
1730 dwritetextformat_GetFlowDirection,
1731 dwritetextformat_GetIncrementalTabStop,
1732 dwritetextformat_GetTrimming,
1733 dwritetextformat_GetLineSpacing,
1734 dwritetextformat_GetFontCollection,
1735 dwritetextformat_GetFontFamilyNameLength,
1736 dwritetextformat_GetFontFamilyName,
1737 dwritetextformat_GetFontWeight,
1738 dwritetextformat_GetFontStyle,
1739 dwritetextformat_GetFontStretch,
1740 dwritetextformat_GetFontSize,
1741 dwritetextformat_GetLocaleNameLength,
1742 dwritetextformat_GetLocaleName
1745 HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
1746 DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
1748 struct dwrite_textformat *This;
1750 *format = NULL;
1752 This = heap_alloc(sizeof(struct dwrite_textformat));
1753 if (!This) return E_OUTOFMEMORY;
1755 This->IDWriteTextFormat_iface.lpVtbl = &dwritetextformatvtbl;
1756 This->ref = 1;
1757 This->format.family_name = heap_strdupW(family_name);
1758 This->format.family_len = strlenW(family_name);
1759 This->format.locale = heap_strdupW(locale);
1760 This->format.locale_len = strlenW(locale);
1761 This->format.weight = weight;
1762 This->format.style = style;
1763 This->format.fontsize = size;
1764 This->format.stretch = stretch;
1765 This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
1766 This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
1767 This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
1768 This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
1769 This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
1770 This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
1771 This->format.spacing = 0.0;
1772 This->format.baseline = 0.0;
1773 This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
1774 This->format.trimming.delimiter = 0;
1775 This->format.trimming.delimiterCount = 0;
1776 This->format.trimmingsign = NULL;
1778 if (collection)
1780 This->format.collection = collection;
1781 IDWriteFontCollection_AddRef(collection);
1783 else
1784 ERR("Collection should always be set\n");
1786 *format = &This->IDWriteTextFormat_iface;
1788 return S_OK;