dwrite: Avoid NULL ptr dereference (Coverity).
[wine.git] / dlls / dwrite / layout.c
blobf6b1e8c9c62ae257650e5420b158b138ad800ff4
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 struct dwrite_typography {
126 IDWriteTypography IDWriteTypography_iface;
127 LONG ref;
129 DWRITE_FONT_FEATURE *features;
130 UINT32 allocated;
131 UINT32 count;
134 static const IDWriteTextFormatVtbl dwritetextformatvtbl;
136 static void release_format_data(struct dwrite_textformat_data *data)
138 if (data->collection) IDWriteFontCollection_Release(data->collection);
139 if (data->trimmingsign) IDWriteInlineObject_Release(data->trimmingsign);
140 heap_free(data->family_name);
141 heap_free(data->locale);
144 static inline struct dwrite_textlayout *impl_from_IDWriteTextLayout(IDWriteTextLayout *iface)
146 return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextLayout_iface);
149 static inline struct dwrite_textformat *impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
151 return CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat_iface);
154 static inline struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
156 return iface->lpVtbl == &dwritetextformatvtbl ? impl_from_IDWriteTextFormat(iface) : NULL;
159 static inline struct dwrite_trimmingsign *impl_from_IDWriteInlineObject(IDWriteInlineObject *iface)
161 return CONTAINING_RECORD(iface, struct dwrite_trimmingsign, IDWriteInlineObject_iface);
164 static inline struct dwrite_typography *impl_from_IDWriteTypography(IDWriteTypography *iface)
166 return CONTAINING_RECORD(iface, struct dwrite_typography, IDWriteTypography_iface);
169 /* To be used in IDWriteTextLayout methods to validate and fix passed range */
170 static inline BOOL validate_text_range(struct dwrite_textlayout *layout, DWRITE_TEXT_RANGE *r)
172 if (r->startPosition >= layout->len)
173 return FALSE;
175 if (r->startPosition + r->length > layout->len)
176 r->length = layout->len - r->startPosition;
178 return TRUE;
181 static BOOL is_same_layout_attrvalue(struct layout_range const *range, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
183 switch (attr) {
184 case LAYOUT_RANGE_ATTR_WEIGHT:
185 return range->weight == value->u.weight;
186 case LAYOUT_RANGE_ATTR_STYLE:
187 return range->style == value->u.style;
188 case LAYOUT_RANGE_ATTR_STRETCH:
189 return range->stretch == value->u.stretch;
190 case LAYOUT_RANGE_ATTR_FONTSIZE:
191 return range->fontsize == value->u.fontsize;
192 case LAYOUT_RANGE_ATTR_INLINE:
193 return range->object == value->u.object;
194 case LAYOUT_RANGE_ATTR_EFFECT:
195 return range->effect == value->u.effect;
196 case LAYOUT_RANGE_ATTR_UNDERLINE:
197 return range->underline == value->u.underline;
198 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
199 return range->strikethrough == value->u.strikethrough;
200 case LAYOUT_RANGE_ATTR_FONTCOLL:
201 return range->collection == value->u.collection;
202 default:
206 return FALSE;
209 static inline BOOL is_same_layout_attributes(struct layout_range const *left, struct layout_range const *right)
211 return left->weight == right->weight &&
212 left->style == right->style &&
213 left->stretch == right->stretch &&
214 left->fontsize == right->fontsize &&
215 left->object == right->object &&
216 left->effect == right->effect &&
217 left->underline == right->underline &&
218 left->strikethrough == right->strikethrough &&
219 left->collection == right->collection;
222 static inline BOOL is_same_text_range(const DWRITE_TEXT_RANGE *left, const DWRITE_TEXT_RANGE *right)
224 return left->startPosition == right->startPosition && left->length == right->length;
227 /* Allocates range and inits it with default values from text format. */
228 static struct layout_range *alloc_layout_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *r)
230 struct layout_range *range;
232 range = heap_alloc(sizeof(*range));
233 if (!range) return NULL;
235 range->range = *r;
236 range->weight = layout->format.weight;
237 range->style = layout->format.style;
238 range->stretch = layout->format.stretch;
239 range->fontsize = layout->format.fontsize;
240 range->object = NULL;
241 range->effect = NULL;
242 range->underline = FALSE;
243 range->strikethrough = FALSE;
244 range->collection = layout->format.collection;
245 if (range->collection)
246 IDWriteFontCollection_AddRef(range->collection);
248 return range;
251 static struct layout_range *alloc_layout_range_from(struct layout_range *from, const DWRITE_TEXT_RANGE *r)
253 struct layout_range *range;
255 range = heap_alloc(sizeof(*range));
256 if (!range) return NULL;
258 *range = *from;
259 range->range = *r;
261 /* update refcounts */
262 if (range->object)
263 IDWriteInlineObject_AddRef(range->object);
264 if (range->effect)
265 IUnknown_AddRef(range->effect);
266 if (range->collection)
267 IDWriteFontCollection_AddRef(range->collection);
269 return range;
272 static void free_layout_range(struct layout_range *range)
274 if (!range)
275 return;
276 if (range->object)
277 IDWriteInlineObject_Release(range->object);
278 if (range->effect)
279 IUnknown_Release(range->effect);
280 if (range->collection)
281 IDWriteFontCollection_Release(range->collection);
282 heap_free(range);
285 static void free_layout_ranges_list(struct dwrite_textlayout *layout)
287 struct layout_range *cur, *cur2;
288 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->ranges, struct layout_range, entry) {
289 list_remove(&cur->entry);
290 free_layout_range(cur);
294 static struct layout_range *find_outer_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *range)
296 struct layout_range *cur;
298 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
300 if (cur->range.startPosition > range->startPosition)
301 return NULL;
303 if ((cur->range.startPosition + cur->range.length < range->startPosition + range->length) &&
304 (range->startPosition < cur->range.startPosition + cur->range.length))
305 return NULL;
306 if (cur->range.startPosition + cur->range.length >= range->startPosition + range->length)
307 return cur;
310 return NULL;
313 static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos)
315 struct layout_range *cur;
317 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
318 DWRITE_TEXT_RANGE *r = &cur->range;
319 if (r->startPosition <= pos && pos < r->startPosition + r->length)
320 return cur;
323 return NULL;
326 static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
328 BOOL changed = FALSE;
330 switch (attr) {
331 case LAYOUT_RANGE_ATTR_WEIGHT:
332 changed = dest->weight != value->u.weight;
333 dest->weight = value->u.weight;
334 break;
335 case LAYOUT_RANGE_ATTR_STYLE:
336 changed = dest->style != value->u.style;
337 dest->style = value->u.style;
338 break;
339 case LAYOUT_RANGE_ATTR_STRETCH:
340 changed = dest->stretch != value->u.stretch;
341 dest->stretch = value->u.stretch;
342 break;
343 case LAYOUT_RANGE_ATTR_FONTSIZE:
344 changed = dest->fontsize != value->u.fontsize;
345 dest->fontsize = value->u.fontsize;
346 break;
347 case LAYOUT_RANGE_ATTR_INLINE:
348 changed = dest->object != value->u.object;
349 if (changed && dest->object)
350 IDWriteInlineObject_Release(dest->object);
351 dest->object = value->u.object;
352 if (dest->object)
353 IDWriteInlineObject_AddRef(dest->object);
354 break;
355 case LAYOUT_RANGE_ATTR_EFFECT:
356 changed = dest->effect != value->u.effect;
357 if (changed && dest->effect)
358 IUnknown_Release(dest->effect);
359 dest->effect = value->u.effect;
360 if (dest->effect)
361 IUnknown_AddRef(dest->effect);
362 break;
363 case LAYOUT_RANGE_ATTR_UNDERLINE:
364 changed = dest->underline != value->u.underline;
365 dest->underline = value->u.underline;
366 break;
367 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
368 changed = dest->strikethrough != value->u.strikethrough;
369 dest->strikethrough = value->u.strikethrough;
370 break;
371 case LAYOUT_RANGE_ATTR_FONTCOLL:
372 changed = dest->collection != value->u.collection;
373 if (changed && dest->collection)
374 IDWriteFontCollection_Release(dest->collection);
375 dest->collection = value->u.collection;
376 if (dest->collection)
377 IDWriteFontCollection_AddRef(dest->collection);
378 break;
379 default:
383 return changed;
386 static inline BOOL is_in_layout_range(const DWRITE_TEXT_RANGE *outer, const DWRITE_TEXT_RANGE *inner)
388 return (inner->startPosition >= outer->startPosition) &&
389 (inner->startPosition + inner->length <= outer->startPosition + outer->length);
392 static inline HRESULT return_range(const struct layout_range *range, DWRITE_TEXT_RANGE *r)
394 if (r) *r = range->range;
395 return S_OK;
398 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
399 static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
401 struct layout_range *outer, *right, *left, *cur;
402 struct list *ranges = &layout->ranges;
403 BOOL changed = FALSE;
404 DWRITE_TEXT_RANGE r;
406 /* If new range is completely within existing range, split existing range in two */
407 if ((outer = find_outer_range(layout, &value->range))) {
409 /* no need to add same range */
410 if (is_same_layout_attrvalue(outer, attr, value))
411 return S_OK;
413 /* for matching range bounds just replace data */
414 if (is_same_text_range(&outer->range, &value->range)) {
415 changed = set_layout_range_attrval(outer, attr, value);
416 goto done;
419 /* add new range to the left */
420 if (value->range.startPosition == outer->range.startPosition) {
421 left = alloc_layout_range_from(outer, &value->range);
422 if (!left) return E_OUTOFMEMORY;
424 changed = set_layout_range_attrval(left, attr, value);
425 list_add_before(&outer->entry, &left->entry);
426 outer->range.startPosition += value->range.length;
427 outer->range.length -= value->range.length;
428 goto done;
431 /* add new range to the right */
432 if (value->range.startPosition + value->range.length == outer->range.startPosition + outer->range.length) {
433 right = alloc_layout_range_from(outer, &value->range);
434 if (!right) return E_OUTOFMEMORY;
436 changed = set_layout_range_attrval(right, attr, value);
437 list_add_after(&outer->entry, &right->entry);
438 outer->range.length -= value->range.length;
439 goto done;
442 r.startPosition = value->range.startPosition + value->range.length;
443 r.length = outer->range.length + outer->range.startPosition - r.startPosition;
445 /* right part */
446 right = alloc_layout_range_from(outer, &r);
447 /* new range in the middle */
448 cur = alloc_layout_range_from(outer, &value->range);
449 if (!right || !cur) {
450 free_layout_range(right);
451 free_layout_range(cur);
452 return E_OUTOFMEMORY;
455 /* reuse container range as a left part */
456 outer->range.length = value->range.startPosition - outer->range.startPosition;
458 /* new part */
459 set_layout_range_attrval(cur, attr, value);
461 list_add_after(&outer->entry, &cur->entry);
462 list_add_after(&cur->entry, &right->entry);
464 return S_OK;
467 /* Now it's only possible that given range contains some existing ranges, fully or partially.
468 Update all of them. */
469 left = get_layout_range_by_pos(layout, value->range.startPosition);
470 if (left->range.startPosition == value->range.startPosition)
471 changed = set_layout_range_attrval(left, attr, value);
472 else /* need to split */ {
473 r.startPosition = value->range.startPosition;
474 r.length = left->range.length - value->range.startPosition + left->range.startPosition;
475 left->range.length -= r.length;
476 cur = alloc_layout_range_from(left, &r);
477 changed = set_layout_range_attrval(cur, attr, value);
478 list_add_after(&left->entry, &cur->entry);
480 cur = LIST_ENTRY(list_next(ranges, &left->entry), struct layout_range, entry);
482 /* for all existing ranges covered by new one update value */
483 while (is_in_layout_range(&value->range, &cur->range)) {
484 changed = set_layout_range_attrval(cur, attr, value);
485 cur = LIST_ENTRY(list_next(ranges, &cur->entry), struct layout_range, entry);
488 /* it's possible rightmost range intersects */
489 if (cur && (cur->range.startPosition < value->range.startPosition + value->range.length)) {
490 r.startPosition = cur->range.startPosition;
491 r.length = value->range.startPosition + value->range.length - cur->range.startPosition;
492 left = alloc_layout_range_from(cur, &r);
493 changed = set_layout_range_attrval(left, attr, value);
494 cur->range.startPosition += left->range.length;
495 cur->range.length -= left->range.length;
496 list_add_before(&cur->entry, &left->entry);
499 done:
500 if (changed) {
501 struct list *next, *i;
503 i = list_head(ranges);
504 while ((next = list_next(ranges, i))) {
505 struct layout_range *next_range = LIST_ENTRY(next, struct layout_range, entry);
507 cur = LIST_ENTRY(i, struct layout_range, entry);
508 if (is_same_layout_attributes(cur, next_range)) {
509 /* remove similar range */
510 cur->range.length += next_range->range.length;
511 list_remove(next);
512 free_layout_range(next_range);
514 else
515 i = list_next(ranges, i);
519 return S_OK;
522 static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout *iface, REFIID riid, void **obj)
524 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
526 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
528 if (IsEqualIID(riid, &IID_IUnknown) ||
529 IsEqualIID(riid, &IID_IDWriteTextFormat) ||
530 IsEqualIID(riid, &IID_IDWriteTextLayout))
532 *obj = iface;
533 IDWriteTextLayout_AddRef(iface);
534 return S_OK;
537 *obj = NULL;
539 return E_NOINTERFACE;
542 static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout *iface)
544 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
545 ULONG ref = InterlockedIncrement(&This->ref);
546 TRACE("(%p)->(%d)\n", This, ref);
547 return ref;
550 static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout *iface)
552 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
553 ULONG ref = InterlockedDecrement(&This->ref);
555 TRACE("(%p)->(%d)\n", This, ref);
557 if (!ref) {
558 free_layout_ranges_list(This);
559 release_format_data(&This->format);
560 heap_free(This->str);
561 heap_free(This);
564 return ref;
567 static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout *iface, DWRITE_TEXT_ALIGNMENT alignment)
569 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
570 FIXME("(%p)->(%d): stub\n", This, alignment);
571 return E_NOTIMPL;
574 static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
576 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
577 FIXME("(%p)->(%d): stub\n", This, alignment);
578 return E_NOTIMPL;
581 static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout *iface, DWRITE_WORD_WRAPPING wrapping)
583 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
584 FIXME("(%p)->(%d): stub\n", This, wrapping);
585 return E_NOTIMPL;
588 static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout *iface, DWRITE_READING_DIRECTION direction)
590 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
591 FIXME("(%p)->(%d): stub\n", This, direction);
592 return E_NOTIMPL;
595 static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout *iface, DWRITE_FLOW_DIRECTION direction)
597 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
598 FIXME("(%p)->(%d): stub\n", This, direction);
599 return E_NOTIMPL;
602 static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout *iface, FLOAT tabstop)
604 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
605 FIXME("(%p)->(%f): stub\n", This, tabstop);
606 return E_NOTIMPL;
609 static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING const *trimming,
610 IDWriteInlineObject *trimming_sign)
612 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
613 FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
614 return E_NOTIMPL;
617 static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD spacing,
618 FLOAT line_spacing, FLOAT baseline)
620 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
621 FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
622 return E_NOTIMPL;
625 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout *iface)
627 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
628 TRACE("(%p)\n", This);
629 return This->format.textalignment;
632 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout *iface)
634 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
635 TRACE("(%p)\n", This);
636 return This->format.paralign;
639 static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout *iface)
641 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
642 FIXME("(%p): stub\n", This);
643 return This->format.wrapping;
646 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout *iface)
648 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
649 TRACE("(%p)\n", This);
650 return This->format.readingdir;
653 static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout *iface)
655 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
656 TRACE("(%p)\n", This);
657 return This->format.flow;
660 static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout *iface)
662 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
663 FIXME("(%p): stub\n", This);
664 return 0.0;
667 static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING *options,
668 IDWriteInlineObject **trimming_sign)
670 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
672 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
674 *options = This->format.trimming;
675 *trimming_sign = This->format.trimmingsign;
676 if (*trimming_sign)
677 IDWriteInlineObject_AddRef(*trimming_sign);
678 return S_OK;
681 static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD *method,
682 FLOAT *spacing, FLOAT *baseline)
684 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
686 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
688 *method = This->format.spacingmethod;
689 *spacing = This->format.spacing;
690 *baseline = This->format.baseline;
691 return S_OK;
694 static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection **collection)
696 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
698 TRACE("(%p)->(%p)\n", This, collection);
700 *collection = This->format.collection;
701 if (*collection)
702 IDWriteFontCollection_AddRef(*collection);
703 return S_OK;
706 static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout *iface)
708 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
709 TRACE("(%p)\n", This);
710 return This->format.family_len;
713 static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
715 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
717 TRACE("(%p)->(%p %u)\n", This, name, size);
719 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
720 strcpyW(name, This->format.family_name);
721 return S_OK;
724 static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout *iface)
726 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
727 TRACE("(%p)\n", This);
728 return This->format.weight;
731 static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout *iface)
733 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
734 TRACE("(%p)\n", This);
735 return This->format.style;
738 static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout *iface)
740 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
741 TRACE("(%p)\n", This);
742 return This->format.stretch;
745 static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout *iface)
747 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
748 TRACE("(%p)\n", This);
749 return This->format.fontsize;
752 static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout *iface)
754 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
755 TRACE("(%p)\n", This);
756 return This->format.locale_len;
759 static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
761 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
763 TRACE("(%p)->(%p %u)\n", This, name, size);
765 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
766 strcpyW(name, This->format.locale);
767 return S_OK;
770 static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout *iface, FLOAT maxWidth)
772 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
773 TRACE("(%p)->(%.1f)\n", This, maxWidth);
774 This->maxwidth = maxWidth;
775 return S_OK;
778 static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout *iface, FLOAT maxHeight)
780 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
781 TRACE("(%p)->(%.1f)\n", This, maxHeight);
782 This->maxheight = maxHeight;
783 return S_OK;
786 static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
788 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
789 struct layout_range_attr_value value;
791 TRACE("(%p)->(%p %s)\n", This, collection, debugstr_range(&range));
793 if (!validate_text_range(This, &range))
794 return S_OK;
796 value.range = range;
797 value.u.collection = collection;
798 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTCOLL, &value);
801 static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
803 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
804 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_range(&range));
805 return E_NOTIMPL;
808 static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
810 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
811 struct layout_range_attr_value value;
813 TRACE("(%p)->(%d %s)\n", This, weight, debugstr_range(&range));
815 if (!validate_text_range(This, &range))
816 return S_OK;
818 value.range = range;
819 value.u.weight = weight;
820 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_WEIGHT, &value);
823 static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
825 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
826 struct layout_range_attr_value value;
828 TRACE("(%p)->(%d %s)\n", This, style, debugstr_range(&range));
830 if (!validate_text_range(This, &range))
831 return S_OK;
833 value.range = range;
834 value.u.style = style;
835 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STYLE, &value);
838 static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
840 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
841 struct layout_range_attr_value value;
843 TRACE("(%p)->(%d %s)\n", This, stretch, debugstr_range(&range));
845 if (!validate_text_range(This, &range))
846 return S_OK;
848 value.range = range;
849 value.u.stretch = stretch;
850 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRETCH, &value);
853 static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout *iface, FLOAT size, DWRITE_TEXT_RANGE range)
855 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
856 struct layout_range_attr_value value;
858 TRACE("(%p)->(%.2f %s)\n", This, size, debugstr_range(&range));
860 if (!validate_text_range(This, &range))
861 return S_OK;
863 value.range = range;
864 value.u.fontsize = size;
865 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTSIZE, &value);
868 static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout *iface, BOOL underline, DWRITE_TEXT_RANGE range)
870 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
871 struct layout_range_attr_value value;
873 TRACE("(%p)->(%d %s)\n", This, underline, debugstr_range(&range));
875 if (!validate_text_range(This, &range))
876 return S_OK;
878 value.range = range;
879 value.u.underline = underline;
880 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_UNDERLINE, &value);
883 static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
885 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
886 struct layout_range_attr_value value;
888 TRACE("(%p)->(%d %s)\n", This, strikethrough, debugstr_range(&range));
890 if (!validate_text_range(This, &range))
891 return S_OK;
893 value.range = range;
894 value.u.underline = strikethrough;
895 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRIKETHROUGH, &value);
898 static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
900 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
901 struct layout_range_attr_value value;
903 TRACE("(%p)->(%p %s)\n", This, effect, debugstr_range(&range));
905 if (!validate_text_range(This, &range))
906 return S_OK;
908 value.range = range;
909 value.u.effect = effect;
910 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_EFFECT, &value);
913 static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE r)
915 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
916 struct layout_range_attr_value attr;
918 TRACE("(%p)->(%p %s)\n", This, object, debugstr_range(&r));
920 if (!validate_text_range(This, &r))
921 return S_OK;
923 attr.range = r;
924 attr.u.object = object;
926 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_INLINE, &attr);
929 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
931 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
932 FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
933 return E_NOTIMPL;
936 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
938 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
939 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(locale), debugstr_range(&range));
940 return E_NOTIMPL;
943 static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout *iface)
945 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
946 TRACE("(%p)\n", This);
947 return This->maxwidth;
950 static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout *iface)
952 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
953 TRACE("(%p)\n", This);
954 return This->maxheight;
957 static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout *iface, UINT32 position,
958 IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *r)
960 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
961 struct layout_range *range;
963 TRACE("(%p)->(%u %p %p)\n", This, position, collection, r);
965 range = get_layout_range_by_pos(This, position);
966 *collection = range ? range->collection : NULL;
967 if (*collection)
968 IDWriteFontCollection_AddRef(*collection);
970 return return_range(range, r);
973 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout *iface,
974 UINT32 pos, UINT32* len, DWRITE_TEXT_RANGE *range)
976 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
977 FIXME("(%p)->(%d %p %p): stub\n", This, pos, len, range);
978 return E_NOTIMPL;
981 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout *iface,
982 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
984 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
985 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
986 return E_NOTIMPL;
989 static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout *iface,
990 UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
992 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
993 struct layout_range *range;
995 TRACE("(%p)->(%u %p %p)\n", This, position, weight, r);
997 if (position >= This->len)
998 return S_OK;
1000 range = get_layout_range_by_pos(This, position);
1001 *weight = range->weight;
1003 return return_range(range, r);
1006 static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout *iface,
1007 UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
1009 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1010 struct layout_range *range;
1012 TRACE("(%p)->(%u %p %p)\n", This, position, style, r);
1014 if (position >= This->len)
1015 return S_OK;
1017 range = get_layout_range_by_pos(This, position);
1018 *style = range->style;
1020 return return_range(range, r);
1023 static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout *iface,
1024 UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *r)
1026 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1027 struct layout_range *range;
1029 TRACE("(%p)->(%u %p %p)\n", This, position, stretch, r);
1031 if (position >= This->len)
1032 return S_OK;
1034 range = get_layout_range_by_pos(This, position);
1035 *stretch = range->stretch;
1037 return return_range(range, r);
1040 static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout *iface,
1041 UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *r)
1043 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1044 struct layout_range *range;
1046 TRACE("(%p)->(%u %p %p)\n", This, position, size, r);
1048 if (position >= This->len)
1049 return S_OK;
1051 range = get_layout_range_by_pos(This, position);
1052 *size = range->fontsize;
1054 return return_range(range, r);
1057 static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout *iface,
1058 UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
1060 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1061 struct layout_range *range;
1063 TRACE("(%p)->(%u %p %p)\n", This, position, underline, r);
1065 if (position >= This->len)
1066 return S_OK;
1068 range = get_layout_range_by_pos(This, position);
1069 *underline = range->underline;
1071 return return_range(range, r);
1074 static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout *iface,
1075 UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
1077 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1078 struct layout_range *range;
1080 TRACE("(%p)->(%u %p %p)\n", This, position, strikethrough, r);
1082 if (position >= This->len)
1083 return S_OK;
1085 range = get_layout_range_by_pos(This, position);
1086 *strikethrough = range->strikethrough;
1088 return return_range(range, r);
1091 static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout *iface,
1092 UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
1094 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1095 struct layout_range *range;
1097 TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
1099 if (position >= This->len)
1100 return S_OK;
1102 range = get_layout_range_by_pos(This, position);
1103 *effect = range->effect;
1104 if (*effect)
1105 IUnknown_AddRef(*effect);
1107 return return_range(range, r);
1110 static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout *iface,
1111 UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
1113 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1114 struct layout_range *range;
1116 TRACE("(%p)->(%u %p %p)\n", This, position, object, r);
1118 range = get_layout_range_by_pos(This, position);
1119 *object = range ? range->object : NULL;
1120 if (*object)
1121 IDWriteInlineObject_AddRef(*object);
1123 return return_range(range, r);
1126 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout *iface,
1127 UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
1129 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1130 FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
1131 return E_NOTIMPL;
1134 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout *iface,
1135 UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *range)
1137 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1138 FIXME("(%p)->(%u %p %p): stub\n", This, position, length, range);
1139 return E_NOTIMPL;
1142 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout *iface,
1143 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
1145 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1146 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
1147 return E_NOTIMPL;
1150 static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout *iface,
1151 void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
1153 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1154 FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
1155 return E_NOTIMPL;
1158 static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout *iface,
1159 DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
1161 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1162 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
1163 return E_NOTIMPL;
1166 static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout *iface, DWRITE_TEXT_METRICS *metrics)
1168 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1169 FIXME("(%p)->(%p): stub\n", This, metrics);
1170 return E_NOTIMPL;
1173 static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout *iface, DWRITE_OVERHANG_METRICS *overhangs)
1175 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1176 FIXME("(%p)->(%p): stub\n", This, overhangs);
1177 return E_NOTIMPL;
1180 static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout *iface,
1181 DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32* act_count)
1183 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1184 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, act_count);
1185 return E_NOTIMPL;
1188 static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout *iface, FLOAT* min_width)
1190 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1191 FIXME("(%p)->(%p): stub\n", This, min_width);
1192 return E_NOTIMPL;
1195 static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout *iface,
1196 FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
1198 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1199 FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
1200 return E_NOTIMPL;
1203 static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout *iface,
1204 UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
1206 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1207 FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
1208 return E_NOTIMPL;
1211 static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout *iface,
1212 UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
1213 DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
1215 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1216 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
1217 max_metricscount, actual_metricscount);
1218 return E_NOTIMPL;
1221 static const IDWriteTextLayoutVtbl dwritetextlayoutvtbl = {
1222 dwritetextlayout_QueryInterface,
1223 dwritetextlayout_AddRef,
1224 dwritetextlayout_Release,
1225 dwritetextlayout_SetTextAlignment,
1226 dwritetextlayout_SetParagraphAlignment,
1227 dwritetextlayout_SetWordWrapping,
1228 dwritetextlayout_SetReadingDirection,
1229 dwritetextlayout_SetFlowDirection,
1230 dwritetextlayout_SetIncrementalTabStop,
1231 dwritetextlayout_SetTrimming,
1232 dwritetextlayout_SetLineSpacing,
1233 dwritetextlayout_GetTextAlignment,
1234 dwritetextlayout_GetParagraphAlignment,
1235 dwritetextlayout_GetWordWrapping,
1236 dwritetextlayout_GetReadingDirection,
1237 dwritetextlayout_GetFlowDirection,
1238 dwritetextlayout_GetIncrementalTabStop,
1239 dwritetextlayout_GetTrimming,
1240 dwritetextlayout_GetLineSpacing,
1241 dwritetextlayout_GetFontCollection,
1242 dwritetextlayout_GetFontFamilyNameLength,
1243 dwritetextlayout_GetFontFamilyName,
1244 dwritetextlayout_GetFontWeight,
1245 dwritetextlayout_GetFontStyle,
1246 dwritetextlayout_GetFontStretch,
1247 dwritetextlayout_GetFontSize,
1248 dwritetextlayout_GetLocaleNameLength,
1249 dwritetextlayout_GetLocaleName,
1250 dwritetextlayout_SetMaxWidth,
1251 dwritetextlayout_SetMaxHeight,
1252 dwritetextlayout_SetFontCollection,
1253 dwritetextlayout_SetFontFamilyName,
1254 dwritetextlayout_SetFontWeight,
1255 dwritetextlayout_SetFontStyle,
1256 dwritetextlayout_SetFontStretch,
1257 dwritetextlayout_SetFontSize,
1258 dwritetextlayout_SetUnderline,
1259 dwritetextlayout_SetStrikethrough,
1260 dwritetextlayout_SetDrawingEffect,
1261 dwritetextlayout_SetInlineObject,
1262 dwritetextlayout_SetTypography,
1263 dwritetextlayout_SetLocaleName,
1264 dwritetextlayout_GetMaxWidth,
1265 dwritetextlayout_GetMaxHeight,
1266 dwritetextlayout_layout_GetFontCollection,
1267 dwritetextlayout_layout_GetFontFamilyNameLength,
1268 dwritetextlayout_layout_GetFontFamilyName,
1269 dwritetextlayout_layout_GetFontWeight,
1270 dwritetextlayout_layout_GetFontStyle,
1271 dwritetextlayout_layout_GetFontStretch,
1272 dwritetextlayout_layout_GetFontSize,
1273 dwritetextlayout_GetUnderline,
1274 dwritetextlayout_GetStrikethrough,
1275 dwritetextlayout_GetDrawingEffect,
1276 dwritetextlayout_GetInlineObject,
1277 dwritetextlayout_GetTypography,
1278 dwritetextlayout_layout_GetLocaleNameLength,
1279 dwritetextlayout_layout_GetLocaleName,
1280 dwritetextlayout_Draw,
1281 dwritetextlayout_GetLineMetrics,
1282 dwritetextlayout_GetMetrics,
1283 dwritetextlayout_GetOverhangMetrics,
1284 dwritetextlayout_GetClusterMetrics,
1285 dwritetextlayout_DetermineMinWidth,
1286 dwritetextlayout_HitTestPoint,
1287 dwritetextlayout_HitTestTextPosition,
1288 dwritetextlayout_HitTestTextRange
1291 static void layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
1293 struct dwrite_textformat *f;
1295 memset(&layout->format, 0, sizeof(layout->format));
1297 if ((f = unsafe_impl_from_IDWriteTextFormat(format)))
1299 layout->format = f->format;
1300 layout->format.locale = heap_strdupW(f->format.locale);
1301 layout->format.family_name = heap_strdupW(f->format.family_name);
1302 if (layout->format.trimmingsign)
1303 IDWriteInlineObject_AddRef(layout->format.trimmingsign);
1305 else
1307 UINT32 locale_len, family_len;
1309 layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
1310 layout->format.style = IDWriteTextFormat_GetFontStyle(format);
1311 layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
1312 layout->format.fontsize= IDWriteTextFormat_GetFontSize(format);
1313 layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
1314 layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
1315 layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
1316 layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
1317 layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
1318 IDWriteTextFormat_GetLineSpacing(format,
1319 &layout->format.spacingmethod,
1320 &layout->format.spacing,
1321 &layout->format.baseline
1323 IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
1325 /* locale name and length */
1326 locale_len = IDWriteTextFormat_GetLocaleNameLength(format);
1327 layout->format.locale = heap_alloc((locale_len+1)*sizeof(WCHAR));
1328 IDWriteTextFormat_GetLocaleName(format, layout->format.locale, locale_len+1);
1329 layout->format.locale_len = locale_len;
1331 /* font family name and length */
1332 family_len = IDWriteTextFormat_GetFontFamilyNameLength(format);
1333 layout->format.family_name = heap_alloc((family_len+1)*sizeof(WCHAR));
1334 IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, family_len+1);
1335 layout->format.family_len = family_len;
1338 IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
1341 HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, IDWriteTextLayout **layout)
1343 struct dwrite_textlayout *This;
1344 struct layout_range *range;
1345 DWRITE_TEXT_RANGE r = { 0, len };
1347 *layout = NULL;
1349 This = heap_alloc(sizeof(struct dwrite_textlayout));
1350 if (!This) return E_OUTOFMEMORY;
1352 This->IDWriteTextLayout_iface.lpVtbl = &dwritetextlayoutvtbl;
1353 This->ref = 1;
1354 This->str = heap_strdupnW(str, len);
1355 This->len = len;
1356 This->maxwidth = maxwidth;
1357 This->maxheight = maxheight;
1358 layout_format_from_textformat(This, format);
1360 list_init(&This->ranges);
1361 range = alloc_layout_range(This, &r);
1362 if (!range) {
1363 IDWriteTextLayout_Release(&This->IDWriteTextLayout_iface);
1364 return E_OUTOFMEMORY;
1366 list_add_head(&This->ranges, &range->entry);
1368 *layout = &This->IDWriteTextLayout_iface;
1370 return S_OK;
1373 static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
1375 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1377 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1379 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
1380 *obj = iface;
1381 IDWriteInlineObject_AddRef(iface);
1382 return S_OK;
1385 *obj = NULL;
1386 return E_NOINTERFACE;
1390 static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
1392 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1393 ULONG ref = InterlockedIncrement(&This->ref);
1394 TRACE("(%p)->(%d)\n", This, ref);
1395 return ref;
1398 static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
1400 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1401 ULONG ref = InterlockedDecrement(&This->ref);
1403 TRACE("(%p)->(%d)\n", This, ref);
1405 if (!ref)
1406 heap_free(This);
1408 return ref;
1411 static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
1412 FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
1414 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1415 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This, context, renderer, originX, originY, is_sideways, is_rtl, drawing_effect);
1416 return E_NOTIMPL;
1419 static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
1421 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1422 FIXME("(%p)->(%p): stub\n", This, metrics);
1423 return E_NOTIMPL;
1426 static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
1428 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1429 FIXME("(%p)->(%p): stub\n", This, overhangs);
1430 return E_NOTIMPL;
1433 static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
1434 DWRITE_BREAK_CONDITION *after)
1436 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1438 TRACE("(%p)->(%p %p)\n", This, before, after);
1440 *before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
1441 return S_OK;
1444 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
1445 dwritetrimmingsign_QueryInterface,
1446 dwritetrimmingsign_AddRef,
1447 dwritetrimmingsign_Release,
1448 dwritetrimmingsign_Draw,
1449 dwritetrimmingsign_GetMetrics,
1450 dwritetrimmingsign_GetOverhangMetrics,
1451 dwritetrimmingsign_GetBreakConditions
1454 HRESULT create_trimmingsign(IDWriteInlineObject **sign)
1456 struct dwrite_trimmingsign *This;
1458 *sign = NULL;
1460 This = heap_alloc(sizeof(struct dwrite_trimmingsign));
1461 if (!This) return E_OUTOFMEMORY;
1463 This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
1464 This->ref = 1;
1466 *sign = &This->IDWriteInlineObject_iface;
1468 return S_OK;
1471 static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat *iface, REFIID riid, void **obj)
1473 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1475 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1477 if (IsEqualIID(riid, &IID_IUnknown) ||
1478 IsEqualIID(riid, &IID_IDWriteTextFormat))
1480 *obj = iface;
1481 IDWriteTextFormat_AddRef(iface);
1482 return S_OK;
1485 *obj = NULL;
1487 return E_NOINTERFACE;
1490 static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat *iface)
1492 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1493 ULONG ref = InterlockedIncrement(&This->ref);
1494 TRACE("(%p)->(%d)\n", This, ref);
1495 return ref;
1498 static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat *iface)
1500 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1501 ULONG ref = InterlockedDecrement(&This->ref);
1503 TRACE("(%p)->(%d)\n", This, ref);
1505 if (!ref)
1507 release_format_data(&This->format);
1508 heap_free(This);
1511 return ref;
1514 static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat *iface, DWRITE_TEXT_ALIGNMENT alignment)
1516 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1517 TRACE("(%p)->(%d)\n", This, alignment);
1518 This->format.textalignment = alignment;
1519 return S_OK;
1522 static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
1524 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1525 TRACE("(%p)->(%d)\n", This, alignment);
1526 This->format.paralign = alignment;
1527 return S_OK;
1530 static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat *iface, DWRITE_WORD_WRAPPING wrapping)
1532 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1533 TRACE("(%p)->(%d)\n", This, wrapping);
1534 This->format.wrapping = wrapping;
1535 return S_OK;
1538 static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat *iface, DWRITE_READING_DIRECTION direction)
1540 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1541 TRACE("(%p)->(%d)\n", This, direction);
1542 This->format.readingdir = direction;
1543 return S_OK;
1546 static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat *iface, DWRITE_FLOW_DIRECTION direction)
1548 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1549 TRACE("(%p)->(%d)\n", This, direction);
1550 This->format.flow = direction;
1551 return S_OK;
1554 static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat *iface, FLOAT tabstop)
1556 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1557 FIXME("(%p)->(%f): stub\n", This, tabstop);
1558 return E_NOTIMPL;
1561 static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING const *trimming,
1562 IDWriteInlineObject *trimming_sign)
1564 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1565 TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign);
1567 This->format.trimming = *trimming;
1568 if (This->format.trimmingsign)
1569 IDWriteInlineObject_Release(This->format.trimmingsign);
1570 This->format.trimmingsign = trimming_sign;
1571 if (This->format.trimmingsign)
1572 IDWriteInlineObject_AddRef(This->format.trimmingsign);
1573 return S_OK;
1576 static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD method,
1577 FLOAT spacing, FLOAT baseline)
1579 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1580 TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
1581 This->format.spacingmethod = method;
1582 This->format.spacing = spacing;
1583 This->format.baseline = baseline;
1584 return S_OK;
1587 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat *iface)
1589 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1590 TRACE("(%p)\n", This);
1591 return This->format.textalignment;
1594 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat *iface)
1596 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1597 TRACE("(%p)\n", This);
1598 return This->format.paralign;
1601 static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat *iface)
1603 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1604 TRACE("(%p)\n", This);
1605 return This->format.wrapping;
1608 static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat *iface)
1610 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1611 TRACE("(%p)\n", This);
1612 return This->format.readingdir;
1615 static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat *iface)
1617 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1618 TRACE("(%p)\n", This);
1619 return This->format.flow;
1622 static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat *iface)
1624 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1625 FIXME("(%p): stub\n", This);
1626 return 0.0;
1629 static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING *options,
1630 IDWriteInlineObject **trimming_sign)
1632 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1633 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
1635 *options = This->format.trimming;
1636 if ((*trimming_sign = This->format.trimmingsign))
1637 IDWriteInlineObject_AddRef(*trimming_sign);
1639 return S_OK;
1642 static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD *method,
1643 FLOAT *spacing, FLOAT *baseline)
1645 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1646 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
1648 *method = This->format.spacingmethod;
1649 *spacing = This->format.spacing;
1650 *baseline = This->format.baseline;
1651 return S_OK;
1654 static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat *iface, IDWriteFontCollection **collection)
1656 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1658 TRACE("(%p)->(%p)\n", This, collection);
1660 *collection = This->format.collection;
1661 IDWriteFontCollection_AddRef(*collection);
1663 return S_OK;
1666 static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat *iface)
1668 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1669 TRACE("(%p)\n", This);
1670 return This->format.family_len;
1673 static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1675 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1677 TRACE("(%p)->(%p %u)\n", This, name, size);
1679 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
1680 strcpyW(name, This->format.family_name);
1681 return S_OK;
1684 static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat *iface)
1686 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1687 TRACE("(%p)\n", This);
1688 return This->format.weight;
1691 static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat *iface)
1693 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1694 TRACE("(%p)\n", This);
1695 return This->format.style;
1698 static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat *iface)
1700 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1701 TRACE("(%p)\n", This);
1702 return This->format.stretch;
1705 static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat *iface)
1707 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1708 TRACE("(%p)\n", This);
1709 return This->format.fontsize;
1712 static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat *iface)
1714 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1715 TRACE("(%p)\n", This);
1716 return This->format.locale_len;
1719 static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1721 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1723 TRACE("(%p)->(%p %u)\n", This, name, size);
1725 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
1726 strcpyW(name, This->format.locale);
1727 return S_OK;
1730 static const IDWriteTextFormatVtbl dwritetextformatvtbl = {
1731 dwritetextformat_QueryInterface,
1732 dwritetextformat_AddRef,
1733 dwritetextformat_Release,
1734 dwritetextformat_SetTextAlignment,
1735 dwritetextformat_SetParagraphAlignment,
1736 dwritetextformat_SetWordWrapping,
1737 dwritetextformat_SetReadingDirection,
1738 dwritetextformat_SetFlowDirection,
1739 dwritetextformat_SetIncrementalTabStop,
1740 dwritetextformat_SetTrimming,
1741 dwritetextformat_SetLineSpacing,
1742 dwritetextformat_GetTextAlignment,
1743 dwritetextformat_GetParagraphAlignment,
1744 dwritetextformat_GetWordWrapping,
1745 dwritetextformat_GetReadingDirection,
1746 dwritetextformat_GetFlowDirection,
1747 dwritetextformat_GetIncrementalTabStop,
1748 dwritetextformat_GetTrimming,
1749 dwritetextformat_GetLineSpacing,
1750 dwritetextformat_GetFontCollection,
1751 dwritetextformat_GetFontFamilyNameLength,
1752 dwritetextformat_GetFontFamilyName,
1753 dwritetextformat_GetFontWeight,
1754 dwritetextformat_GetFontStyle,
1755 dwritetextformat_GetFontStretch,
1756 dwritetextformat_GetFontSize,
1757 dwritetextformat_GetLocaleNameLength,
1758 dwritetextformat_GetLocaleName
1761 HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
1762 DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
1764 struct dwrite_textformat *This;
1766 *format = NULL;
1768 This = heap_alloc(sizeof(struct dwrite_textformat));
1769 if (!This) return E_OUTOFMEMORY;
1771 This->IDWriteTextFormat_iface.lpVtbl = &dwritetextformatvtbl;
1772 This->ref = 1;
1773 This->format.family_name = heap_strdupW(family_name);
1774 This->format.family_len = strlenW(family_name);
1775 This->format.locale = heap_strdupW(locale);
1776 This->format.locale_len = strlenW(locale);
1777 This->format.weight = weight;
1778 This->format.style = style;
1779 This->format.fontsize = size;
1780 This->format.stretch = stretch;
1781 This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
1782 This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
1783 This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
1784 This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
1785 This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
1786 This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
1787 This->format.spacing = 0.0;
1788 This->format.baseline = 0.0;
1789 This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
1790 This->format.trimming.delimiter = 0;
1791 This->format.trimming.delimiterCount = 0;
1792 This->format.trimmingsign = NULL;
1794 if (collection)
1796 This->format.collection = collection;
1797 IDWriteFontCollection_AddRef(collection);
1799 else
1800 ERR("Collection should always be set\n");
1802 *format = &This->IDWriteTextFormat_iface;
1804 return S_OK;
1807 static HRESULT WINAPI dwritetypography_QueryInterface(IDWriteTypography *iface, REFIID riid, void **obj)
1809 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
1811 TRACE("(%p)->(%s %p)\n", typography, debugstr_guid(riid), obj);
1813 if (IsEqualIID(riid, &IID_IDWriteTypography) || IsEqualIID(riid, &IID_IUnknown)) {
1814 *obj = iface;
1815 IDWriteTypography_AddRef(iface);
1816 return S_OK;
1819 *obj = NULL;
1821 return E_NOINTERFACE;
1824 static ULONG WINAPI dwritetypography_AddRef(IDWriteTypography *iface)
1826 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
1827 ULONG ref = InterlockedIncrement(&typography->ref);
1828 TRACE("(%p)->(%d)\n", typography, ref);
1829 return ref;
1832 static ULONG WINAPI dwritetypography_Release(IDWriteTypography *iface)
1834 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
1835 ULONG ref = InterlockedDecrement(&typography->ref);
1837 TRACE("(%p)->(%d)\n", typography, ref);
1839 if (!ref) {
1840 heap_free(typography->features);
1841 heap_free(typography);
1844 return ref;
1847 static HRESULT WINAPI dwritetypography_AddFontFeature(IDWriteTypography *iface, DWRITE_FONT_FEATURE feature)
1849 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
1851 TRACE("(%p)->(%x %u)\n", typography, feature.nameTag, feature.parameter);
1853 if (typography->count == typography->allocated) {
1854 DWRITE_FONT_FEATURE *ptr = heap_realloc(typography->features, 2*typography->allocated*sizeof(DWRITE_FONT_FEATURE));
1855 if (!ptr)
1856 return E_OUTOFMEMORY;
1858 typography->features = ptr;
1859 typography->allocated *= 2;
1862 typography->features[typography->count++] = feature;
1863 return S_OK;
1866 static UINT32 WINAPI dwritetypography_GetFontFeatureCount(IDWriteTypography *iface)
1868 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
1869 TRACE("(%p)\n", typography);
1870 return typography->count;
1873 static HRESULT WINAPI dwritetypography_GetFontFeature(IDWriteTypography *iface, UINT32 index, DWRITE_FONT_FEATURE *feature)
1875 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
1877 TRACE("(%p)->(%u %p)\n", typography, index, feature);
1879 if (index >= typography->count)
1880 return E_INVALIDARG;
1882 *feature = typography->features[index];
1883 return S_OK;
1886 static const IDWriteTypographyVtbl dwritetypographyvtbl = {
1887 dwritetypography_QueryInterface,
1888 dwritetypography_AddRef,
1889 dwritetypography_Release,
1890 dwritetypography_AddFontFeature,
1891 dwritetypography_GetFontFeatureCount,
1892 dwritetypography_GetFontFeature
1895 HRESULT create_typography(IDWriteTypography **ret)
1897 struct dwrite_typography *typography;
1899 *ret = NULL;
1901 typography = heap_alloc(sizeof(*typography));
1902 if (!typography)
1903 return E_OUTOFMEMORY;
1905 typography->IDWriteTypography_iface.lpVtbl = &dwritetypographyvtbl;
1906 typography->ref = 1;
1907 typography->allocated = 2;
1908 typography->count = 0;
1910 typography->features = heap_alloc(typography->allocated*sizeof(DWRITE_FONT_FEATURE));
1911 if (!typography->features) {
1912 heap_free(typography);
1913 return E_OUTOFMEMORY;
1916 *ret = &typography->IDWriteTypography_iface;
1917 return S_OK;