dwrite: Use layout pointer as an argument instead of neutral list.
[wine/multimedia.git] / dlls / dwrite / layout.c
blob2ef7c9fab1b523a83878c7e8902b8e4af6d14f58
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 size;
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_EFFECT,
65 LAYOUT_RANGE_ATTR_INLINE,
66 LAYOUT_RANGE_ATTR_UNDERLINE,
67 LAYOUT_RANGE_ATTR_STRIKETHROUGH
70 struct layout_range_attr_value {
71 DWRITE_TEXT_RANGE range;
72 union {
73 DWRITE_FONT_WEIGHT weight;
74 DWRITE_FONT_STYLE style;
75 IDWriteInlineObject *object;
76 IUnknown *effect;
77 BOOL underline;
78 BOOL strikethrough;
79 } u;
82 struct layout_range {
83 struct list entry;
84 DWRITE_TEXT_RANGE range;
85 DWRITE_FONT_WEIGHT weight;
86 DWRITE_FONT_STYLE style;
87 IDWriteInlineObject *object;
88 IUnknown *effect;
89 BOOL underline;
90 BOOL strikethrough;
93 struct dwrite_textlayout {
94 IDWriteTextLayout IDWriteTextLayout_iface;
95 LONG ref;
97 WCHAR *str;
98 UINT32 len;
99 struct dwrite_textformat_data format;
100 FLOAT maxwidth;
101 FLOAT maxheight;
102 struct list ranges;
105 struct dwrite_textformat {
106 IDWriteTextFormat IDWriteTextFormat_iface;
107 LONG ref;
108 struct dwrite_textformat_data format;
111 struct dwrite_trimmingsign {
112 IDWriteInlineObject IDWriteInlineObject_iface;
113 LONG ref;
116 static const IDWriteTextFormatVtbl dwritetextformatvtbl;
118 static void release_format_data(struct dwrite_textformat_data *data)
120 if (data->collection) IDWriteFontCollection_Release(data->collection);
121 if (data->trimmingsign) IDWriteInlineObject_Release(data->trimmingsign);
122 heap_free(data->family_name);
123 heap_free(data->locale);
126 static inline struct dwrite_textlayout *impl_from_IDWriteTextLayout(IDWriteTextLayout *iface)
128 return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextLayout_iface);
131 static inline struct dwrite_textformat *impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
133 return CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat_iface);
136 static inline struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
138 return iface->lpVtbl == &dwritetextformatvtbl ? impl_from_IDWriteTextFormat(iface) : NULL;
141 static inline struct dwrite_trimmingsign *impl_from_IDWriteInlineObject(IDWriteInlineObject *iface)
143 return CONTAINING_RECORD(iface, struct dwrite_trimmingsign, IDWriteInlineObject_iface);
146 /* To be used in IDWriteTextLayout methods to validate and fix passed range */
147 static inline BOOL validate_text_range(struct dwrite_textlayout *layout, DWRITE_TEXT_RANGE *r)
149 if (r->startPosition >= layout->len)
150 return FALSE;
152 if (r->startPosition + r->length > layout->len)
153 r->length = layout->len - r->startPosition;
155 return TRUE;
158 static BOOL is_same_layout_attrvalue(struct layout_range const *range, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
160 switch (attr) {
161 case LAYOUT_RANGE_ATTR_WEIGHT:
162 return range->weight == value->u.weight;
163 case LAYOUT_RANGE_ATTR_STYLE:
164 return range->style == value->u.style;
165 case LAYOUT_RANGE_ATTR_INLINE:
166 return range->object == value->u.object;
167 case LAYOUT_RANGE_ATTR_EFFECT:
168 return range->effect == value->u.effect;
169 case LAYOUT_RANGE_ATTR_UNDERLINE:
170 return range->underline == value->u.underline;
171 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
172 return range->strikethrough == value->u.strikethrough;
173 default:
177 return FALSE;
180 static inline BOOL is_same_layout_attributes(struct layout_range const *left, struct layout_range const *right)
182 return left->weight == right->weight &&
183 left->style == right->style &&
184 left->object == right->object &&
185 left->effect == right->effect &&
186 left->underline == right->underline &&
187 left->strikethrough == right->strikethrough;
190 static inline BOOL is_same_text_range(const DWRITE_TEXT_RANGE *left, const DWRITE_TEXT_RANGE *right)
192 return left->startPosition == right->startPosition && left->length == right->length;
195 /* Allocates range and inits it with default values from text format. */
196 static struct layout_range *alloc_layout_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *r)
198 struct layout_range *range;
200 range = heap_alloc(sizeof(*range));
201 if (!range) return NULL;
203 range->range = *r;
204 range->weight = layout->format.weight;
205 range->style = layout->format.style;
206 range->object = NULL;
207 range->effect = NULL;
208 range->underline = FALSE;
209 range->strikethrough = FALSE;
211 return range;
214 static struct layout_range *alloc_layout_range_from(struct layout_range *from, const DWRITE_TEXT_RANGE *r)
216 struct layout_range *range;
218 range = heap_alloc(sizeof(*range));
219 if (!range) return NULL;
221 *range = *from;
222 range->range = *r;
224 /* update refcounts */
225 if (range->object)
226 IDWriteInlineObject_AddRef(range->object);
227 if (range->effect)
228 IUnknown_AddRef(range->effect);
230 return range;
233 static void free_layout_range(struct layout_range *range)
235 if (range->object)
236 IDWriteInlineObject_Release(range->object);
237 if (range->effect)
238 IUnknown_Release(range->effect);
239 heap_free(range);
242 static void free_layout_ranges_list(struct dwrite_textlayout *layout)
244 struct layout_range *cur, *cur2;
245 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->ranges, struct layout_range, entry) {
246 list_remove(&cur->entry);
247 free_layout_range(cur);
251 static struct layout_range *find_outer_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *range)
253 struct layout_range *cur;
255 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
257 if (cur->range.startPosition > range->startPosition)
258 return NULL;
260 if ((cur->range.startPosition + cur->range.length < range->startPosition + range->length) &&
261 (range->startPosition < cur->range.startPosition + cur->range.length))
262 return NULL;
263 if (cur->range.startPosition + cur->range.length >= range->startPosition + range->length)
264 return cur;
267 return NULL;
270 static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos)
272 struct layout_range *cur;
274 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
275 DWRITE_TEXT_RANGE *r = &cur->range;
276 if (r->startPosition <= pos && pos < r->startPosition + r->length)
277 return cur;
280 return NULL;
283 static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
285 BOOL changed = FALSE;
287 switch (attr) {
288 case LAYOUT_RANGE_ATTR_WEIGHT:
289 changed = dest->weight != value->u.weight;
290 dest->weight = value->u.weight;
291 break;
292 case LAYOUT_RANGE_ATTR_STYLE:
293 changed = dest->style != value->u.style;
294 dest->style = value->u.style;
295 break;
296 case LAYOUT_RANGE_ATTR_INLINE:
297 changed = dest->object != value->u.object;
298 if (changed && dest->object)
299 IDWriteInlineObject_Release(dest->object);
300 dest->object = value->u.object;
301 if (dest->object)
302 IDWriteInlineObject_AddRef(dest->object);
303 break;
304 case LAYOUT_RANGE_ATTR_EFFECT:
305 changed = dest->effect != value->u.effect;
306 if (changed && dest->effect)
307 IUnknown_Release(dest->effect);
308 dest->effect = value->u.effect;
309 if (dest->effect)
310 IUnknown_AddRef(dest->effect);
311 break;
312 case LAYOUT_RANGE_ATTR_UNDERLINE:
313 changed = dest->underline != value->u.underline;
314 dest->underline = value->u.underline;
315 break;
316 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
317 changed = dest->strikethrough != value->u.strikethrough;
318 dest->strikethrough = value->u.strikethrough;
319 break;
320 default:
324 return changed;
327 static inline BOOL is_in_layout_range(const DWRITE_TEXT_RANGE *outer, const DWRITE_TEXT_RANGE *inner)
329 return (inner->startPosition >= outer->startPosition) &&
330 (inner->startPosition + inner->length <= outer->startPosition + outer->length);
333 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
334 static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
336 struct layout_range *outer, *right, *left, *cur;
337 struct list *ranges = &layout->ranges;
338 BOOL changed = FALSE;
339 DWRITE_TEXT_RANGE r;
341 /* If new range is completely within existing range, split existing range in two */
342 if ((outer = find_outer_range(layout, &value->range))) {
344 /* no need to add same range */
345 if (is_same_layout_attrvalue(outer, attr, value))
346 return S_OK;
348 /* for matching range bounds just replace data */
349 if (is_same_text_range(&outer->range, &value->range)) {
350 changed = set_layout_range_attrval(outer, attr, value);
351 goto done;
354 /* add new range to the left */
355 if (value->range.startPosition == outer->range.startPosition) {
356 left = alloc_layout_range_from(outer, &value->range);
357 if (!left) return E_OUTOFMEMORY;
359 changed = set_layout_range_attrval(left, attr, value);
360 list_add_before(&outer->entry, &left->entry);
361 outer->range.startPosition += value->range.length;
362 outer->range.length -= value->range.length;
363 goto done;
366 /* add new range to the right */
367 if (value->range.startPosition + value->range.length == outer->range.startPosition + outer->range.length) {
368 right = alloc_layout_range_from(outer, &value->range);
369 if (!right) return E_OUTOFMEMORY;
371 changed = set_layout_range_attrval(right, attr, value);
372 list_add_after(&outer->entry, &right->entry);
373 outer->range.length -= value->range.length;
374 goto done;
377 r.startPosition = value->range.startPosition + value->range.length;
378 r.length = outer->range.length + outer->range.startPosition - r.startPosition;
380 /* right part */
381 right = alloc_layout_range_from(outer, &r);
382 /* new range in the middle */
383 cur = alloc_layout_range_from(outer, &value->range);
384 if (!right || !cur) {
385 free_layout_range(right);
386 free_layout_range(cur);
387 return E_OUTOFMEMORY;
390 /* reuse container range as a left part */
391 outer->range.length = value->range.startPosition - outer->range.startPosition;
393 /* new part */
394 set_layout_range_attrval(cur, attr, value);
396 list_add_after(&outer->entry, &cur->entry);
397 list_add_after(&cur->entry, &right->entry);
399 return S_OK;
402 /* Now it's only possible that given range contains some existing ranges, fully or partially.
403 Update all of them. */
404 left = get_layout_range_by_pos(layout, value->range.startPosition);
405 if (left->range.startPosition == value->range.startPosition)
406 changed = set_layout_range_attrval(left, attr, value);
407 else /* need to split */ {
408 r.startPosition = value->range.startPosition;
409 r.length = left->range.length - value->range.startPosition + left->range.startPosition;
410 left->range.length -= r.length;
411 cur = alloc_layout_range_from(left, &r);
412 changed = set_layout_range_attrval(cur, attr, value);
413 list_add_after(&left->entry, &cur->entry);
415 cur = LIST_ENTRY(list_next(ranges, &left->entry), struct layout_range, entry);
417 /* for all existing ranges covered by new one update value */
418 while (is_in_layout_range(&value->range, &cur->range)) {
419 changed = set_layout_range_attrval(cur, attr, value);
420 cur = LIST_ENTRY(list_next(ranges, &cur->entry), struct layout_range, entry);
423 /* it's possible rightmost range intersects */
424 if (cur && (cur->range.startPosition < value->range.startPosition + value->range.length)) {
425 r.startPosition = cur->range.startPosition;
426 r.length = value->range.startPosition + value->range.length - cur->range.startPosition;
427 left = alloc_layout_range_from(cur, &r);
428 changed = set_layout_range_attrval(left, attr, value);
429 cur->range.startPosition += left->range.length;
430 cur->range.length -= left->range.length;
431 list_add_before(&cur->entry, &left->entry);
434 done:
435 if (changed) {
436 struct list *next, *i;
438 i = list_head(ranges);
439 while ((next = list_next(ranges, i))) {
440 struct layout_range *next_range = LIST_ENTRY(next, struct layout_range, entry);
442 cur = LIST_ENTRY(i, struct layout_range, entry);
443 if (is_same_layout_attributes(cur, next_range)) {
444 /* remove similar range */
445 cur->range.length += next_range->range.length;
446 list_remove(next);
447 free_layout_range(next_range);
449 else
450 i = list_next(ranges, i);
454 return S_OK;
457 static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout *iface, REFIID riid, void **obj)
459 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
461 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
463 if (IsEqualIID(riid, &IID_IUnknown) ||
464 IsEqualIID(riid, &IID_IDWriteTextFormat) ||
465 IsEqualIID(riid, &IID_IDWriteTextLayout))
467 *obj = iface;
468 IDWriteTextLayout_AddRef(iface);
469 return S_OK;
472 *obj = NULL;
474 return E_NOINTERFACE;
477 static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout *iface)
479 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
480 ULONG ref = InterlockedIncrement(&This->ref);
481 TRACE("(%p)->(%d)\n", This, ref);
482 return ref;
485 static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout *iface)
487 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
488 ULONG ref = InterlockedDecrement(&This->ref);
490 TRACE("(%p)->(%d)\n", This, ref);
492 if (!ref) {
493 free_layout_ranges_list(This);
494 release_format_data(&This->format);
495 heap_free(This->str);
496 heap_free(This);
499 return ref;
502 static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout *iface, DWRITE_TEXT_ALIGNMENT alignment)
504 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
505 FIXME("(%p)->(%d): stub\n", This, alignment);
506 return E_NOTIMPL;
509 static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
511 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
512 FIXME("(%p)->(%d): stub\n", This, alignment);
513 return E_NOTIMPL;
516 static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout *iface, DWRITE_WORD_WRAPPING wrapping)
518 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
519 FIXME("(%p)->(%d): stub\n", This, wrapping);
520 return E_NOTIMPL;
523 static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout *iface, DWRITE_READING_DIRECTION direction)
525 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
526 FIXME("(%p)->(%d): stub\n", This, direction);
527 return E_NOTIMPL;
530 static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout *iface, DWRITE_FLOW_DIRECTION direction)
532 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
533 FIXME("(%p)->(%d): stub\n", This, direction);
534 return E_NOTIMPL;
537 static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout *iface, FLOAT tabstop)
539 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
540 FIXME("(%p)->(%f): stub\n", This, tabstop);
541 return E_NOTIMPL;
544 static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING const *trimming,
545 IDWriteInlineObject *trimming_sign)
547 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
548 FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
549 return E_NOTIMPL;
552 static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD spacing,
553 FLOAT line_spacing, FLOAT baseline)
555 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
556 FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
557 return E_NOTIMPL;
560 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout *iface)
562 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
563 TRACE("(%p)\n", This);
564 return This->format.textalignment;
567 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout *iface)
569 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
570 TRACE("(%p)\n", This);
571 return This->format.paralign;
574 static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout *iface)
576 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
577 FIXME("(%p): stub\n", This);
578 return This->format.wrapping;
581 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout *iface)
583 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
584 TRACE("(%p)\n", This);
585 return This->format.readingdir;
588 static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout *iface)
590 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
591 TRACE("(%p)\n", This);
592 return This->format.flow;
595 static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout *iface)
597 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
598 FIXME("(%p): stub\n", This);
599 return 0.0;
602 static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING *options,
603 IDWriteInlineObject **trimming_sign)
605 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
607 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
609 *options = This->format.trimming;
610 *trimming_sign = This->format.trimmingsign;
611 if (*trimming_sign)
612 IDWriteInlineObject_AddRef(*trimming_sign);
613 return S_OK;
616 static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD *method,
617 FLOAT *spacing, FLOAT *baseline)
619 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
621 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
623 *method = This->format.spacingmethod;
624 *spacing = This->format.spacing;
625 *baseline = This->format.baseline;
626 return S_OK;
629 static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection **collection)
631 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
633 TRACE("(%p)->(%p)\n", This, collection);
635 *collection = This->format.collection;
636 if (*collection)
637 IDWriteFontCollection_AddRef(*collection);
638 return S_OK;
641 static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout *iface)
643 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
644 TRACE("(%p)\n", This);
645 return This->format.family_len;
648 static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
650 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
652 TRACE("(%p)->(%p %u)\n", This, name, size);
654 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
655 strcpyW(name, This->format.family_name);
656 return S_OK;
659 static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout *iface)
661 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
662 TRACE("(%p)\n", This);
663 return This->format.weight;
666 static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout *iface)
668 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
669 TRACE("(%p)\n", This);
670 return This->format.style;
673 static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout *iface)
675 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
676 TRACE("(%p)\n", This);
677 return This->format.stretch;
680 static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout *iface)
682 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
683 TRACE("(%p)\n", This);
684 return This->format.size;
687 static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout *iface)
689 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
690 TRACE("(%p)\n", This);
691 return This->format.locale_len;
694 static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
696 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
698 TRACE("(%p)->(%p %u)\n", This, name, size);
700 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
701 strcpyW(name, This->format.locale);
702 return S_OK;
705 static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout *iface, FLOAT maxWidth)
707 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
708 TRACE("(%p)->(%.1f)\n", This, maxWidth);
709 This->maxwidth = maxWidth;
710 return S_OK;
713 static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout *iface, FLOAT maxHeight)
715 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
716 TRACE("(%p)->(%.1f)\n", This, maxHeight);
717 This->maxheight = maxHeight;
718 return S_OK;
721 static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
723 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
724 FIXME("(%p)->(%p %s): stub\n", This, collection, debugstr_range(&range));
725 return E_NOTIMPL;
728 static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
730 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
731 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_range(&range));
732 return E_NOTIMPL;
735 static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
737 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
738 struct layout_range_attr_value value;
740 TRACE("(%p)->(%d %s)\n", This, weight, debugstr_range(&range));
742 if (!validate_text_range(This, &range))
743 return S_OK;
745 value.range = range;
746 value.u.weight = weight;
747 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_WEIGHT, &value);
750 static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
752 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
753 struct layout_range_attr_value value;
755 TRACE("(%p)->(%d %s)\n", This, style, debugstr_range(&range));
757 if (!validate_text_range(This, &range))
758 return S_OK;
760 value.range = range;
761 value.u.style = style;
762 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STYLE, &value);
765 static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
767 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
768 FIXME("(%p)->(%d %s): stub\n", This, stretch, debugstr_range(&range));
769 return E_NOTIMPL;
772 static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout *iface, FLOAT size, DWRITE_TEXT_RANGE range)
774 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
775 FIXME("(%p)->(%f %s): stub\n", This, size, debugstr_range(&range));
776 return E_NOTIMPL;
779 static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout *iface, BOOL underline, DWRITE_TEXT_RANGE range)
781 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
782 struct layout_range_attr_value value;
784 TRACE("(%p)->(%d %s)\n", This, underline, debugstr_range(&range));
786 if (!validate_text_range(This, &range))
787 return S_OK;
789 value.range = range;
790 value.u.underline = underline;
791 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_UNDERLINE, &value);
794 static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
796 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
797 struct layout_range_attr_value value;
799 TRACE("(%p)->(%d %s)\n", This, strikethrough, debugstr_range(&range));
801 if (!validate_text_range(This, &range))
802 return S_OK;
804 value.range = range;
805 value.u.underline = strikethrough;
806 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRIKETHROUGH, &value);
809 static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
811 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
812 struct layout_range_attr_value value;
814 TRACE("(%p)->(%p %s)\n", This, effect, debugstr_range(&range));
816 if (!validate_text_range(This, &range))
817 return S_OK;
819 value.range = range;
820 value.u.effect = effect;
821 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_EFFECT, &value);
824 static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE r)
826 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
827 struct layout_range_attr_value attr;
829 TRACE("(%p)->(%p %s)\n", This, object, debugstr_range(&r));
831 if (!validate_text_range(This, &r))
832 return S_OK;
834 attr.range = r;
835 attr.u.object = object;
837 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_INLINE, &attr);
840 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
842 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
843 FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
844 return E_NOTIMPL;
847 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
849 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
850 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(locale), debugstr_range(&range));
851 return E_NOTIMPL;
854 static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout *iface)
856 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
857 TRACE("(%p)\n", This);
858 return This->maxwidth;
861 static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout *iface)
863 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
864 TRACE("(%p)\n", This);
865 return This->maxheight;
868 static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout *iface, UINT32 pos,
869 IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *range)
871 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
872 FIXME("(%p)->(%p %p): stub\n", This, collection, range);
873 return E_NOTIMPL;
876 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout *iface,
877 UINT32 pos, UINT32* len, DWRITE_TEXT_RANGE *range)
879 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
880 FIXME("(%p)->(%d %p %p): stub\n", This, pos, len, range);
881 return E_NOTIMPL;
884 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout *iface,
885 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
887 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
888 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
889 return E_NOTIMPL;
892 static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout *iface,
893 UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
895 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
896 struct layout_range *range;
898 TRACE("(%p)->(%u %p %p)\n", This, position, weight, r);
900 if (position >= This->len)
901 return S_OK;
903 range = get_layout_range_by_pos(This, position);
904 *weight = range->weight;
905 if (r) *r = range->range;
907 return S_OK;
910 static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout *iface,
911 UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
913 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
914 struct layout_range *range;
916 TRACE("(%p)->(%u %p %p)\n", This, position, style, r);
918 if (position >= This->len)
919 return S_OK;
921 range = get_layout_range_by_pos(This, position);
922 *style = range->style;
923 if (r) *r = range->range;
925 return S_OK;
928 static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout *iface,
929 UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *range)
931 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
932 FIXME("(%p)->(%u %p %p): stub\n", This, position, stretch, range);
933 return E_NOTIMPL;
936 static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout *iface,
937 UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *range)
939 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
940 FIXME("(%p)->(%u %p %p): stub\n", This, position, size, range);
941 return E_NOTIMPL;
944 static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout *iface,
945 UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
947 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
948 struct layout_range *range;
950 TRACE("(%p)->(%u %p %p)\n", This, position, underline, r);
952 if (position >= This->len)
953 return S_OK;
955 range = get_layout_range_by_pos(This, position);
956 *underline = range->underline;
957 if (r) *r = range->range;
959 return S_OK;
962 static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout *iface,
963 UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
965 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
966 struct layout_range *range;
968 TRACE("(%p)->(%u %p %p)\n", This, position, strikethrough, r);
970 if (position >= This->len)
971 return S_OK;
973 range = get_layout_range_by_pos(This, position);
974 *strikethrough = range->strikethrough;
975 if (r) *r = range->range;
977 return S_OK;
980 static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout *iface,
981 UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
983 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
984 struct layout_range *range;
986 TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
988 if (position >= This->len)
989 return S_OK;
991 range = get_layout_range_by_pos(This, position);
992 *effect = range->effect;
993 if (*effect)
994 IUnknown_AddRef(*effect);
995 if (r) *r = range->range;
997 return S_OK;
1000 static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout *iface,
1001 UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
1003 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1004 struct layout_range *range;
1006 TRACE("(%p)->(%u %p %p)\n", This, position, object, r);
1008 range = get_layout_range_by_pos(This, position);
1009 *object = range ? range->object : NULL;
1010 if (*object)
1011 IDWriteInlineObject_AddRef(*object);
1012 if (r) *r = range->range;
1014 return S_OK;
1017 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout *iface,
1018 UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
1020 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1021 FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
1022 return E_NOTIMPL;
1025 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout *iface,
1026 UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *range)
1028 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1029 FIXME("(%p)->(%u %p %p): stub\n", This, position, length, range);
1030 return E_NOTIMPL;
1033 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout *iface,
1034 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
1036 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1037 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
1038 return E_NOTIMPL;
1041 static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout *iface,
1042 void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
1044 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1045 FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
1046 return E_NOTIMPL;
1049 static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout *iface,
1050 DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
1052 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1053 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
1054 return E_NOTIMPL;
1057 static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout *iface, DWRITE_TEXT_METRICS *metrics)
1059 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1060 FIXME("(%p)->(%p): stub\n", This, metrics);
1061 return E_NOTIMPL;
1064 static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout *iface, DWRITE_OVERHANG_METRICS *overhangs)
1066 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1067 FIXME("(%p)->(%p): stub\n", This, overhangs);
1068 return E_NOTIMPL;
1071 static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout *iface,
1072 DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32* act_count)
1074 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1075 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, act_count);
1076 return E_NOTIMPL;
1079 static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout *iface, FLOAT* min_width)
1081 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1082 FIXME("(%p)->(%p): stub\n", This, min_width);
1083 return E_NOTIMPL;
1086 static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout *iface,
1087 FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
1089 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1090 FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
1091 return E_NOTIMPL;
1094 static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout *iface,
1095 UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
1097 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1098 FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
1099 return E_NOTIMPL;
1102 static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout *iface,
1103 UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
1104 DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
1106 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1107 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
1108 max_metricscount, actual_metricscount);
1109 return E_NOTIMPL;
1112 static const IDWriteTextLayoutVtbl dwritetextlayoutvtbl = {
1113 dwritetextlayout_QueryInterface,
1114 dwritetextlayout_AddRef,
1115 dwritetextlayout_Release,
1116 dwritetextlayout_SetTextAlignment,
1117 dwritetextlayout_SetParagraphAlignment,
1118 dwritetextlayout_SetWordWrapping,
1119 dwritetextlayout_SetReadingDirection,
1120 dwritetextlayout_SetFlowDirection,
1121 dwritetextlayout_SetIncrementalTabStop,
1122 dwritetextlayout_SetTrimming,
1123 dwritetextlayout_SetLineSpacing,
1124 dwritetextlayout_GetTextAlignment,
1125 dwritetextlayout_GetParagraphAlignment,
1126 dwritetextlayout_GetWordWrapping,
1127 dwritetextlayout_GetReadingDirection,
1128 dwritetextlayout_GetFlowDirection,
1129 dwritetextlayout_GetIncrementalTabStop,
1130 dwritetextlayout_GetTrimming,
1131 dwritetextlayout_GetLineSpacing,
1132 dwritetextlayout_GetFontCollection,
1133 dwritetextlayout_GetFontFamilyNameLength,
1134 dwritetextlayout_GetFontFamilyName,
1135 dwritetextlayout_GetFontWeight,
1136 dwritetextlayout_GetFontStyle,
1137 dwritetextlayout_GetFontStretch,
1138 dwritetextlayout_GetFontSize,
1139 dwritetextlayout_GetLocaleNameLength,
1140 dwritetextlayout_GetLocaleName,
1141 dwritetextlayout_SetMaxWidth,
1142 dwritetextlayout_SetMaxHeight,
1143 dwritetextlayout_SetFontCollection,
1144 dwritetextlayout_SetFontFamilyName,
1145 dwritetextlayout_SetFontWeight,
1146 dwritetextlayout_SetFontStyle,
1147 dwritetextlayout_SetFontStretch,
1148 dwritetextlayout_SetFontSize,
1149 dwritetextlayout_SetUnderline,
1150 dwritetextlayout_SetStrikethrough,
1151 dwritetextlayout_SetDrawingEffect,
1152 dwritetextlayout_SetInlineObject,
1153 dwritetextlayout_SetTypography,
1154 dwritetextlayout_SetLocaleName,
1155 dwritetextlayout_GetMaxWidth,
1156 dwritetextlayout_GetMaxHeight,
1157 dwritetextlayout_layout_GetFontCollection,
1158 dwritetextlayout_layout_GetFontFamilyNameLength,
1159 dwritetextlayout_layout_GetFontFamilyName,
1160 dwritetextlayout_layout_GetFontWeight,
1161 dwritetextlayout_layout_GetFontStyle,
1162 dwritetextlayout_layout_GetFontStretch,
1163 dwritetextlayout_layout_GetFontSize,
1164 dwritetextlayout_GetUnderline,
1165 dwritetextlayout_GetStrikethrough,
1166 dwritetextlayout_GetDrawingEffect,
1167 dwritetextlayout_GetInlineObject,
1168 dwritetextlayout_GetTypography,
1169 dwritetextlayout_layout_GetLocaleNameLength,
1170 dwritetextlayout_layout_GetLocaleName,
1171 dwritetextlayout_Draw,
1172 dwritetextlayout_GetLineMetrics,
1173 dwritetextlayout_GetMetrics,
1174 dwritetextlayout_GetOverhangMetrics,
1175 dwritetextlayout_GetClusterMetrics,
1176 dwritetextlayout_DetermineMinWidth,
1177 dwritetextlayout_HitTestPoint,
1178 dwritetextlayout_HitTestTextPosition,
1179 dwritetextlayout_HitTestTextRange
1182 static void layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
1184 struct dwrite_textformat *f;
1186 memset(&layout->format, 0, sizeof(layout->format));
1188 if ((f = unsafe_impl_from_IDWriteTextFormat(format)))
1190 layout->format = f->format;
1191 layout->format.locale = heap_strdupW(f->format.locale);
1192 layout->format.family_name = heap_strdupW(f->format.family_name);
1193 if (layout->format.trimmingsign)
1194 IDWriteInlineObject_AddRef(layout->format.trimmingsign);
1196 else
1198 UINT32 locale_len, family_len;
1200 layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
1201 layout->format.style = IDWriteTextFormat_GetFontStyle(format);
1202 layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
1203 layout->format.size = IDWriteTextFormat_GetFontSize(format);
1204 layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
1205 layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
1206 layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
1207 layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
1208 layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
1209 IDWriteTextFormat_GetLineSpacing(format,
1210 &layout->format.spacingmethod,
1211 &layout->format.spacing,
1212 &layout->format.baseline
1214 IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
1216 /* locale name and length */
1217 locale_len = IDWriteTextFormat_GetLocaleNameLength(format);
1218 layout->format.locale = heap_alloc((locale_len+1)*sizeof(WCHAR));
1219 IDWriteTextFormat_GetLocaleName(format, layout->format.locale, locale_len+1);
1220 layout->format.locale_len = locale_len;
1222 /* font family name and length */
1223 family_len = IDWriteTextFormat_GetFontFamilyNameLength(format);
1224 layout->format.family_name = heap_alloc((family_len+1)*sizeof(WCHAR));
1225 IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, family_len+1);
1226 layout->format.family_len = family_len;
1229 IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
1232 HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, IDWriteTextLayout **layout)
1234 struct dwrite_textlayout *This;
1235 struct layout_range *range;
1236 DWRITE_TEXT_RANGE r = { 0, len };
1238 *layout = NULL;
1240 This = heap_alloc(sizeof(struct dwrite_textlayout));
1241 if (!This) return E_OUTOFMEMORY;
1243 This->IDWriteTextLayout_iface.lpVtbl = &dwritetextlayoutvtbl;
1244 This->ref = 1;
1245 This->str = heap_strdupnW(str, len);
1246 This->len = len;
1247 This->maxwidth = maxwidth;
1248 This->maxheight = maxheight;
1249 layout_format_from_textformat(This, format);
1251 list_init(&This->ranges);
1252 range = alloc_layout_range(This, &r);
1253 if (!range) {
1254 IDWriteTextLayout_Release(&This->IDWriteTextLayout_iface);
1255 return E_OUTOFMEMORY;
1257 list_add_head(&This->ranges, &range->entry);
1259 *layout = &This->IDWriteTextLayout_iface;
1261 return S_OK;
1264 static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
1266 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1268 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1270 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
1271 *obj = iface;
1272 IDWriteInlineObject_AddRef(iface);
1273 return S_OK;
1276 *obj = NULL;
1277 return E_NOINTERFACE;
1281 static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
1283 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1284 ULONG ref = InterlockedIncrement(&This->ref);
1285 TRACE("(%p)->(%d)\n", This, ref);
1286 return ref;
1289 static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
1291 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1292 ULONG ref = InterlockedDecrement(&This->ref);
1294 TRACE("(%p)->(%d)\n", This, ref);
1296 if (!ref)
1297 heap_free(This);
1299 return ref;
1302 static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
1303 FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
1305 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1306 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This, context, renderer, originX, originY, is_sideways, is_rtl, drawing_effect);
1307 return E_NOTIMPL;
1310 static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
1312 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1313 FIXME("(%p)->(%p): stub\n", This, metrics);
1314 return E_NOTIMPL;
1317 static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
1319 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1320 FIXME("(%p)->(%p): stub\n", This, overhangs);
1321 return E_NOTIMPL;
1324 static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
1325 DWRITE_BREAK_CONDITION *after)
1327 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1329 TRACE("(%p)->(%p %p)\n", This, before, after);
1331 *before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
1332 return S_OK;
1335 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
1336 dwritetrimmingsign_QueryInterface,
1337 dwritetrimmingsign_AddRef,
1338 dwritetrimmingsign_Release,
1339 dwritetrimmingsign_Draw,
1340 dwritetrimmingsign_GetMetrics,
1341 dwritetrimmingsign_GetOverhangMetrics,
1342 dwritetrimmingsign_GetBreakConditions
1345 HRESULT create_trimmingsign(IDWriteInlineObject **sign)
1347 struct dwrite_trimmingsign *This;
1349 *sign = NULL;
1351 This = heap_alloc(sizeof(struct dwrite_trimmingsign));
1352 if (!This) return E_OUTOFMEMORY;
1354 This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
1355 This->ref = 1;
1357 *sign = &This->IDWriteInlineObject_iface;
1359 return S_OK;
1362 static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat *iface, REFIID riid, void **obj)
1364 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1366 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1368 if (IsEqualIID(riid, &IID_IUnknown) ||
1369 IsEqualIID(riid, &IID_IDWriteTextFormat))
1371 *obj = iface;
1372 IDWriteTextFormat_AddRef(iface);
1373 return S_OK;
1376 *obj = NULL;
1378 return E_NOINTERFACE;
1381 static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat *iface)
1383 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1384 ULONG ref = InterlockedIncrement(&This->ref);
1385 TRACE("(%p)->(%d)\n", This, ref);
1386 return ref;
1389 static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat *iface)
1391 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1392 ULONG ref = InterlockedDecrement(&This->ref);
1394 TRACE("(%p)->(%d)\n", This, ref);
1396 if (!ref)
1398 release_format_data(&This->format);
1399 heap_free(This);
1402 return ref;
1405 static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat *iface, DWRITE_TEXT_ALIGNMENT alignment)
1407 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1408 TRACE("(%p)->(%d)\n", This, alignment);
1409 This->format.textalignment = alignment;
1410 return S_OK;
1413 static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
1415 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1416 TRACE("(%p)->(%d)\n", This, alignment);
1417 This->format.paralign = alignment;
1418 return S_OK;
1421 static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat *iface, DWRITE_WORD_WRAPPING wrapping)
1423 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1424 TRACE("(%p)->(%d)\n", This, wrapping);
1425 This->format.wrapping = wrapping;
1426 return S_OK;
1429 static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat *iface, DWRITE_READING_DIRECTION direction)
1431 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1432 TRACE("(%p)->(%d)\n", This, direction);
1433 This->format.readingdir = direction;
1434 return S_OK;
1437 static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat *iface, DWRITE_FLOW_DIRECTION direction)
1439 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1440 TRACE("(%p)->(%d)\n", This, direction);
1441 This->format.flow = direction;
1442 return S_OK;
1445 static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat *iface, FLOAT tabstop)
1447 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1448 FIXME("(%p)->(%f): stub\n", This, tabstop);
1449 return E_NOTIMPL;
1452 static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING const *trimming,
1453 IDWriteInlineObject *trimming_sign)
1455 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1456 TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign);
1458 This->format.trimming = *trimming;
1459 if (This->format.trimmingsign)
1460 IDWriteInlineObject_Release(This->format.trimmingsign);
1461 This->format.trimmingsign = trimming_sign;
1462 if (This->format.trimmingsign)
1463 IDWriteInlineObject_AddRef(This->format.trimmingsign);
1464 return S_OK;
1467 static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD method,
1468 FLOAT spacing, FLOAT baseline)
1470 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1471 TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
1472 This->format.spacingmethod = method;
1473 This->format.spacing = spacing;
1474 This->format.baseline = baseline;
1475 return S_OK;
1478 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat *iface)
1480 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1481 TRACE("(%p)\n", This);
1482 return This->format.textalignment;
1485 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat *iface)
1487 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1488 TRACE("(%p)\n", This);
1489 return This->format.paralign;
1492 static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat *iface)
1494 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1495 TRACE("(%p)\n", This);
1496 return This->format.wrapping;
1499 static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat *iface)
1501 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1502 TRACE("(%p)\n", This);
1503 return This->format.readingdir;
1506 static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat *iface)
1508 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1509 TRACE("(%p)\n", This);
1510 return This->format.flow;
1513 static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat *iface)
1515 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1516 FIXME("(%p): stub\n", This);
1517 return 0.0;
1520 static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING *options,
1521 IDWriteInlineObject **trimming_sign)
1523 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1524 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
1526 *options = This->format.trimming;
1527 if ((*trimming_sign = This->format.trimmingsign))
1528 IDWriteInlineObject_AddRef(*trimming_sign);
1530 return S_OK;
1533 static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD *method,
1534 FLOAT *spacing, FLOAT *baseline)
1536 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1537 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
1539 *method = This->format.spacingmethod;
1540 *spacing = This->format.spacing;
1541 *baseline = This->format.baseline;
1542 return S_OK;
1545 static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat *iface, IDWriteFontCollection **collection)
1547 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1549 TRACE("(%p)->(%p)\n", This, collection);
1551 *collection = This->format.collection;
1552 IDWriteFontCollection_AddRef(*collection);
1554 return S_OK;
1557 static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat *iface)
1559 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1560 TRACE("(%p)\n", This);
1561 return This->format.family_len;
1564 static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1566 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1568 TRACE("(%p)->(%p %u)\n", This, name, size);
1570 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
1571 strcpyW(name, This->format.family_name);
1572 return S_OK;
1575 static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat *iface)
1577 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1578 TRACE("(%p)\n", This);
1579 return This->format.weight;
1582 static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat *iface)
1584 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1585 TRACE("(%p)\n", This);
1586 return This->format.style;
1589 static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat *iface)
1591 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1592 TRACE("(%p)\n", This);
1593 return This->format.stretch;
1596 static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat *iface)
1598 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1599 TRACE("(%p)\n", This);
1600 return This->format.size;
1603 static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat *iface)
1605 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1606 TRACE("(%p)\n", This);
1607 return This->format.locale_len;
1610 static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1612 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1614 TRACE("(%p)->(%p %u)\n", This, name, size);
1616 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
1617 strcpyW(name, This->format.locale);
1618 return S_OK;
1621 static const IDWriteTextFormatVtbl dwritetextformatvtbl = {
1622 dwritetextformat_QueryInterface,
1623 dwritetextformat_AddRef,
1624 dwritetextformat_Release,
1625 dwritetextformat_SetTextAlignment,
1626 dwritetextformat_SetParagraphAlignment,
1627 dwritetextformat_SetWordWrapping,
1628 dwritetextformat_SetReadingDirection,
1629 dwritetextformat_SetFlowDirection,
1630 dwritetextformat_SetIncrementalTabStop,
1631 dwritetextformat_SetTrimming,
1632 dwritetextformat_SetLineSpacing,
1633 dwritetextformat_GetTextAlignment,
1634 dwritetextformat_GetParagraphAlignment,
1635 dwritetextformat_GetWordWrapping,
1636 dwritetextformat_GetReadingDirection,
1637 dwritetextformat_GetFlowDirection,
1638 dwritetextformat_GetIncrementalTabStop,
1639 dwritetextformat_GetTrimming,
1640 dwritetextformat_GetLineSpacing,
1641 dwritetextformat_GetFontCollection,
1642 dwritetextformat_GetFontFamilyNameLength,
1643 dwritetextformat_GetFontFamilyName,
1644 dwritetextformat_GetFontWeight,
1645 dwritetextformat_GetFontStyle,
1646 dwritetextformat_GetFontStretch,
1647 dwritetextformat_GetFontSize,
1648 dwritetextformat_GetLocaleNameLength,
1649 dwritetextformat_GetLocaleName
1652 HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
1653 DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
1655 struct dwrite_textformat *This;
1657 *format = NULL;
1659 This = heap_alloc(sizeof(struct dwrite_textformat));
1660 if (!This) return E_OUTOFMEMORY;
1662 This->IDWriteTextFormat_iface.lpVtbl = &dwritetextformatvtbl;
1663 This->ref = 1;
1664 This->format.family_name = heap_strdupW(family_name);
1665 This->format.family_len = strlenW(family_name);
1666 This->format.locale = heap_strdupW(locale);
1667 This->format.locale_len = strlenW(locale);
1668 This->format.weight = weight;
1669 This->format.style = style;
1670 This->format.size = size;
1671 This->format.stretch = stretch;
1672 This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
1673 This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
1674 This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
1675 This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
1676 This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
1677 This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
1678 This->format.spacing = 0.0;
1679 This->format.baseline = 0.0;
1680 This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
1681 This->format.trimming.delimiter = 0;
1682 This->format.trimming.delimiterCount = 0;
1683 This->format.trimmingsign = NULL;
1685 if (collection)
1687 This->format.collection = collection;
1688 IDWriteFontCollection_AddRef(collection);
1690 else
1692 HRESULT hr = get_system_fontcollection(&This->format.collection);
1693 if (hr != S_OK)
1695 IDWriteTextFormat_Release(&This->IDWriteTextFormat_iface);
1696 return hr;
1700 *format = &This->IDWriteTextFormat_iface;
1702 return S_OK;