dwrite: Implement ranges merging.
[wine.git] / dlls / dwrite / layout.c
blobaed6652620e710c11dc94fec1fdf3a9dfd3f9f66
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 list *ranges)
244 struct layout_range *cur, *cur2;
245 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, ranges, struct layout_range, entry) {
246 list_remove(&cur->entry);
247 free_layout_range(cur);
251 static struct layout_range *find_outer_range(struct list *ranges, const DWRITE_TEXT_RANGE *range)
253 struct layout_range *cur;
255 LIST_FOR_EACH_ENTRY(cur, 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 list *ranges, UINT32 pos)
272 struct layout_range *cur;
274 LIST_FOR_EACH_ENTRY(cur, 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(ranges, &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(ranges, 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->ranges);
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 FIXME("(%p): stub\n", This);
564 return DWRITE_TEXT_ALIGNMENT_LEADING;
567 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout *iface)
569 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
570 FIXME("(%p): stub\n", This);
571 return DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
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 DWRITE_WORD_WRAPPING_NO_WRAP;
581 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout *iface)
583 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
584 FIXME("(%p): stub\n", This);
585 return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
588 static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout *iface)
590 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
591 FIXME("(%p): stub\n", This);
592 return DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
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);
606 FIXME("(%p)->(%p %p): stub\n", This, options, trimming_sign);
607 return E_NOTIMPL;
610 static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD *method,
611 FLOAT *spacing, FLOAT *baseline)
613 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
614 FIXME("(%p)->(%p %p %p): stub\n", This, method, spacing, baseline);
615 return E_NOTIMPL;
618 static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection **collection)
620 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
621 FIXME("(%p)->(%p): stub\n", This, collection);
622 return E_NOTIMPL;
625 static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout *iface)
627 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
628 FIXME("(%p): stub\n", This);
629 return 0;
632 static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
634 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
635 FIXME("(%p)->(%p %u): stub\n", This, name, size);
636 return E_NOTIMPL;
639 static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout *iface)
641 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
642 FIXME("(%p): stub\n", This);
643 return DWRITE_FONT_WEIGHT_NORMAL;
646 static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout *iface)
648 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
649 FIXME("(%p): stub\n", This);
650 return DWRITE_FONT_STYLE_NORMAL;
653 static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout *iface)
655 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
656 FIXME("(%p): stub\n", This);
657 return DWRITE_FONT_STRETCH_NORMAL;
660 static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout *iface)
662 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
663 FIXME("(%p): stub\n", This);
664 return 0.0;
667 static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout *iface)
669 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
670 TRACE("(%p)\n", This);
671 return This->format.locale_len;
674 static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
676 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
678 TRACE("(%p)->(%p %u)\n", This, name, size);
680 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
681 strcpyW(name, This->format.locale);
682 return S_OK;
685 static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout *iface, FLOAT maxWidth)
687 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
688 TRACE("(%p)->(%.1f)\n", This, maxWidth);
689 This->maxwidth = maxWidth;
690 return S_OK;
693 static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout *iface, FLOAT maxHeight)
695 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
696 TRACE("(%p)->(%.1f)\n", This, maxHeight);
697 This->maxheight = maxHeight;
698 return S_OK;
701 static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
703 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
704 FIXME("(%p)->(%p %s): stub\n", This, collection, debugstr_range(&range));
705 return E_NOTIMPL;
708 static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
710 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
711 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_range(&range));
712 return E_NOTIMPL;
715 static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
717 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
718 struct layout_range_attr_value value;
720 TRACE("(%p)->(%d %s)\n", This, weight, debugstr_range(&range));
722 if (!validate_text_range(This, &range))
723 return S_OK;
725 value.range = range;
726 value.u.weight = weight;
727 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_WEIGHT, &value);
730 static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
732 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
733 struct layout_range_attr_value value;
735 TRACE("(%p)->(%d %s)\n", This, style, debugstr_range(&range));
737 if (!validate_text_range(This, &range))
738 return S_OK;
740 value.range = range;
741 value.u.style = style;
742 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STYLE, &value);
745 static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
747 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
748 FIXME("(%p)->(%d %s): stub\n", This, stretch, debugstr_range(&range));
749 return E_NOTIMPL;
752 static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout *iface, FLOAT size, DWRITE_TEXT_RANGE range)
754 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
755 FIXME("(%p)->(%f %s): stub\n", This, size, debugstr_range(&range));
756 return E_NOTIMPL;
759 static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout *iface, BOOL underline, DWRITE_TEXT_RANGE range)
761 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
762 struct layout_range_attr_value value;
764 TRACE("(%p)->(%d %s)\n", This, underline, debugstr_range(&range));
766 if (!validate_text_range(This, &range))
767 return S_OK;
769 value.range = range;
770 value.u.underline = underline;
771 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_UNDERLINE, &value);
774 static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
776 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
777 struct layout_range_attr_value value;
779 TRACE("(%p)->(%d %s)\n", This, strikethrough, debugstr_range(&range));
781 if (!validate_text_range(This, &range))
782 return S_OK;
784 value.range = range;
785 value.u.underline = strikethrough;
786 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRIKETHROUGH, &value);
789 static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
791 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
792 struct layout_range_attr_value value;
794 TRACE("(%p)->(%p %s)\n", This, effect, debugstr_range(&range));
796 if (!validate_text_range(This, &range))
797 return S_OK;
799 value.range = range;
800 value.u.effect = effect;
801 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_EFFECT, &value);
804 static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE r)
806 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
807 struct layout_range_attr_value attr;
809 TRACE("(%p)->(%p %s)\n", This, object, debugstr_range(&r));
811 if (!validate_text_range(This, &r))
812 return S_OK;
814 attr.range = r;
815 attr.u.object = object;
817 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_INLINE, &attr);
820 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
822 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
823 FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
824 return E_NOTIMPL;
827 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
829 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
830 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(locale), debugstr_range(&range));
831 return E_NOTIMPL;
834 static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout *iface)
836 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
837 TRACE("(%p)\n", This);
838 return This->maxwidth;
841 static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout *iface)
843 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
844 TRACE("(%p)\n", This);
845 return This->maxheight;
848 static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout *iface, UINT32 pos,
849 IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *range)
851 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
852 FIXME("(%p)->(%p %p): stub\n", This, collection, range);
853 return E_NOTIMPL;
856 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout *iface,
857 UINT32 pos, UINT32* len, DWRITE_TEXT_RANGE *range)
859 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
860 FIXME("(%p)->(%d %p %p): stub\n", This, pos, len, range);
861 return E_NOTIMPL;
864 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout *iface,
865 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
867 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
868 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
869 return E_NOTIMPL;
872 static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout *iface,
873 UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
875 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
876 struct layout_range *range;
878 TRACE("(%p)->(%u %p %p)\n", This, position, weight, r);
880 if (position >= This->len)
881 return S_OK;
883 range = get_layout_range_by_pos(&This->ranges, position);
884 *weight = range->weight;
885 if (r) *r = range->range;
887 return S_OK;
890 static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout *iface,
891 UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
893 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
894 struct layout_range *range;
896 TRACE("(%p)->(%u %p %p)\n", This, position, style, r);
898 if (position >= This->len)
899 return S_OK;
901 range = get_layout_range_by_pos(&This->ranges, position);
902 *style = range->style;
903 if (r) *r = range->range;
905 return S_OK;
908 static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout *iface,
909 UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *range)
911 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
912 FIXME("(%p)->(%u %p %p): stub\n", This, position, stretch, range);
913 return E_NOTIMPL;
916 static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout *iface,
917 UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *range)
919 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
920 FIXME("(%p)->(%u %p %p): stub\n", This, position, size, range);
921 return E_NOTIMPL;
924 static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout *iface,
925 UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
927 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
928 struct layout_range *range;
930 TRACE("(%p)->(%u %p %p)\n", This, position, underline, r);
932 if (position >= This->len)
933 return S_OK;
935 range = get_layout_range_by_pos(&This->ranges, position);
936 *underline = range->underline;
937 if (r) *r = range->range;
939 return S_OK;
942 static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout *iface,
943 UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
945 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
946 struct layout_range *range;
948 TRACE("(%p)->(%u %p %p)\n", This, position, strikethrough, r);
950 if (position >= This->len)
951 return S_OK;
953 range = get_layout_range_by_pos(&This->ranges, position);
954 *strikethrough = range->strikethrough;
955 if (r) *r = range->range;
957 return S_OK;
960 static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout *iface,
961 UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
963 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
964 struct layout_range *range;
966 TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
968 if (position >= This->len)
969 return S_OK;
971 range = get_layout_range_by_pos(&This->ranges, position);
972 *effect = range->effect;
973 if (*effect)
974 IUnknown_AddRef(*effect);
975 if (r) *r = range->range;
977 return S_OK;
980 static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout *iface,
981 UINT32 position, IDWriteInlineObject **object, 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, object, r);
988 range = get_layout_range_by_pos(&This->ranges, position);
989 *object = range ? range->object : NULL;
990 if (*object)
991 IDWriteInlineObject_AddRef(*object);
992 if (r) *r = range->range;
994 return S_OK;
997 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout *iface,
998 UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
1000 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1001 FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
1002 return E_NOTIMPL;
1005 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout *iface,
1006 UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *range)
1008 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1009 FIXME("(%p)->(%u %p %p): stub\n", This, position, length, range);
1010 return E_NOTIMPL;
1013 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout *iface,
1014 UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
1016 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1017 FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
1018 return E_NOTIMPL;
1021 static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout *iface,
1022 void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
1024 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1025 FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
1026 return E_NOTIMPL;
1029 static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout *iface,
1030 DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
1032 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1033 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
1034 return E_NOTIMPL;
1037 static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout *iface, DWRITE_TEXT_METRICS *metrics)
1039 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1040 FIXME("(%p)->(%p): stub\n", This, metrics);
1041 return E_NOTIMPL;
1044 static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout *iface, DWRITE_OVERHANG_METRICS *overhangs)
1046 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1047 FIXME("(%p)->(%p): stub\n", This, overhangs);
1048 return E_NOTIMPL;
1051 static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout *iface,
1052 DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32* act_count)
1054 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1055 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, act_count);
1056 return E_NOTIMPL;
1059 static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout *iface, FLOAT* min_width)
1061 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1062 FIXME("(%p)->(%p): stub\n", This, min_width);
1063 return E_NOTIMPL;
1066 static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout *iface,
1067 FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
1069 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1070 FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
1071 return E_NOTIMPL;
1074 static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout *iface,
1075 UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
1077 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1078 FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
1079 return E_NOTIMPL;
1082 static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout *iface,
1083 UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
1084 DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
1086 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
1087 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
1088 max_metricscount, actual_metricscount);
1089 return E_NOTIMPL;
1092 static const IDWriteTextLayoutVtbl dwritetextlayoutvtbl = {
1093 dwritetextlayout_QueryInterface,
1094 dwritetextlayout_AddRef,
1095 dwritetextlayout_Release,
1096 dwritetextlayout_SetTextAlignment,
1097 dwritetextlayout_SetParagraphAlignment,
1098 dwritetextlayout_SetWordWrapping,
1099 dwritetextlayout_SetReadingDirection,
1100 dwritetextlayout_SetFlowDirection,
1101 dwritetextlayout_SetIncrementalTabStop,
1102 dwritetextlayout_SetTrimming,
1103 dwritetextlayout_SetLineSpacing,
1104 dwritetextlayout_GetTextAlignment,
1105 dwritetextlayout_GetParagraphAlignment,
1106 dwritetextlayout_GetWordWrapping,
1107 dwritetextlayout_GetReadingDirection,
1108 dwritetextlayout_GetFlowDirection,
1109 dwritetextlayout_GetIncrementalTabStop,
1110 dwritetextlayout_GetTrimming,
1111 dwritetextlayout_GetLineSpacing,
1112 dwritetextlayout_GetFontCollection,
1113 dwritetextlayout_GetFontFamilyNameLength,
1114 dwritetextlayout_GetFontFamilyName,
1115 dwritetextlayout_GetFontWeight,
1116 dwritetextlayout_GetFontStyle,
1117 dwritetextlayout_GetFontStretch,
1118 dwritetextlayout_GetFontSize,
1119 dwritetextlayout_GetLocaleNameLength,
1120 dwritetextlayout_GetLocaleName,
1121 dwritetextlayout_SetMaxWidth,
1122 dwritetextlayout_SetMaxHeight,
1123 dwritetextlayout_SetFontCollection,
1124 dwritetextlayout_SetFontFamilyName,
1125 dwritetextlayout_SetFontWeight,
1126 dwritetextlayout_SetFontStyle,
1127 dwritetextlayout_SetFontStretch,
1128 dwritetextlayout_SetFontSize,
1129 dwritetextlayout_SetUnderline,
1130 dwritetextlayout_SetStrikethrough,
1131 dwritetextlayout_SetDrawingEffect,
1132 dwritetextlayout_SetInlineObject,
1133 dwritetextlayout_SetTypography,
1134 dwritetextlayout_SetLocaleName,
1135 dwritetextlayout_GetMaxWidth,
1136 dwritetextlayout_GetMaxHeight,
1137 dwritetextlayout_layout_GetFontCollection,
1138 dwritetextlayout_layout_GetFontFamilyNameLength,
1139 dwritetextlayout_layout_GetFontFamilyName,
1140 dwritetextlayout_layout_GetFontWeight,
1141 dwritetextlayout_layout_GetFontStyle,
1142 dwritetextlayout_layout_GetFontStretch,
1143 dwritetextlayout_layout_GetFontSize,
1144 dwritetextlayout_GetUnderline,
1145 dwritetextlayout_GetStrikethrough,
1146 dwritetextlayout_GetDrawingEffect,
1147 dwritetextlayout_GetInlineObject,
1148 dwritetextlayout_GetTypography,
1149 dwritetextlayout_layout_GetLocaleNameLength,
1150 dwritetextlayout_layout_GetLocaleName,
1151 dwritetextlayout_Draw,
1152 dwritetextlayout_GetLineMetrics,
1153 dwritetextlayout_GetMetrics,
1154 dwritetextlayout_GetOverhangMetrics,
1155 dwritetextlayout_GetClusterMetrics,
1156 dwritetextlayout_DetermineMinWidth,
1157 dwritetextlayout_HitTestPoint,
1158 dwritetextlayout_HitTestTextPosition,
1159 dwritetextlayout_HitTestTextRange
1162 static void layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
1164 struct dwrite_textformat *f;
1166 memset(&layout->format, 0, sizeof(layout->format));
1168 if ((f = unsafe_impl_from_IDWriteTextFormat(format)))
1170 layout->format = f->format;
1171 layout->format.locale = heap_strdupW(f->format.locale);
1172 layout->format.family_name = heap_strdupW(f->format.family_name);
1173 if (layout->format.trimmingsign)
1174 IDWriteInlineObject_AddRef(layout->format.trimmingsign);
1176 else
1178 UINT32 locale_len, family_len;
1180 layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
1181 layout->format.style = IDWriteTextFormat_GetFontStyle(format);
1182 layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
1183 layout->format.size = IDWriteTextFormat_GetFontSize(format);
1184 layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
1185 layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
1186 layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
1187 layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
1188 layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
1189 IDWriteTextFormat_GetLineSpacing(format,
1190 &layout->format.spacingmethod,
1191 &layout->format.spacing,
1192 &layout->format.baseline
1194 IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
1196 /* locale name and length */
1197 locale_len = IDWriteTextFormat_GetLocaleNameLength(format);
1198 layout->format.locale = heap_alloc((locale_len+1)*sizeof(WCHAR));
1199 IDWriteTextFormat_GetLocaleName(format, layout->format.locale, locale_len+1);
1200 layout->format.locale_len = locale_len;
1202 /* font family name and length */
1203 family_len = IDWriteTextFormat_GetFontFamilyNameLength(format);
1204 layout->format.family_name = heap_alloc((family_len+1)*sizeof(WCHAR));
1205 IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, family_len+1);
1206 layout->format.family_len = family_len;
1209 IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
1212 HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, IDWriteTextLayout **layout)
1214 struct dwrite_textlayout *This;
1215 struct layout_range *range;
1216 DWRITE_TEXT_RANGE r = { 0, len };
1218 *layout = NULL;
1220 This = heap_alloc(sizeof(struct dwrite_textlayout));
1221 if (!This) return E_OUTOFMEMORY;
1223 This->IDWriteTextLayout_iface.lpVtbl = &dwritetextlayoutvtbl;
1224 This->ref = 1;
1225 This->str = heap_strdupnW(str, len);
1226 This->len = len;
1227 This->maxwidth = maxwidth;
1228 This->maxheight = maxheight;
1229 layout_format_from_textformat(This, format);
1231 list_init(&This->ranges);
1232 range = alloc_layout_range(This, &r);
1233 if (!range) {
1234 IDWriteTextLayout_Release(&This->IDWriteTextLayout_iface);
1235 return E_OUTOFMEMORY;
1237 list_add_head(&This->ranges, &range->entry);
1239 *layout = &This->IDWriteTextLayout_iface;
1241 return S_OK;
1244 static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
1246 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1248 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1250 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
1251 *obj = iface;
1252 IDWriteInlineObject_AddRef(iface);
1253 return S_OK;
1256 *obj = NULL;
1257 return E_NOINTERFACE;
1261 static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
1263 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1264 ULONG ref = InterlockedIncrement(&This->ref);
1265 TRACE("(%p)->(%d)\n", This, ref);
1266 return ref;
1269 static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
1271 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1272 ULONG ref = InterlockedDecrement(&This->ref);
1274 TRACE("(%p)->(%d)\n", This, ref);
1276 if (!ref)
1277 heap_free(This);
1279 return ref;
1282 static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
1283 FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
1285 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1286 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This, context, renderer, originX, originY, is_sideways, is_rtl, drawing_effect);
1287 return E_NOTIMPL;
1290 static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
1292 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1293 FIXME("(%p)->(%p): stub\n", This, metrics);
1294 return E_NOTIMPL;
1297 static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
1299 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1300 FIXME("(%p)->(%p): stub\n", This, overhangs);
1301 return E_NOTIMPL;
1304 static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
1305 DWRITE_BREAK_CONDITION *after)
1307 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
1309 TRACE("(%p)->(%p %p)\n", This, before, after);
1311 *before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
1312 return S_OK;
1315 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
1316 dwritetrimmingsign_QueryInterface,
1317 dwritetrimmingsign_AddRef,
1318 dwritetrimmingsign_Release,
1319 dwritetrimmingsign_Draw,
1320 dwritetrimmingsign_GetMetrics,
1321 dwritetrimmingsign_GetOverhangMetrics,
1322 dwritetrimmingsign_GetBreakConditions
1325 HRESULT create_trimmingsign(IDWriteInlineObject **sign)
1327 struct dwrite_trimmingsign *This;
1329 *sign = NULL;
1331 This = heap_alloc(sizeof(struct dwrite_trimmingsign));
1332 if (!This) return E_OUTOFMEMORY;
1334 This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
1335 This->ref = 1;
1337 *sign = &This->IDWriteInlineObject_iface;
1339 return S_OK;
1342 static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat *iface, REFIID riid, void **obj)
1344 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1346 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1348 if (IsEqualIID(riid, &IID_IUnknown) ||
1349 IsEqualIID(riid, &IID_IDWriteTextFormat))
1351 *obj = iface;
1352 IDWriteTextFormat_AddRef(iface);
1353 return S_OK;
1356 *obj = NULL;
1358 return E_NOINTERFACE;
1361 static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat *iface)
1363 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1364 ULONG ref = InterlockedIncrement(&This->ref);
1365 TRACE("(%p)->(%d)\n", This, ref);
1366 return ref;
1369 static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat *iface)
1371 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1372 ULONG ref = InterlockedDecrement(&This->ref);
1374 TRACE("(%p)->(%d)\n", This, ref);
1376 if (!ref)
1378 release_format_data(&This->format);
1379 heap_free(This);
1382 return ref;
1385 static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat *iface, DWRITE_TEXT_ALIGNMENT alignment)
1387 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1388 TRACE("(%p)->(%d)\n", This, alignment);
1389 This->format.textalignment = alignment;
1390 return S_OK;
1393 static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
1395 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1396 TRACE("(%p)->(%d)\n", This, alignment);
1397 This->format.paralign = alignment;
1398 return S_OK;
1401 static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat *iface, DWRITE_WORD_WRAPPING wrapping)
1403 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1404 TRACE("(%p)->(%d)\n", This, wrapping);
1405 This->format.wrapping = wrapping;
1406 return S_OK;
1409 static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat *iface, DWRITE_READING_DIRECTION direction)
1411 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1412 TRACE("(%p)->(%d)\n", This, direction);
1413 This->format.readingdir = direction;
1414 return S_OK;
1417 static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat *iface, DWRITE_FLOW_DIRECTION direction)
1419 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1420 TRACE("(%p)->(%d)\n", This, direction);
1421 This->format.flow = direction;
1422 return S_OK;
1425 static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat *iface, FLOAT tabstop)
1427 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1428 FIXME("(%p)->(%f): stub\n", This, tabstop);
1429 return E_NOTIMPL;
1432 static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING const *trimming,
1433 IDWriteInlineObject *trimming_sign)
1435 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1436 TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign);
1438 This->format.trimming = *trimming;
1439 if (This->format.trimmingsign)
1440 IDWriteInlineObject_Release(This->format.trimmingsign);
1441 This->format.trimmingsign = trimming_sign;
1442 if (This->format.trimmingsign)
1443 IDWriteInlineObject_AddRef(This->format.trimmingsign);
1444 return S_OK;
1447 static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD method,
1448 FLOAT spacing, FLOAT baseline)
1450 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1451 TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
1452 This->format.spacingmethod = method;
1453 This->format.spacing = spacing;
1454 This->format.baseline = baseline;
1455 return S_OK;
1458 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat *iface)
1460 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1461 TRACE("(%p)\n", This);
1462 return This->format.textalignment;
1465 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat *iface)
1467 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1468 TRACE("(%p)\n", This);
1469 return This->format.paralign;
1472 static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat *iface)
1474 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1475 TRACE("(%p)\n", This);
1476 return This->format.wrapping;
1479 static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat *iface)
1481 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1482 TRACE("(%p)\n", This);
1483 return This->format.readingdir;
1486 static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat *iface)
1488 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1489 TRACE("(%p)\n", This);
1490 return This->format.flow;
1493 static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat *iface)
1495 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1496 FIXME("(%p): stub\n", This);
1497 return 0.0;
1500 static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING *options,
1501 IDWriteInlineObject **trimming_sign)
1503 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1504 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
1506 *options = This->format.trimming;
1507 if ((*trimming_sign = This->format.trimmingsign))
1508 IDWriteInlineObject_AddRef(*trimming_sign);
1510 return S_OK;
1513 static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD *method,
1514 FLOAT *spacing, FLOAT *baseline)
1516 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1517 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
1519 *method = This->format.spacingmethod;
1520 *spacing = This->format.spacing;
1521 *baseline = This->format.baseline;
1522 return S_OK;
1525 static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat *iface, IDWriteFontCollection **collection)
1527 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1529 TRACE("(%p)->(%p)\n", This, collection);
1531 *collection = This->format.collection;
1532 IDWriteFontCollection_AddRef(*collection);
1534 return S_OK;
1537 static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat *iface)
1539 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1540 TRACE("(%p)\n", This);
1541 return This->format.family_len;
1544 static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1546 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1548 TRACE("(%p)->(%p %u)\n", This, name, size);
1550 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
1551 strcpyW(name, This->format.family_name);
1552 return S_OK;
1555 static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat *iface)
1557 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1558 TRACE("(%p)\n", This);
1559 return This->format.weight;
1562 static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat *iface)
1564 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1565 TRACE("(%p)\n", This);
1566 return This->format.style;
1569 static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat *iface)
1571 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1572 TRACE("(%p)\n", This);
1573 return This->format.stretch;
1576 static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat *iface)
1578 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1579 TRACE("(%p)\n", This);
1580 return This->format.size;
1583 static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat *iface)
1585 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1586 TRACE("(%p)\n", This);
1587 return This->format.locale_len;
1590 static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
1592 struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
1594 TRACE("(%p)->(%p %u)\n", This, name, size);
1596 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
1597 strcpyW(name, This->format.locale);
1598 return S_OK;
1601 static const IDWriteTextFormatVtbl dwritetextformatvtbl = {
1602 dwritetextformat_QueryInterface,
1603 dwritetextformat_AddRef,
1604 dwritetextformat_Release,
1605 dwritetextformat_SetTextAlignment,
1606 dwritetextformat_SetParagraphAlignment,
1607 dwritetextformat_SetWordWrapping,
1608 dwritetextformat_SetReadingDirection,
1609 dwritetextformat_SetFlowDirection,
1610 dwritetextformat_SetIncrementalTabStop,
1611 dwritetextformat_SetTrimming,
1612 dwritetextformat_SetLineSpacing,
1613 dwritetextformat_GetTextAlignment,
1614 dwritetextformat_GetParagraphAlignment,
1615 dwritetextformat_GetWordWrapping,
1616 dwritetextformat_GetReadingDirection,
1617 dwritetextformat_GetFlowDirection,
1618 dwritetextformat_GetIncrementalTabStop,
1619 dwritetextformat_GetTrimming,
1620 dwritetextformat_GetLineSpacing,
1621 dwritetextformat_GetFontCollection,
1622 dwritetextformat_GetFontFamilyNameLength,
1623 dwritetextformat_GetFontFamilyName,
1624 dwritetextformat_GetFontWeight,
1625 dwritetextformat_GetFontStyle,
1626 dwritetextformat_GetFontStretch,
1627 dwritetextformat_GetFontSize,
1628 dwritetextformat_GetLocaleNameLength,
1629 dwritetextformat_GetLocaleName
1632 HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
1633 DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
1635 struct dwrite_textformat *This;
1637 *format = NULL;
1639 This = heap_alloc(sizeof(struct dwrite_textformat));
1640 if (!This) return E_OUTOFMEMORY;
1642 This->IDWriteTextFormat_iface.lpVtbl = &dwritetextformatvtbl;
1643 This->ref = 1;
1644 This->format.family_name = heap_strdupW(family_name);
1645 This->format.family_len = strlenW(family_name);
1646 This->format.locale = heap_strdupW(locale);
1647 This->format.locale_len = strlenW(locale);
1648 This->format.weight = weight;
1649 This->format.style = style;
1650 This->format.size = size;
1651 This->format.stretch = stretch;
1652 This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
1653 This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
1654 This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
1655 This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
1656 This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
1657 This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
1658 This->format.spacing = 0.0;
1659 This->format.baseline = 0.0;
1660 This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
1661 This->format.trimming.delimiter = 0;
1662 This->format.trimming.delimiterCount = 0;
1663 This->format.trimmingsign = NULL;
1665 if (collection)
1667 This->format.collection = collection;
1668 IDWriteFontCollection_AddRef(collection);
1670 else
1672 HRESULT hr = get_system_fontcollection(&This->format.collection);
1673 if (hr != S_OK)
1675 IDWriteTextFormat_Release(&This->IDWriteTextFormat_iface);
1676 return hr;
1680 *format = &This->IDWriteTextFormat_iface;
1682 return S_OK;