gdi32: Fix arguments for OSMesaMakeCurrent when using 16 bit formats.
[wine.git] / dlls / dwrite / layout.c
blob88a83ccd1ce999ac23439d5ecd6b5c44dc281824
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_private.h"
29 #include "scripts.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
34 struct dwrite_textformat_data {
35 WCHAR *family_name;
36 UINT32 family_len;
37 WCHAR *locale;
38 UINT32 locale_len;
40 DWRITE_FONT_WEIGHT weight;
41 DWRITE_FONT_STYLE style;
42 DWRITE_FONT_STRETCH stretch;
44 DWRITE_PARAGRAPH_ALIGNMENT paralign;
45 DWRITE_READING_DIRECTION readingdir;
46 DWRITE_WORD_WRAPPING wrapping;
47 DWRITE_TEXT_ALIGNMENT textalignment;
48 DWRITE_FLOW_DIRECTION flow;
49 DWRITE_LINE_SPACING_METHOD spacingmethod;
51 FLOAT spacing;
52 FLOAT baseline;
53 FLOAT fontsize;
55 DWRITE_TRIMMING trimming;
56 IDWriteInlineObject *trimmingsign;
58 IDWriteFontCollection *collection;
61 enum layout_range_attr_kind {
62 LAYOUT_RANGE_ATTR_WEIGHT,
63 LAYOUT_RANGE_ATTR_STYLE,
64 LAYOUT_RANGE_ATTR_STRETCH,
65 LAYOUT_RANGE_ATTR_FONTSIZE,
66 LAYOUT_RANGE_ATTR_EFFECT,
67 LAYOUT_RANGE_ATTR_INLINE,
68 LAYOUT_RANGE_ATTR_UNDERLINE,
69 LAYOUT_RANGE_ATTR_STRIKETHROUGH,
70 LAYOUT_RANGE_ATTR_FONTCOLL,
71 LAYOUT_RANGE_ATTR_LOCALE,
72 LAYOUT_RANGE_ATTR_FONTFAMILY
75 struct layout_range_attr_value {
76 DWRITE_TEXT_RANGE range;
77 union {
78 DWRITE_FONT_WEIGHT weight;
79 DWRITE_FONT_STYLE style;
80 DWRITE_FONT_STRETCH stretch;
81 FLOAT fontsize;
82 IDWriteInlineObject *object;
83 IUnknown *effect;
84 BOOL underline;
85 BOOL strikethrough;
86 IDWriteFontCollection *collection;
87 const WCHAR *locale;
88 const WCHAR *fontfamily;
89 } u;
92 struct layout_range {
93 struct list entry;
94 DWRITE_TEXT_RANGE range;
95 DWRITE_FONT_WEIGHT weight;
96 DWRITE_FONT_STYLE style;
97 FLOAT fontsize;
98 DWRITE_FONT_STRETCH stretch;
99 IDWriteInlineObject *object;
100 IUnknown *effect;
101 BOOL underline;
102 BOOL strikethrough;
103 IDWriteFontCollection *collection;
104 WCHAR locale[LOCALE_NAME_MAX_LENGTH];
105 WCHAR *fontfamily;
108 struct layout_run {
109 struct list entry;
110 DWRITE_GLYPH_RUN_DESCRIPTION descr;
111 DWRITE_GLYPH_RUN run;
112 DWRITE_SCRIPT_ANALYSIS sa;
113 UINT16 *glyphs;
114 UINT16 *clustermap;
115 FLOAT *advances;
116 DWRITE_GLYPH_OFFSET *offsets;
119 struct dwrite_textlayout {
120 IDWriteTextLayout2 IDWriteTextLayout2_iface;
121 IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface;
122 IDWriteTextAnalysisSource IDWriteTextAnalysisSource_iface;
123 LONG ref;
125 WCHAR *str;
126 UINT32 len;
127 struct dwrite_textformat_data format;
128 FLOAT maxwidth;
129 FLOAT maxheight;
130 struct list ranges;
131 struct list runs;
132 BOOL recompute;
134 DWRITE_LINE_BREAKPOINT *nominal_breakpoints;
135 DWRITE_LINE_BREAKPOINT *actual_breakpoints;
137 DWRITE_CLUSTER_METRICS *clusters;
138 UINT32 clusters_count;
140 /* gdi-compatible layout specifics */
141 BOOL gdicompatible;
142 FLOAT pixels_per_dip;
143 BOOL use_gdi_natural;
144 DWRITE_MATRIX transform;
147 struct dwrite_textformat {
148 IDWriteTextFormat1 IDWriteTextFormat1_iface;
149 LONG ref;
150 struct dwrite_textformat_data format;
153 struct dwrite_trimmingsign {
154 IDWriteInlineObject IDWriteInlineObject_iface;
155 LONG ref;
158 struct dwrite_typography {
159 IDWriteTypography IDWriteTypography_iface;
160 LONG ref;
162 DWRITE_FONT_FEATURE *features;
163 UINT32 allocated;
164 UINT32 count;
167 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl;
169 static void release_format_data(struct dwrite_textformat_data *data)
171 if (data->collection) IDWriteFontCollection_Release(data->collection);
172 if (data->trimmingsign) IDWriteInlineObject_Release(data->trimmingsign);
173 heap_free(data->family_name);
174 heap_free(data->locale);
177 static inline struct dwrite_textlayout *impl_from_IDWriteTextLayout2(IDWriteTextLayout2 *iface)
179 return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextLayout2_iface);
182 static inline struct dwrite_textlayout *impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink *iface)
184 return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextAnalysisSink_iface);
187 static inline struct dwrite_textlayout *impl_from_IDWriteTextAnalysisSource(IDWriteTextAnalysisSource *iface)
189 return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextAnalysisSource_iface);
192 static inline struct dwrite_textformat *impl_from_IDWriteTextFormat1(IDWriteTextFormat1 *iface)
194 return CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat1_iface);
197 static inline struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat1(IDWriteTextFormat1 *iface)
199 return iface->lpVtbl == &dwritetextformatvtbl ? impl_from_IDWriteTextFormat1(iface) : NULL;
202 static inline struct dwrite_trimmingsign *impl_from_IDWriteInlineObject(IDWriteInlineObject *iface)
204 return CONTAINING_RECORD(iface, struct dwrite_trimmingsign, IDWriteInlineObject_iface);
207 static inline struct dwrite_typography *impl_from_IDWriteTypography(IDWriteTypography *iface)
209 return CONTAINING_RECORD(iface, struct dwrite_typography, IDWriteTypography_iface);
212 static inline const char *debugstr_run(const struct layout_run *run)
214 return wine_dbg_sprintf("[%u,%u]", run->descr.textPosition, run->descr.textPosition +
215 run->descr.stringLength);
218 static struct layout_run *alloc_layout_run(void)
220 struct layout_run *ret;
222 ret = heap_alloc(sizeof(*ret));
223 if (!ret) return NULL;
225 ret->descr.localeName = NULL;
226 ret->descr.string = NULL;
227 ret->descr.stringLength = 0;
228 ret->descr.clusterMap = NULL;
229 ret->descr.textPosition = 0;
231 ret->run.fontFace = NULL;
232 ret->run.fontEmSize = 0.0;
233 ret->run.glyphCount = 0;
234 ret->run.glyphIndices = NULL;
235 ret->run.glyphAdvances = NULL;
236 ret->run.glyphOffsets = NULL;
237 ret->run.isSideways = FALSE;
238 ret->run.bidiLevel = 0;
240 ret->sa.script = Script_Unknown;
241 ret->sa.shapes = DWRITE_SCRIPT_SHAPES_DEFAULT;
243 ret->glyphs = NULL;
244 ret->clustermap = NULL;
245 ret->advances = NULL;
246 ret->offsets = NULL;
248 return ret;
251 static void free_layout_runs(struct dwrite_textlayout *layout)
253 struct layout_run *cur, *cur2;
254 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->runs, struct layout_run, entry) {
255 list_remove(&cur->entry);
256 if (cur->run.fontFace)
257 IDWriteFontFace_Release(cur->run.fontFace);
258 heap_free(cur->glyphs);
259 heap_free(cur->clustermap);
260 heap_free(cur->advances);
261 heap_free(cur->offsets);
262 heap_free(cur);
266 /* Used to resolve break condition by forcing stronger condition over weaker. */
267 static inline DWRITE_BREAK_CONDITION override_break_condition(DWRITE_BREAK_CONDITION existingbreak, DWRITE_BREAK_CONDITION newbreak)
269 switch (existingbreak) {
270 case DWRITE_BREAK_CONDITION_NEUTRAL:
271 return newbreak;
272 case DWRITE_BREAK_CONDITION_CAN_BREAK:
273 return newbreak == DWRITE_BREAK_CONDITION_NEUTRAL ? existingbreak : newbreak;
274 /* let's keep stronger conditions as is */
275 case DWRITE_BREAK_CONDITION_MAY_NOT_BREAK:
276 case DWRITE_BREAK_CONDITION_MUST_BREAK:
277 break;
278 default:
279 ERR("unknown break condition %d\n", existingbreak);
282 return existingbreak;
285 /* Actual breakpoint data gets updated with break condition required by inline object set for range 'cur'. */
286 static HRESULT layout_update_breakpoints_range(struct dwrite_textlayout *layout, const struct layout_range *cur)
288 DWRITE_BREAK_CONDITION before, after;
289 HRESULT hr;
290 UINT32 i;
292 hr = IDWriteInlineObject_GetBreakConditions(cur->object, &before, &after);
293 if (FAILED(hr))
294 return hr;
296 if (!layout->actual_breakpoints) {
297 layout->actual_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
298 if (!layout->actual_breakpoints)
299 return E_OUTOFMEMORY;
301 memcpy(layout->actual_breakpoints, layout->nominal_breakpoints, sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
303 for (i = cur->range.startPosition; i < cur->range.length + cur->range.startPosition; i++) {
304 UINT32 j = i + cur->range.startPosition;
305 if (i == 0) {
306 if (j)
307 layout->actual_breakpoints[j].breakConditionBefore = layout->actual_breakpoints[j-1].breakConditionAfter =
308 override_break_condition(layout->actual_breakpoints[j-1].breakConditionAfter, before);
309 else
310 layout->actual_breakpoints[j].breakConditionBefore = before;
312 layout->actual_breakpoints[j].breakConditionAfter = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK;
315 layout->actual_breakpoints[j].isWhitespace = 0;
316 layout->actual_breakpoints[j].isSoftHyphen = 0;
318 if (i == cur->range.length - 1) {
319 layout->actual_breakpoints[j].breakConditionBefore = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK;
320 if (j < layout->len - 1)
321 layout->actual_breakpoints[j].breakConditionAfter = layout->actual_breakpoints[j+1].breakConditionAfter =
322 override_break_condition(layout->actual_breakpoints[j+1].breakConditionAfter, before);
323 else
324 layout->actual_breakpoints[j].breakConditionAfter = before;
328 return S_OK;
331 static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos);
333 static void init_cluster_metrics(const struct layout_run *run, DWRITE_CLUSTER_METRICS *metrics)
335 metrics->width = 0.0;
336 metrics->length = 1;
337 metrics->canWrapLineAfter = FALSE;
338 metrics->isWhitespace = FALSE;
339 metrics->isNewline = FALSE;
340 metrics->isSoftHyphen = FALSE;
341 metrics->isRightToLeft = run->run.bidiLevel & 1;
342 metrics->padding = 0;
347 All clusters in a 'run' will be added to 'layout' data, starting at index pointed to by 'cluster'.
348 On return 'cluster' is updated to point to next metrics struct to be filled in on next call.
351 static void layout_set_cluster_metrics(struct dwrite_textlayout *layout, const struct layout_run *run, UINT32 *cluster)
353 DWRITE_CLUSTER_METRICS *metrics = &layout->clusters[*cluster];
354 UINT16 glyph;
355 UINT32 i;
357 glyph = run->descr.clusterMap[0];
358 init_cluster_metrics(run, metrics);
360 for (i = 0; i < run->descr.stringLength; i++) {
361 BOOL newcluster = glyph != run->descr.clusterMap[i];
363 /* add new cluster on starting glyph change or simply when run is over */
364 if (newcluster || i == run->descr.stringLength - 1) {
365 UINT8 breakcondition;
366 UINT16 j;
368 for (j = glyph; j < run->descr.clusterMap[i]; j++)
369 metrics->width += run->run.glyphAdvances[j];
371 /* FIXME: also set isWhitespace, isNewline and isSoftHyphen */
372 breakcondition = newcluster ? layout->nominal_breakpoints[i].breakConditionBefore :
373 layout->nominal_breakpoints[i].breakConditionAfter;
374 metrics->canWrapLineAfter = breakcondition == DWRITE_BREAK_CONDITION_CAN_BREAK ||
375 breakcondition == DWRITE_BREAK_CONDITION_MUST_BREAK;
377 /* advance to next cluster */
378 glyph = run->descr.clusterMap[i];
379 *cluster += 1;
380 metrics++;
381 init_cluster_metrics(run, metrics);
383 else
384 metrics->length++;
388 static HRESULT layout_compute_runs(struct dwrite_textlayout *layout)
390 IDWriteTextAnalyzer *analyzer;
391 struct layout_range *range;
392 struct layout_run *run;
393 UINT32 cluster = 0;
394 HRESULT hr;
396 free_layout_runs(layout);
397 heap_free(layout->clusters);
398 layout->clusters_count = 0;
399 layout->clusters = heap_alloc(layout->len*sizeof(DWRITE_CLUSTER_METRICS));
400 if (!layout->clusters)
401 return E_OUTOFMEMORY;
403 hr = get_textanalyzer(&analyzer);
404 if (FAILED(hr))
405 return hr;
407 LIST_FOR_EACH_ENTRY(range, &layout->ranges, struct layout_range, entry) {
408 /* inline objects override actual text in a range */
409 if (range->object) {
410 hr = layout_update_breakpoints_range(layout, range);
411 if (FAILED(hr))
412 return hr;
413 continue;
416 /* initial splitting by script */
417 hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &layout->IDWriteTextAnalysisSource_iface,
418 range->range.startPosition, range->range.length, &layout->IDWriteTextAnalysisSink_iface);
419 if (FAILED(hr))
420 break;
422 /* this splits it further */
423 hr = IDWriteTextAnalyzer_AnalyzeBidi(analyzer, &layout->IDWriteTextAnalysisSource_iface,
424 range->range.startPosition, range->range.length, &layout->IDWriteTextAnalysisSink_iface);
425 if (FAILED(hr))
426 break;
429 /* fill run info */
430 LIST_FOR_EACH_ENTRY(run, &layout->runs, struct layout_run, entry) {
431 DWRITE_SHAPING_GLYPH_PROPERTIES *glyph_props = NULL;
432 DWRITE_SHAPING_TEXT_PROPERTIES *text_props = NULL;
433 IDWriteFontFamily *family;
434 UINT32 index, max_count;
435 IDWriteFont *font;
436 BOOL exists = TRUE;
438 range = get_layout_range_by_pos(layout, run->descr.textPosition);
440 hr = IDWriteFontCollection_FindFamilyName(range->collection, range->fontfamily, &index, &exists);
441 if (FAILED(hr) || !exists) {
442 WARN("%s: family %s not found in collection %p\n", debugstr_run(run), debugstr_w(range->fontfamily), range->collection);
443 continue;
446 hr = IDWriteFontCollection_GetFontFamily(range->collection, index, &family);
447 if (FAILED(hr))
448 continue;
450 hr = IDWriteFontFamily_GetFirstMatchingFont(family, range->weight, range->stretch, range->style, &font);
451 IDWriteFontFamily_Release(family);
452 if (FAILED(hr)) {
453 WARN("%s: failed to get a matching font\n", debugstr_run(run));
454 continue;
457 hr = IDWriteFont_CreateFontFace(font, &run->run.fontFace);
458 IDWriteFont_Release(font);
459 if (FAILED(hr))
460 continue;
462 run->run.fontEmSize = range->fontsize;
463 run->descr.localeName = range->locale;
464 run->clustermap = heap_alloc(run->descr.stringLength*sizeof(UINT16));
466 max_count = 3*run->descr.stringLength/2 + 16;
467 run->glyphs = heap_alloc(max_count*sizeof(UINT16));
468 if (!run->clustermap || !run->glyphs)
469 goto memerr;
471 text_props = heap_alloc(run->descr.stringLength*sizeof(DWRITE_SHAPING_TEXT_PROPERTIES));
472 glyph_props = heap_alloc(max_count*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
473 if (!text_props || !glyph_props)
474 goto memerr;
476 while (1) {
477 hr = IDWriteTextAnalyzer_GetGlyphs(analyzer, run->descr.string, run->descr.stringLength,
478 run->run.fontFace, FALSE /* FIXME */, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
479 NULL /* FIXME */, NULL, NULL, 0, max_count, run->clustermap, text_props, run->glyphs, glyph_props,
480 &run->run.glyphCount);
481 if (hr == E_NOT_SUFFICIENT_BUFFER) {
482 heap_free(run->glyphs);
483 heap_free(glyph_props);
485 max_count = run->run.glyphCount;
487 run->glyphs = heap_alloc(max_count*sizeof(UINT16));
488 glyph_props = heap_alloc(max_count*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES));
489 if (!run->glyphs || !glyph_props)
490 goto memerr;
492 continue;
495 break;
498 if (FAILED(hr)) {
499 heap_free(text_props);
500 heap_free(glyph_props);
501 WARN("%s: shaping failed 0x%08x\n", debugstr_run(run), hr);
502 continue;
505 run->run.glyphIndices = run->glyphs;
506 run->descr.clusterMap = run->clustermap;
508 run->advances = heap_alloc(run->run.glyphCount*sizeof(FLOAT));
509 run->offsets = heap_alloc(run->run.glyphCount*sizeof(DWRITE_GLYPH_OFFSET));
510 if (!run->advances || !run->offsets)
511 goto memerr;
513 /* now set advances and offsets */
514 if (layout->gdicompatible)
515 hr = IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap,
516 text_props, run->descr.stringLength, run->run.glyphIndices, glyph_props, run->run.glyphCount,
517 run->run.fontFace, run->run.fontEmSize, layout->pixels_per_dip, &layout->transform, layout->use_gdi_natural,
518 FALSE /* FIXME */, run->run.bidiLevel & 1, &run->sa, run->descr.localeName, NULL, NULL, 0,
519 run->advances, run->offsets);
520 else
521 hr = IDWriteTextAnalyzer_GetGlyphPlacements(analyzer, run->descr.string, run->descr.clusterMap, text_props,
522 run->descr.stringLength, run->run.glyphIndices, glyph_props, run->run.glyphCount, run->run.fontFace,
523 run->run.fontEmSize, FALSE /* FIXME */, run->run.bidiLevel & 1, &run->sa, run->descr.localeName,
524 NULL, NULL, 0, run->advances, run->offsets);
526 heap_free(text_props);
527 heap_free(glyph_props);
528 if (FAILED(hr))
529 WARN("%s: failed to get glyph placement info, 0x%08x\n", debugstr_run(run), hr);
531 run->run.glyphAdvances = run->advances;
532 run->run.glyphOffsets = run->offsets;
534 /* now set cluster metrics */
535 layout_set_cluster_metrics(layout, run, &cluster);
537 continue;
539 memerr:
540 heap_free(text_props);
541 heap_free(glyph_props);
542 heap_free(run->clustermap);
543 heap_free(run->glyphs);
544 heap_free(run->advances);
545 heap_free(run->offsets);
546 run->advances = NULL;
547 run->offsets = NULL;
548 run->clustermap = run->glyphs = NULL;
549 hr = E_OUTOFMEMORY;
550 break;
553 if (hr == S_OK)
554 layout->clusters_count = cluster + 1;
556 IDWriteTextAnalyzer_Release(analyzer);
557 return hr;
560 static HRESULT layout_compute(struct dwrite_textlayout *layout)
562 HRESULT hr;
564 if (!layout->recompute)
565 return S_OK;
567 /* nominal breakpoints are evaluated only once, because string never changes */
568 if (!layout->nominal_breakpoints) {
569 IDWriteTextAnalyzer *analyzer;
570 HRESULT hr;
572 layout->nominal_breakpoints = heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT)*layout->len);
573 if (!layout->nominal_breakpoints)
574 return E_OUTOFMEMORY;
576 hr = get_textanalyzer(&analyzer);
577 if (FAILED(hr))
578 return hr;
580 hr = IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer, &layout->IDWriteTextAnalysisSource_iface,
581 0, layout->len, &layout->IDWriteTextAnalysisSink_iface);
582 IDWriteTextAnalyzer_Release(analyzer);
585 hr = layout_compute_runs(layout);
587 if (TRACE_ON(dwrite)) {
588 struct layout_run *cur;
590 LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
591 TRACE("run [%u,%u], len %u, bidilevel %u\n", cur->descr.textPosition, cur->descr.textPosition+cur->descr.stringLength-1,
592 cur->descr.stringLength, cur->run.bidiLevel);
596 layout->recompute = FALSE;
597 return hr;
600 /* To be used in IDWriteTextLayout methods to validate and fix passed range */
601 static inline BOOL validate_text_range(struct dwrite_textlayout *layout, DWRITE_TEXT_RANGE *r)
603 if (r->startPosition >= layout->len)
604 return FALSE;
606 if (r->startPosition + r->length > layout->len)
607 r->length = layout->len - r->startPosition;
609 return TRUE;
612 static BOOL is_same_layout_attrvalue(struct layout_range const *range, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
614 switch (attr) {
615 case LAYOUT_RANGE_ATTR_WEIGHT:
616 return range->weight == value->u.weight;
617 case LAYOUT_RANGE_ATTR_STYLE:
618 return range->style == value->u.style;
619 case LAYOUT_RANGE_ATTR_STRETCH:
620 return range->stretch == value->u.stretch;
621 case LAYOUT_RANGE_ATTR_FONTSIZE:
622 return range->fontsize == value->u.fontsize;
623 case LAYOUT_RANGE_ATTR_INLINE:
624 return range->object == value->u.object;
625 case LAYOUT_RANGE_ATTR_EFFECT:
626 return range->effect == value->u.effect;
627 case LAYOUT_RANGE_ATTR_UNDERLINE:
628 return range->underline == value->u.underline;
629 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
630 return range->strikethrough == value->u.strikethrough;
631 case LAYOUT_RANGE_ATTR_FONTCOLL:
632 return range->collection == value->u.collection;
633 case LAYOUT_RANGE_ATTR_LOCALE:
634 return strcmpW(range->locale, value->u.locale) == 0;
635 case LAYOUT_RANGE_ATTR_FONTFAMILY:
636 return strcmpW(range->fontfamily, value->u.fontfamily) == 0;
637 default:
641 return FALSE;
644 static inline BOOL is_same_layout_attributes(struct layout_range const *left, struct layout_range const *right)
646 return left->weight == right->weight &&
647 left->style == right->style &&
648 left->stretch == right->stretch &&
649 left->fontsize == right->fontsize &&
650 left->object == right->object &&
651 left->effect == right->effect &&
652 left->underline == right->underline &&
653 left->strikethrough == right->strikethrough &&
654 left->collection == right->collection &&
655 !strcmpW(left->locale, right->locale) &&
656 !strcmpW(left->fontfamily, right->fontfamily);
659 static inline BOOL is_same_text_range(const DWRITE_TEXT_RANGE *left, const DWRITE_TEXT_RANGE *right)
661 return left->startPosition == right->startPosition && left->length == right->length;
664 /* Allocates range and inits it with default values from text format. */
665 static struct layout_range *alloc_layout_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *r)
667 struct layout_range *range;
669 range = heap_alloc(sizeof(*range));
670 if (!range) return NULL;
672 range->range = *r;
673 range->weight = layout->format.weight;
674 range->style = layout->format.style;
675 range->stretch = layout->format.stretch;
676 range->fontsize = layout->format.fontsize;
677 range->object = NULL;
678 range->effect = NULL;
679 range->underline = FALSE;
680 range->strikethrough = FALSE;
682 range->fontfamily = heap_strdupW(layout->format.family_name);
683 if (!range->fontfamily) {
684 heap_free(range);
685 return NULL;
688 range->collection = layout->format.collection;
689 if (range->collection)
690 IDWriteFontCollection_AddRef(range->collection);
691 strcpyW(range->locale, layout->format.locale);
693 return range;
696 static struct layout_range *alloc_layout_range_from(struct layout_range *from, const DWRITE_TEXT_RANGE *r)
698 struct layout_range *range;
700 range = heap_alloc(sizeof(*range));
701 if (!range) return NULL;
703 *range = *from;
704 range->range = *r;
706 /* update refcounts */
707 if (range->object)
708 IDWriteInlineObject_AddRef(range->object);
709 if (range->effect)
710 IUnknown_AddRef(range->effect);
711 if (range->collection)
712 IDWriteFontCollection_AddRef(range->collection);
714 return range;
717 static void free_layout_range(struct layout_range *range)
719 if (!range)
720 return;
721 if (range->object)
722 IDWriteInlineObject_Release(range->object);
723 if (range->effect)
724 IUnknown_Release(range->effect);
725 if (range->collection)
726 IDWriteFontCollection_Release(range->collection);
727 heap_free(range->fontfamily);
728 heap_free(range);
731 static void free_layout_ranges_list(struct dwrite_textlayout *layout)
733 struct layout_range *cur, *cur2;
734 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &layout->ranges, struct layout_range, entry) {
735 list_remove(&cur->entry);
736 free_layout_range(cur);
740 static struct layout_range *find_outer_range(struct dwrite_textlayout *layout, const DWRITE_TEXT_RANGE *range)
742 struct layout_range *cur;
744 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
746 if (cur->range.startPosition > range->startPosition)
747 return NULL;
749 if ((cur->range.startPosition + cur->range.length < range->startPosition + range->length) &&
750 (range->startPosition < cur->range.startPosition + cur->range.length))
751 return NULL;
752 if (cur->range.startPosition + cur->range.length >= range->startPosition + range->length)
753 return cur;
756 return NULL;
759 static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *layout, UINT32 pos)
761 struct layout_range *cur;
763 LIST_FOR_EACH_ENTRY(cur, &layout->ranges, struct layout_range, entry) {
764 DWRITE_TEXT_RANGE *r = &cur->range;
765 if (r->startPosition <= pos && pos < r->startPosition + r->length)
766 return cur;
769 return NULL;
772 static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
774 BOOL changed = FALSE;
776 switch (attr) {
777 case LAYOUT_RANGE_ATTR_WEIGHT:
778 changed = dest->weight != value->u.weight;
779 dest->weight = value->u.weight;
780 break;
781 case LAYOUT_RANGE_ATTR_STYLE:
782 changed = dest->style != value->u.style;
783 dest->style = value->u.style;
784 break;
785 case LAYOUT_RANGE_ATTR_STRETCH:
786 changed = dest->stretch != value->u.stretch;
787 dest->stretch = value->u.stretch;
788 break;
789 case LAYOUT_RANGE_ATTR_FONTSIZE:
790 changed = dest->fontsize != value->u.fontsize;
791 dest->fontsize = value->u.fontsize;
792 break;
793 case LAYOUT_RANGE_ATTR_INLINE:
794 changed = dest->object != value->u.object;
795 if (changed && dest->object)
796 IDWriteInlineObject_Release(dest->object);
797 dest->object = value->u.object;
798 if (dest->object)
799 IDWriteInlineObject_AddRef(dest->object);
800 break;
801 case LAYOUT_RANGE_ATTR_EFFECT:
802 changed = dest->effect != value->u.effect;
803 if (changed && dest->effect)
804 IUnknown_Release(dest->effect);
805 dest->effect = value->u.effect;
806 if (dest->effect)
807 IUnknown_AddRef(dest->effect);
808 break;
809 case LAYOUT_RANGE_ATTR_UNDERLINE:
810 changed = dest->underline != value->u.underline;
811 dest->underline = value->u.underline;
812 break;
813 case LAYOUT_RANGE_ATTR_STRIKETHROUGH:
814 changed = dest->strikethrough != value->u.strikethrough;
815 dest->strikethrough = value->u.strikethrough;
816 break;
817 case LAYOUT_RANGE_ATTR_FONTCOLL:
818 changed = dest->collection != value->u.collection;
819 if (changed && dest->collection)
820 IDWriteFontCollection_Release(dest->collection);
821 dest->collection = value->u.collection;
822 if (dest->collection)
823 IDWriteFontCollection_AddRef(dest->collection);
824 break;
825 case LAYOUT_RANGE_ATTR_LOCALE:
826 changed = strcmpW(dest->locale, value->u.locale) != 0;
827 if (changed)
828 strcpyW(dest->locale, value->u.locale);
829 break;
830 case LAYOUT_RANGE_ATTR_FONTFAMILY:
831 changed = strcmpW(dest->fontfamily, value->u.fontfamily) != 0;
832 if (changed) {
833 heap_free(dest->fontfamily);
834 dest->fontfamily = heap_strdupW(value->u.fontfamily);
836 break;
837 default:
841 return changed;
844 static inline BOOL is_in_layout_range(const DWRITE_TEXT_RANGE *outer, const DWRITE_TEXT_RANGE *inner)
846 return (inner->startPosition >= outer->startPosition) &&
847 (inner->startPosition + inner->length <= outer->startPosition + outer->length);
850 static inline HRESULT return_range(const struct layout_range *range, DWRITE_TEXT_RANGE *r)
852 if (r) *r = range->range;
853 return S_OK;
856 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
857 static HRESULT set_layout_range_attr(struct dwrite_textlayout *layout, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
859 struct layout_range *outer, *right, *left, *cur;
860 struct list *ranges = &layout->ranges;
861 BOOL changed = FALSE;
862 DWRITE_TEXT_RANGE r;
864 if (!validate_text_range(layout, &value->range))
865 return S_OK;
867 /* If new range is completely within existing range, split existing range in two */
868 if ((outer = find_outer_range(layout, &value->range))) {
870 /* no need to add same range */
871 if (is_same_layout_attrvalue(outer, attr, value))
872 return S_OK;
874 /* for matching range bounds just replace data */
875 if (is_same_text_range(&outer->range, &value->range)) {
876 changed = set_layout_range_attrval(outer, attr, value);
877 goto done;
880 /* add new range to the left */
881 if (value->range.startPosition == outer->range.startPosition) {
882 left = alloc_layout_range_from(outer, &value->range);
883 if (!left) return E_OUTOFMEMORY;
885 changed = set_layout_range_attrval(left, attr, value);
886 list_add_before(&outer->entry, &left->entry);
887 outer->range.startPosition += value->range.length;
888 outer->range.length -= value->range.length;
889 goto done;
892 /* add new range to the right */
893 if (value->range.startPosition + value->range.length == outer->range.startPosition + outer->range.length) {
894 right = alloc_layout_range_from(outer, &value->range);
895 if (!right) return E_OUTOFMEMORY;
897 changed = set_layout_range_attrval(right, attr, value);
898 list_add_after(&outer->entry, &right->entry);
899 outer->range.length -= value->range.length;
900 goto done;
903 r.startPosition = value->range.startPosition + value->range.length;
904 r.length = outer->range.length + outer->range.startPosition - r.startPosition;
906 /* right part */
907 right = alloc_layout_range_from(outer, &r);
908 /* new range in the middle */
909 cur = alloc_layout_range_from(outer, &value->range);
910 if (!right || !cur) {
911 free_layout_range(right);
912 free_layout_range(cur);
913 return E_OUTOFMEMORY;
916 /* reuse container range as a left part */
917 outer->range.length = value->range.startPosition - outer->range.startPosition;
919 /* new part */
920 set_layout_range_attrval(cur, attr, value);
922 list_add_after(&outer->entry, &cur->entry);
923 list_add_after(&cur->entry, &right->entry);
925 return S_OK;
928 /* Now it's only possible that given range contains some existing ranges, fully or partially.
929 Update all of them. */
930 left = get_layout_range_by_pos(layout, value->range.startPosition);
931 if (left->range.startPosition == value->range.startPosition)
932 changed = set_layout_range_attrval(left, attr, value);
933 else /* need to split */ {
934 r.startPosition = value->range.startPosition;
935 r.length = left->range.length - value->range.startPosition + left->range.startPosition;
936 left->range.length -= r.length;
937 cur = alloc_layout_range_from(left, &r);
938 changed = set_layout_range_attrval(cur, attr, value);
939 list_add_after(&left->entry, &cur->entry);
941 cur = LIST_ENTRY(list_next(ranges, &left->entry), struct layout_range, entry);
943 /* for all existing ranges covered by new one update value */
944 while (is_in_layout_range(&value->range, &cur->range)) {
945 changed = set_layout_range_attrval(cur, attr, value);
946 cur = LIST_ENTRY(list_next(ranges, &cur->entry), struct layout_range, entry);
949 /* it's possible rightmost range intersects */
950 if (cur && (cur->range.startPosition < value->range.startPosition + value->range.length)) {
951 r.startPosition = cur->range.startPosition;
952 r.length = value->range.startPosition + value->range.length - cur->range.startPosition;
953 left = alloc_layout_range_from(cur, &r);
954 changed = set_layout_range_attrval(left, attr, value);
955 cur->range.startPosition += left->range.length;
956 cur->range.length -= left->range.length;
957 list_add_before(&cur->entry, &left->entry);
960 done:
961 if (changed) {
962 struct list *next, *i;
964 layout->recompute = TRUE;
965 i = list_head(ranges);
966 while ((next = list_next(ranges, i))) {
967 struct layout_range *next_range = LIST_ENTRY(next, struct layout_range, entry);
969 cur = LIST_ENTRY(i, struct layout_range, entry);
970 if (is_same_layout_attributes(cur, next_range)) {
971 /* remove similar range */
972 cur->range.length += next_range->range.length;
973 list_remove(next);
974 free_layout_range(next_range);
976 else
977 i = list_next(ranges, i);
981 return S_OK;
984 static inline const WCHAR *get_string_attribute_ptr(struct layout_range *range, enum layout_range_attr_kind kind)
986 const WCHAR *str;
988 switch (kind) {
989 case LAYOUT_RANGE_ATTR_LOCALE:
990 str = range->locale;
991 break;
992 case LAYOUT_RANGE_ATTR_FONTFAMILY:
993 str = range->fontfamily;
994 break;
995 default:
996 str = NULL;
999 return str;
1002 static HRESULT get_string_attribute_length(struct dwrite_textlayout *layout, enum layout_range_attr_kind kind, UINT32 position,
1003 UINT32 *length, DWRITE_TEXT_RANGE *r)
1005 struct layout_range *range;
1006 const WCHAR *str;
1008 range = get_layout_range_by_pos(layout, position);
1009 if (!range) {
1010 *length = 0;
1011 return S_OK;
1014 str = get_string_attribute_ptr(range, kind);
1015 *length = strlenW(str);
1016 return return_range(range, r);
1019 static HRESULT get_string_attribute_value(struct dwrite_textlayout *layout, enum layout_range_attr_kind kind, UINT32 position,
1020 WCHAR *ret, UINT32 length, DWRITE_TEXT_RANGE *r)
1022 struct layout_range *range;
1023 const WCHAR *str;
1025 if (length == 0)
1026 return E_INVALIDARG;
1028 ret[0] = 0;
1029 range = get_layout_range_by_pos(layout, position);
1030 if (!range)
1031 return E_INVALIDARG;
1033 str = get_string_attribute_ptr(range, kind);
1034 if (length < strlenW(str) + 1)
1035 return E_NOT_SUFFICIENT_BUFFER;
1037 strcpyW(ret, str);
1038 return return_range(range, r);
1041 static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout2 *iface, REFIID riid, void **obj)
1043 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1045 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1047 if (IsEqualIID(riid, &IID_IDWriteTextLayout2) ||
1048 IsEqualIID(riid, &IID_IDWriteTextLayout1) ||
1049 IsEqualIID(riid, &IID_IDWriteTextLayout) ||
1050 IsEqualIID(riid, &IID_IDWriteTextFormat) ||
1051 IsEqualIID(riid, &IID_IUnknown))
1053 *obj = iface;
1054 IDWriteTextLayout2_AddRef(iface);
1055 return S_OK;
1058 *obj = NULL;
1060 return E_NOINTERFACE;
1063 static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout2 *iface)
1065 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1066 ULONG ref = InterlockedIncrement(&This->ref);
1067 TRACE("(%p)->(%d)\n", This, ref);
1068 return ref;
1071 static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout2 *iface)
1073 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1074 ULONG ref = InterlockedDecrement(&This->ref);
1076 TRACE("(%p)->(%d)\n", This, ref);
1078 if (!ref) {
1079 free_layout_ranges_list(This);
1080 free_layout_runs(This);
1081 release_format_data(&This->format);
1082 heap_free(This->nominal_breakpoints);
1083 heap_free(This->actual_breakpoints);
1084 heap_free(This->clusters);
1085 heap_free(This->str);
1086 heap_free(This);
1089 return ref;
1092 static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout2 *iface, DWRITE_TEXT_ALIGNMENT alignment)
1094 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1095 FIXME("(%p)->(%d): stub\n", This, alignment);
1096 return E_NOTIMPL;
1099 static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout2 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
1101 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1102 FIXME("(%p)->(%d): stub\n", This, alignment);
1103 return E_NOTIMPL;
1106 static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout2 *iface, DWRITE_WORD_WRAPPING wrapping)
1108 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1109 FIXME("(%p)->(%d): stub\n", This, wrapping);
1110 return E_NOTIMPL;
1113 static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout2 *iface, DWRITE_READING_DIRECTION direction)
1115 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1116 FIXME("(%p)->(%d): stub\n", This, direction);
1117 return E_NOTIMPL;
1120 static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout2 *iface, DWRITE_FLOW_DIRECTION direction)
1122 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1123 FIXME("(%p)->(%d): stub\n", This, direction);
1124 return E_NOTIMPL;
1127 static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout2 *iface, FLOAT tabstop)
1129 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1130 FIXME("(%p)->(%f): stub\n", This, tabstop);
1131 return E_NOTIMPL;
1134 static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout2 *iface, DWRITE_TRIMMING const *trimming,
1135 IDWriteInlineObject *trimming_sign)
1137 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1138 FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
1139 return E_NOTIMPL;
1142 static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout2 *iface, DWRITE_LINE_SPACING_METHOD spacing,
1143 FLOAT line_spacing, FLOAT baseline)
1145 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1146 FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
1147 return E_NOTIMPL;
1150 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout2 *iface)
1152 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1153 TRACE("(%p)\n", This);
1154 return This->format.textalignment;
1157 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout2 *iface)
1159 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1160 TRACE("(%p)\n", This);
1161 return This->format.paralign;
1164 static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout2 *iface)
1166 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1167 FIXME("(%p): stub\n", This);
1168 return This->format.wrapping;
1171 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout2 *iface)
1173 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1174 TRACE("(%p)\n", This);
1175 return This->format.readingdir;
1178 static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout2 *iface)
1180 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1181 TRACE("(%p)\n", This);
1182 return This->format.flow;
1185 static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout2 *iface)
1187 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1188 FIXME("(%p): stub\n", This);
1189 return 0.0;
1192 static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout2 *iface, DWRITE_TRIMMING *options,
1193 IDWriteInlineObject **trimming_sign)
1195 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1197 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
1199 *options = This->format.trimming;
1200 *trimming_sign = This->format.trimmingsign;
1201 if (*trimming_sign)
1202 IDWriteInlineObject_AddRef(*trimming_sign);
1203 return S_OK;
1206 static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout2 *iface, DWRITE_LINE_SPACING_METHOD *method,
1207 FLOAT *spacing, FLOAT *baseline)
1209 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1211 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
1213 *method = This->format.spacingmethod;
1214 *spacing = This->format.spacing;
1215 *baseline = This->format.baseline;
1216 return S_OK;
1219 static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout2 *iface, IDWriteFontCollection **collection)
1221 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1223 TRACE("(%p)->(%p)\n", This, collection);
1225 *collection = This->format.collection;
1226 if (*collection)
1227 IDWriteFontCollection_AddRef(*collection);
1228 return S_OK;
1231 static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout2 *iface)
1233 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1234 TRACE("(%p)\n", This);
1235 return This->format.family_len;
1238 static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout2 *iface, WCHAR *name, UINT32 size)
1240 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1242 TRACE("(%p)->(%p %u)\n", This, name, size);
1244 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
1245 strcpyW(name, This->format.family_name);
1246 return S_OK;
1249 static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout2 *iface)
1251 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1252 TRACE("(%p)\n", This);
1253 return This->format.weight;
1256 static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout2 *iface)
1258 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1259 TRACE("(%p)\n", This);
1260 return This->format.style;
1263 static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout2 *iface)
1265 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1266 TRACE("(%p)\n", This);
1267 return This->format.stretch;
1270 static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout2 *iface)
1272 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1273 TRACE("(%p)\n", This);
1274 return This->format.fontsize;
1277 static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout2 *iface)
1279 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1280 TRACE("(%p)\n", This);
1281 return This->format.locale_len;
1284 static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout2 *iface, WCHAR *name, UINT32 size)
1286 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1288 TRACE("(%p)->(%p %u)\n", This, name, size);
1290 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
1291 strcpyW(name, This->format.locale);
1292 return S_OK;
1295 static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout2 *iface, FLOAT maxWidth)
1297 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1298 TRACE("(%p)->(%.1f)\n", This, maxWidth);
1300 if (maxWidth < 0.0)
1301 return E_INVALIDARG;
1303 This->maxwidth = maxWidth;
1304 return S_OK;
1307 static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout2 *iface, FLOAT maxHeight)
1309 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1310 TRACE("(%p)->(%.1f)\n", This, maxHeight);
1312 if (maxHeight < 0.0)
1313 return E_INVALIDARG;
1315 This->maxheight = maxHeight;
1316 return S_OK;
1319 static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout2 *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
1321 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1322 struct layout_range_attr_value value;
1324 TRACE("(%p)->(%p %s)\n", This, collection, debugstr_range(&range));
1326 value.range = range;
1327 value.u.collection = collection;
1328 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTCOLL, &value);
1331 static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout2 *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
1333 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1334 struct layout_range_attr_value value;
1336 TRACE("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_range(&range));
1338 if (!name)
1339 return E_INVALIDARG;
1341 value.range = range;
1342 value.u.fontfamily = name;
1343 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTFAMILY, &value);
1346 static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout2 *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
1348 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1349 struct layout_range_attr_value value;
1351 TRACE("(%p)->(%d %s)\n", This, weight, debugstr_range(&range));
1353 value.range = range;
1354 value.u.weight = weight;
1355 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_WEIGHT, &value);
1358 static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout2 *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
1360 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1361 struct layout_range_attr_value value;
1363 TRACE("(%p)->(%d %s)\n", This, style, debugstr_range(&range));
1365 value.range = range;
1366 value.u.style = style;
1367 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STYLE, &value);
1370 static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout2 *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
1372 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1373 struct layout_range_attr_value value;
1375 TRACE("(%p)->(%d %s)\n", This, stretch, debugstr_range(&range));
1377 value.range = range;
1378 value.u.stretch = stretch;
1379 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRETCH, &value);
1382 static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout2 *iface, FLOAT size, DWRITE_TEXT_RANGE range)
1384 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1385 struct layout_range_attr_value value;
1387 TRACE("(%p)->(%.2f %s)\n", This, size, debugstr_range(&range));
1389 value.range = range;
1390 value.u.fontsize = size;
1391 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_FONTSIZE, &value);
1394 static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout2 *iface, BOOL underline, DWRITE_TEXT_RANGE range)
1396 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1397 struct layout_range_attr_value value;
1399 TRACE("(%p)->(%d %s)\n", This, underline, debugstr_range(&range));
1401 value.range = range;
1402 value.u.underline = underline;
1403 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_UNDERLINE, &value);
1406 static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout2 *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
1408 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1409 struct layout_range_attr_value value;
1411 TRACE("(%p)->(%d %s)\n", This, strikethrough, debugstr_range(&range));
1413 value.range = range;
1414 value.u.underline = strikethrough;
1415 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_STRIKETHROUGH, &value);
1418 static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout2 *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
1420 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1421 struct layout_range_attr_value value;
1423 TRACE("(%p)->(%p %s)\n", This, effect, debugstr_range(&range));
1425 value.range = range;
1426 value.u.effect = effect;
1427 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_EFFECT, &value);
1430 static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout2 *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE range)
1432 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1433 struct layout_range_attr_value value;
1435 TRACE("(%p)->(%p %s)\n", This, object, debugstr_range(&range));
1437 value.range = range;
1438 value.u.object = object;
1439 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_INLINE, &value);
1442 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout2 *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
1444 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1445 FIXME("(%p)->(%p %s): stub\n", This, typography, debugstr_range(&range));
1446 return E_NOTIMPL;
1449 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout2 *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
1451 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1452 struct layout_range_attr_value value;
1454 TRACE("(%p)->(%s %s)\n", This, debugstr_w(locale), debugstr_range(&range));
1456 if (!locale || strlenW(locale) > LOCALE_NAME_MAX_LENGTH-1)
1457 return E_INVALIDARG;
1459 value.range = range;
1460 value.u.locale = locale;
1461 return set_layout_range_attr(This, LAYOUT_RANGE_ATTR_LOCALE, &value);
1464 static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout2 *iface)
1466 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1467 TRACE("(%p)\n", This);
1468 return This->maxwidth;
1471 static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout2 *iface)
1473 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1474 TRACE("(%p)\n", This);
1475 return This->maxheight;
1478 static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout2 *iface, UINT32 position,
1479 IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *r)
1481 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1482 struct layout_range *range;
1484 TRACE("(%p)->(%u %p %p)\n", This, position, collection, r);
1486 range = get_layout_range_by_pos(This, position);
1487 *collection = range ? range->collection : NULL;
1488 if (*collection)
1489 IDWriteFontCollection_AddRef(*collection);
1491 return return_range(range, r);
1494 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout2 *iface,
1495 UINT32 position, UINT32 *length, DWRITE_TEXT_RANGE *r)
1497 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1498 TRACE("(%p)->(%d %p %p)\n", This, position, length, r);
1499 return get_string_attribute_length(This, LAYOUT_RANGE_ATTR_FONTFAMILY, position, length, r);
1502 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout2 *iface,
1503 UINT32 position, WCHAR *name, UINT32 length, DWRITE_TEXT_RANGE *r)
1505 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1506 TRACE("(%p)->(%u %p %u %p)\n", This, position, name, length, r);
1507 return get_string_attribute_value(This, LAYOUT_RANGE_ATTR_FONTFAMILY, position, name, length, r);
1510 static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout2 *iface,
1511 UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *r)
1513 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1514 struct layout_range *range;
1516 TRACE("(%p)->(%u %p %p)\n", This, position, weight, r);
1518 if (position >= This->len)
1519 return S_OK;
1521 range = get_layout_range_by_pos(This, position);
1522 *weight = range->weight;
1524 return return_range(range, r);
1527 static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout2 *iface,
1528 UINT32 position, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *r)
1530 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1531 struct layout_range *range;
1533 TRACE("(%p)->(%u %p %p)\n", This, position, style, r);
1535 if (position >= This->len)
1536 return S_OK;
1538 range = get_layout_range_by_pos(This, position);
1539 *style = range->style;
1541 return return_range(range, r);
1544 static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout2 *iface,
1545 UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *r)
1547 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1548 struct layout_range *range;
1550 TRACE("(%p)->(%u %p %p)\n", This, position, stretch, r);
1552 if (position >= This->len)
1553 return S_OK;
1555 range = get_layout_range_by_pos(This, position);
1556 *stretch = range->stretch;
1558 return return_range(range, r);
1561 static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout2 *iface,
1562 UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *r)
1564 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1565 struct layout_range *range;
1567 TRACE("(%p)->(%u %p %p)\n", This, position, size, r);
1569 if (position >= This->len)
1570 return S_OK;
1572 range = get_layout_range_by_pos(This, position);
1573 *size = range->fontsize;
1575 return return_range(range, r);
1578 static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout2 *iface,
1579 UINT32 position, BOOL *underline, DWRITE_TEXT_RANGE *r)
1581 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1582 struct layout_range *range;
1584 TRACE("(%p)->(%u %p %p)\n", This, position, underline, r);
1586 if (position >= This->len)
1587 return S_OK;
1589 range = get_layout_range_by_pos(This, position);
1590 *underline = range->underline;
1592 return return_range(range, r);
1595 static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout2 *iface,
1596 UINT32 position, BOOL *strikethrough, DWRITE_TEXT_RANGE *r)
1598 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1599 struct layout_range *range;
1601 TRACE("(%p)->(%u %p %p)\n", This, position, strikethrough, r);
1603 if (position >= This->len)
1604 return S_OK;
1606 range = get_layout_range_by_pos(This, position);
1607 *strikethrough = range->strikethrough;
1609 return return_range(range, r);
1612 static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2 *iface,
1613 UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *r)
1615 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1616 struct layout_range *range;
1618 TRACE("(%p)->(%u %p %p)\n", This, position, effect, r);
1620 if (position >= This->len)
1621 return S_OK;
1623 range = get_layout_range_by_pos(This, position);
1624 *effect = range->effect;
1625 if (*effect)
1626 IUnknown_AddRef(*effect);
1628 return return_range(range, r);
1631 static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout2 *iface,
1632 UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *r)
1634 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1635 struct layout_range *range;
1637 TRACE("(%p)->(%u %p %p)\n", This, position, object, r);
1639 range = get_layout_range_by_pos(This, position);
1640 *object = range ? range->object : NULL;
1641 if (*object)
1642 IDWriteInlineObject_AddRef(*object);
1644 return return_range(range, r);
1647 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout2 *iface,
1648 UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
1650 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1651 FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
1652 return E_NOTIMPL;
1655 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2 *iface,
1656 UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *r)
1658 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1659 TRACE("(%p)->(%u %p %p)\n", This, position, length, r);
1660 return get_string_attribute_length(This, LAYOUT_RANGE_ATTR_LOCALE, position, length, r);
1663 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout2 *iface,
1664 UINT32 position, WCHAR* locale, UINT32 length, DWRITE_TEXT_RANGE *r)
1666 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1667 TRACE("(%p)->(%u %p %u %p)\n", This, position, locale, length, r);
1668 return get_string_attribute_value(This, LAYOUT_RANGE_ATTR_LOCALE, position, locale, length, r);
1671 static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
1672 void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
1674 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1675 FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
1676 return E_NOTIMPL;
1679 static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout2 *iface,
1680 DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
1682 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1683 FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
1684 return E_NOTIMPL;
1687 static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout2 *iface, DWRITE_TEXT_METRICS *metrics)
1689 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1690 FIXME("(%p)->(%p): stub\n", This, metrics);
1691 return E_NOTIMPL;
1694 static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout2 *iface, DWRITE_OVERHANG_METRICS *overhangs)
1696 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1697 FIXME("(%p)->(%p): stub\n", This, overhangs);
1698 return E_NOTIMPL;
1701 static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout2 *iface,
1702 DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32 *count)
1704 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1705 HRESULT hr;
1707 TRACE("(%p)->(%p %u %p)\n", This, metrics, max_count, count);
1709 hr = layout_compute(This);
1710 if (FAILED(hr))
1711 return hr;
1713 if (metrics)
1714 memcpy(metrics, This->clusters, sizeof(DWRITE_CLUSTER_METRICS)*min(max_count, This->clusters_count));
1716 *count = This->clusters_count;
1717 return max_count < This->clusters_count ? S_OK : E_NOT_SUFFICIENT_BUFFER;
1720 static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout2 *iface, FLOAT* min_width)
1722 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1723 FIXME("(%p)->(%p): stub\n", This, min_width);
1724 return E_NOTIMPL;
1727 static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout2 *iface,
1728 FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
1730 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1731 FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
1732 return E_NOTIMPL;
1735 static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout2 *iface,
1736 UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
1738 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1739 FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
1740 return E_NOTIMPL;
1743 static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout2 *iface,
1744 UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
1745 DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
1747 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1748 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
1749 max_metricscount, actual_metricscount);
1750 return E_NOTIMPL;
1753 static HRESULT WINAPI dwritetextlayout1_SetPairKerning(IDWriteTextLayout2 *iface, BOOL is_pairkerning_enabled,
1754 DWRITE_TEXT_RANGE range)
1756 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1757 FIXME("(%p)->(%d %s): stub\n", This, is_pairkerning_enabled, debugstr_range(&range));
1758 return E_NOTIMPL;
1761 static HRESULT WINAPI dwritetextlayout1_GetPairKerning(IDWriteTextLayout2 *iface, UINT32 position, BOOL *is_pairkerning_enabled,
1762 DWRITE_TEXT_RANGE *range)
1764 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1765 FIXME("(%p)->(%p %p): stub\n", This, is_pairkerning_enabled, range);
1766 return E_NOTIMPL;
1769 static HRESULT WINAPI dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2 *iface, FLOAT leading_spacing, FLOAT trailing_spacing,
1770 FLOAT minimum_advance_width, DWRITE_TEXT_RANGE range)
1772 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1773 FIXME("(%p)->(%f %f %f %s): stub\n", This, leading_spacing, trailing_spacing, minimum_advance_width, debugstr_range(&range));
1774 return E_NOTIMPL;
1777 static HRESULT WINAPI dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2 *iface, UINT32 position, FLOAT* leading_spacing,
1778 FLOAT* trailing_spacing, FLOAT* minimum_advance_width, DWRITE_TEXT_RANGE *range)
1780 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1781 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, position, leading_spacing, trailing_spacing, minimum_advance_width, range);
1782 return E_NOTIMPL;
1785 static HRESULT WINAPI dwritetextlayout2_GetMetrics(IDWriteTextLayout2 *iface, DWRITE_TEXT_METRICS1 *metrics)
1787 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1788 FIXME("(%p)->(%p): stub\n", This, metrics);
1789 return E_NOTIMPL;
1792 static HRESULT WINAPI dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout2 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
1794 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1795 FIXME("(%p)->(%d): stub\n", This, orientation);
1796 return E_NOTIMPL;
1799 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextlayout2_GetVerticalGlyphOrientation(IDWriteTextLayout2 *iface)
1801 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1802 FIXME("(%p): stub\n", This);
1803 return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
1806 static HRESULT WINAPI dwritetextlayout2_SetLastLineWrapping(IDWriteTextLayout2 *iface, BOOL lastline_wrapping_enabled)
1808 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1809 FIXME("(%p)->(%d): stub\n", This, lastline_wrapping_enabled);
1810 return E_NOTIMPL;
1813 static BOOL WINAPI dwritetextlayout2_GetLastLineWrapping(IDWriteTextLayout2 *iface)
1815 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1816 FIXME("(%p): stub\n", This);
1817 return FALSE;
1820 static HRESULT WINAPI dwritetextlayout2_SetOpticalAlignment(IDWriteTextLayout2 *iface, DWRITE_OPTICAL_ALIGNMENT alignment)
1822 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1823 FIXME("(%p)->(%d): stub\n", This, alignment);
1824 return E_NOTIMPL;
1827 static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextlayout2_GetOpticalAlignment(IDWriteTextLayout2 *iface)
1829 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1830 FIXME("(%p): stub\n", This);
1831 return DWRITE_OPTICAL_ALIGNMENT_NONE;
1834 static HRESULT WINAPI dwritetextlayout2_SetFontFallback(IDWriteTextLayout2 *iface, IDWriteFontFallback *fallback)
1836 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1837 FIXME("(%p)->(%p): stub\n", This, fallback);
1838 return E_NOTIMPL;
1841 static HRESULT WINAPI dwritetextlayout2_GetFontFallback(IDWriteTextLayout2 *iface, IDWriteFontFallback **fallback)
1843 struct dwrite_textlayout *This = impl_from_IDWriteTextLayout2(iface);
1844 FIXME("(%p)->(%p): stub\n", This, fallback);
1845 return E_NOTIMPL;
1848 static const IDWriteTextLayout2Vtbl dwritetextlayoutvtbl = {
1849 dwritetextlayout_QueryInterface,
1850 dwritetextlayout_AddRef,
1851 dwritetextlayout_Release,
1852 dwritetextlayout_SetTextAlignment,
1853 dwritetextlayout_SetParagraphAlignment,
1854 dwritetextlayout_SetWordWrapping,
1855 dwritetextlayout_SetReadingDirection,
1856 dwritetextlayout_SetFlowDirection,
1857 dwritetextlayout_SetIncrementalTabStop,
1858 dwritetextlayout_SetTrimming,
1859 dwritetextlayout_SetLineSpacing,
1860 dwritetextlayout_GetTextAlignment,
1861 dwritetextlayout_GetParagraphAlignment,
1862 dwritetextlayout_GetWordWrapping,
1863 dwritetextlayout_GetReadingDirection,
1864 dwritetextlayout_GetFlowDirection,
1865 dwritetextlayout_GetIncrementalTabStop,
1866 dwritetextlayout_GetTrimming,
1867 dwritetextlayout_GetLineSpacing,
1868 dwritetextlayout_GetFontCollection,
1869 dwritetextlayout_GetFontFamilyNameLength,
1870 dwritetextlayout_GetFontFamilyName,
1871 dwritetextlayout_GetFontWeight,
1872 dwritetextlayout_GetFontStyle,
1873 dwritetextlayout_GetFontStretch,
1874 dwritetextlayout_GetFontSize,
1875 dwritetextlayout_GetLocaleNameLength,
1876 dwritetextlayout_GetLocaleName,
1877 dwritetextlayout_SetMaxWidth,
1878 dwritetextlayout_SetMaxHeight,
1879 dwritetextlayout_SetFontCollection,
1880 dwritetextlayout_SetFontFamilyName,
1881 dwritetextlayout_SetFontWeight,
1882 dwritetextlayout_SetFontStyle,
1883 dwritetextlayout_SetFontStretch,
1884 dwritetextlayout_SetFontSize,
1885 dwritetextlayout_SetUnderline,
1886 dwritetextlayout_SetStrikethrough,
1887 dwritetextlayout_SetDrawingEffect,
1888 dwritetextlayout_SetInlineObject,
1889 dwritetextlayout_SetTypography,
1890 dwritetextlayout_SetLocaleName,
1891 dwritetextlayout_GetMaxWidth,
1892 dwritetextlayout_GetMaxHeight,
1893 dwritetextlayout_layout_GetFontCollection,
1894 dwritetextlayout_layout_GetFontFamilyNameLength,
1895 dwritetextlayout_layout_GetFontFamilyName,
1896 dwritetextlayout_layout_GetFontWeight,
1897 dwritetextlayout_layout_GetFontStyle,
1898 dwritetextlayout_layout_GetFontStretch,
1899 dwritetextlayout_layout_GetFontSize,
1900 dwritetextlayout_GetUnderline,
1901 dwritetextlayout_GetStrikethrough,
1902 dwritetextlayout_GetDrawingEffect,
1903 dwritetextlayout_GetInlineObject,
1904 dwritetextlayout_GetTypography,
1905 dwritetextlayout_layout_GetLocaleNameLength,
1906 dwritetextlayout_layout_GetLocaleName,
1907 dwritetextlayout_Draw,
1908 dwritetextlayout_GetLineMetrics,
1909 dwritetextlayout_GetMetrics,
1910 dwritetextlayout_GetOverhangMetrics,
1911 dwritetextlayout_GetClusterMetrics,
1912 dwritetextlayout_DetermineMinWidth,
1913 dwritetextlayout_HitTestPoint,
1914 dwritetextlayout_HitTestTextPosition,
1915 dwritetextlayout_HitTestTextRange,
1916 dwritetextlayout1_SetPairKerning,
1917 dwritetextlayout1_GetPairKerning,
1918 dwritetextlayout1_SetCharacterSpacing,
1919 dwritetextlayout1_GetCharacterSpacing,
1920 dwritetextlayout2_GetMetrics,
1921 dwritetextlayout2_SetVerticalGlyphOrientation,
1922 dwritetextlayout2_GetVerticalGlyphOrientation,
1923 dwritetextlayout2_SetLastLineWrapping,
1924 dwritetextlayout2_GetLastLineWrapping,
1925 dwritetextlayout2_SetOpticalAlignment,
1926 dwritetextlayout2_GetOpticalAlignment,
1927 dwritetextlayout2_SetFontFallback,
1928 dwritetextlayout2_GetFontFallback
1931 static HRESULT WINAPI dwritetextlayout_sink_QueryInterface(IDWriteTextAnalysisSink *iface,
1932 REFIID riid, void **obj)
1934 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) || IsEqualIID(riid, &IID_IUnknown)) {
1935 *obj = iface;
1936 IDWriteTextAnalysisSink_AddRef(iface);
1937 return S_OK;
1940 *obj = NULL;
1941 return E_NOINTERFACE;
1944 static ULONG WINAPI dwritetextlayout_sink_AddRef(IDWriteTextAnalysisSink *iface)
1946 return 2;
1949 static ULONG WINAPI dwritetextlayout_sink_Release(IDWriteTextAnalysisSink *iface)
1951 return 1;
1954 static HRESULT WINAPI dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysisSink *iface,
1955 UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* sa)
1957 struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface);
1958 struct layout_run *run;
1960 TRACE("%u %u script=%d\n", position, length, sa->script);
1962 run = alloc_layout_run();
1963 if (!run)
1964 return E_OUTOFMEMORY;
1966 run->descr.string = &layout->str[position];
1967 run->descr.stringLength = length;
1968 run->descr.textPosition = position;
1969 run->sa = *sa;
1970 list_add_head(&layout->runs, &run->entry);
1971 return S_OK;
1974 static HRESULT WINAPI dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalysisSink *iface,
1975 UINT32 position, UINT32 length, DWRITE_LINE_BREAKPOINT const* breakpoints)
1977 struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface);
1979 if (position + length > layout->len)
1980 return E_FAIL;
1982 memcpy(&layout->nominal_breakpoints[position], breakpoints, length*sizeof(DWRITE_LINE_BREAKPOINT));
1983 return S_OK;
1986 static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink *iface, UINT32 position,
1987 UINT32 length, UINT8 explicitLevel, UINT8 resolvedLevel)
1989 struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink(iface);
1990 struct layout_run *cur;
1992 LIST_FOR_EACH_ENTRY(cur, &layout->runs, struct layout_run, entry) {
1993 struct layout_run *run, *run2;
1995 /* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */
1996 if (position < cur->descr.textPosition || position > cur->descr.textPosition + cur->descr.stringLength)
1997 continue;
1999 /* full hit - just set run level */
2000 if (cur->descr.textPosition == position && cur->descr.stringLength == length) {
2001 cur->run.bidiLevel = resolvedLevel;
2002 break;
2005 /* current run is fully covered, move to next one */
2006 if (cur->descr.textPosition == position && cur->descr.stringLength < length) {
2007 cur->run.bidiLevel = resolvedLevel;
2008 position += cur->descr.stringLength;
2009 length -= cur->descr.stringLength;
2010 continue;
2013 /* now starting point is in a run, so it splits it */
2014 run = alloc_layout_run();
2015 if (!run)
2016 return E_OUTOFMEMORY;
2018 *run = *cur;
2019 run->descr.textPosition = position;
2020 run->descr.stringLength = cur->descr.stringLength - position + cur->descr.textPosition;
2021 run->descr.string = &layout->str[position];
2022 run->run.bidiLevel = resolvedLevel;
2023 cur->descr.stringLength -= position - cur->descr.textPosition;
2025 list_add_after(&cur->entry, &run->entry);
2027 if (position + length == run->descr.textPosition + run->descr.stringLength)
2028 break;
2030 /* split second time */
2031 run2 = alloc_layout_run();
2032 if (!run2)
2033 return E_OUTOFMEMORY;
2035 *run2 = *cur;
2036 run2->descr.textPosition = run->descr.textPosition + run->descr.stringLength;
2037 run2->descr.stringLength = cur->descr.textPosition + cur->descr.stringLength - position - length;
2038 run2->descr.string = &layout->str[run2->descr.textPosition];
2039 run->descr.stringLength -= run2->descr.stringLength;
2041 list_add_after(&run->entry, &run2->entry);
2042 break;
2045 return S_OK;
2048 static HRESULT WINAPI dwritetextlayout_sink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface,
2049 UINT32 position, UINT32 length, IDWriteNumberSubstitution* substitution)
2051 return E_NOTIMPL;
2054 static const IDWriteTextAnalysisSinkVtbl dwritetextlayoutsinkvtbl = {
2055 dwritetextlayout_sink_QueryInterface,
2056 dwritetextlayout_sink_AddRef,
2057 dwritetextlayout_sink_Release,
2058 dwritetextlayout_sink_SetScriptAnalysis,
2059 dwritetextlayout_sink_SetLineBreakpoints,
2060 dwritetextlayout_sink_SetBidiLevel,
2061 dwritetextlayout_sink_SetNumberSubstitution
2064 static HRESULT WINAPI dwritetextlayout_source_QueryInterface(IDWriteTextAnalysisSource *iface,
2065 REFIID riid, void **obj)
2067 if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSource) ||
2068 IsEqualIID(riid, &IID_IUnknown))
2070 *obj = iface;
2071 IDWriteTextAnalysisSource_AddRef(iface);
2072 return S_OK;
2075 *obj = NULL;
2076 return E_NOINTERFACE;
2079 static ULONG WINAPI dwritetextlayout_source_AddRef(IDWriteTextAnalysisSource *iface)
2081 return 2;
2084 static ULONG WINAPI dwritetextlayout_source_Release(IDWriteTextAnalysisSource *iface)
2086 return 1;
2089 static HRESULT WINAPI dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnalysisSource *iface,
2090 UINT32 position, WCHAR const** text, UINT32* text_len)
2092 struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSource(iface);
2094 TRACE("(%p)->(%u %p %p)\n", layout, position, text, text_len);
2096 if (position < layout->len) {
2097 *text = &layout->str[position];
2098 *text_len = layout->len - position;
2100 else {
2101 *text = NULL;
2102 *text_len = 0;
2105 return S_OK;
2108 static HRESULT WINAPI dwritetextlayout_source_GetTextBeforePosition(IDWriteTextAnalysisSource *iface,
2109 UINT32 position, WCHAR const** text, UINT32* text_len)
2111 FIXME("%u %p %p: stub\n", position, text, text_len);
2112 return E_NOTIMPL;
2115 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_source_GetParagraphReadingDirection(IDWriteTextAnalysisSource *iface)
2117 struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSource(iface);
2118 return IDWriteTextLayout2_GetReadingDirection(&layout->IDWriteTextLayout2_iface);
2121 static HRESULT WINAPI dwritetextlayout_source_GetLocaleName(IDWriteTextAnalysisSource *iface,
2122 UINT32 position, UINT32* text_len, WCHAR const** locale)
2124 FIXME("%u %p %p: stub\n", position, text_len, locale);
2125 return E_NOTIMPL;
2128 static HRESULT WINAPI dwritetextlayout_source_GetNumberSubstitution(IDWriteTextAnalysisSource *iface,
2129 UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
2131 FIXME("%u %p %p: stub\n", position, text_len, substitution);
2132 return E_NOTIMPL;
2135 static const IDWriteTextAnalysisSourceVtbl dwritetextlayoutsourcevtbl = {
2136 dwritetextlayout_source_QueryInterface,
2137 dwritetextlayout_source_AddRef,
2138 dwritetextlayout_source_Release,
2139 dwritetextlayout_source_GetTextAtPosition,
2140 dwritetextlayout_source_GetTextBeforePosition,
2141 dwritetextlayout_source_GetParagraphReadingDirection,
2142 dwritetextlayout_source_GetLocaleName,
2143 dwritetextlayout_source_GetNumberSubstitution
2146 static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
2148 UINT32 len;
2149 HRESULT hr;
2151 layout->format.weight = IDWriteTextFormat_GetFontWeight(format);
2152 layout->format.style = IDWriteTextFormat_GetFontStyle(format);
2153 layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
2154 layout->format.fontsize= IDWriteTextFormat_GetFontSize(format);
2155 layout->format.textalignment = IDWriteTextFormat_GetTextAlignment(format);
2156 layout->format.paralign = IDWriteTextFormat_GetParagraphAlignment(format);
2157 layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
2158 layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
2159 layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
2160 hr = IDWriteTextFormat_GetLineSpacing(format, &layout->format.spacingmethod,
2161 &layout->format.spacing, &layout->format.baseline);
2162 if (FAILED(hr))
2163 return hr;
2165 hr = IDWriteTextFormat_GetTrimming(format, &layout->format.trimming, &layout->format.trimmingsign);
2166 if (FAILED(hr))
2167 return hr;
2169 /* locale name and length */
2170 len = IDWriteTextFormat_GetLocaleNameLength(format);
2171 layout->format.locale = heap_alloc((len+1)*sizeof(WCHAR));
2172 if (!layout->format.locale)
2173 return E_OUTOFMEMORY;
2175 hr = IDWriteTextFormat_GetLocaleName(format, layout->format.locale, len+1);
2176 if (FAILED(hr))
2177 return hr;
2178 layout->format.locale_len = len;
2180 /* font family name and length */
2181 len = IDWriteTextFormat_GetFontFamilyNameLength(format);
2182 layout->format.family_name = heap_alloc((len+1)*sizeof(WCHAR));
2183 if (!layout->format.family_name)
2184 return E_OUTOFMEMORY;
2186 hr = IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, len+1);
2187 if (FAILED(hr))
2188 return hr;
2189 layout->format.family_len = len;
2191 return IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
2194 static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, struct dwrite_textlayout *layout)
2196 DWRITE_TEXT_RANGE r = { 0, len };
2197 struct layout_range *range;
2198 HRESULT hr;
2200 layout->IDWriteTextLayout2_iface.lpVtbl = &dwritetextlayoutvtbl;
2201 layout->IDWriteTextAnalysisSink_iface.lpVtbl = &dwritetextlayoutsinkvtbl;
2202 layout->IDWriteTextAnalysisSource_iface.lpVtbl = &dwritetextlayoutsourcevtbl;
2203 layout->ref = 1;
2204 layout->len = len;
2205 layout->maxwidth = maxwidth;
2206 layout->maxheight = maxheight;
2207 layout->recompute = TRUE;
2208 layout->nominal_breakpoints = NULL;
2209 layout->actual_breakpoints = NULL;
2210 layout->clusters_count = 0;
2211 layout->clusters = NULL;
2212 list_init(&layout->runs);
2213 list_init(&layout->ranges);
2214 memset(&layout->format, 0, sizeof(layout->format));
2216 layout->gdicompatible = FALSE;
2217 layout->pixels_per_dip = 0.0;
2218 layout->use_gdi_natural = FALSE;
2219 memset(&layout->transform, 0, sizeof(layout->transform));
2221 layout->str = heap_strdupnW(str, len);
2222 if (len && !layout->str) {
2223 hr = E_OUTOFMEMORY;
2224 goto fail;
2227 hr = layout_format_from_textformat(layout, format);
2228 if (FAILED(hr))
2229 goto fail;
2231 range = alloc_layout_range(layout, &r);
2232 if (!range) {
2233 hr = E_OUTOFMEMORY;
2234 goto fail;
2237 list_add_head(&layout->ranges, &range->entry);
2238 return S_OK;
2240 fail:
2241 IDWriteTextLayout2_Release(&layout->IDWriteTextLayout2_iface);
2242 return hr;
2245 HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight, IDWriteTextLayout **ret)
2247 struct dwrite_textlayout *layout;
2248 HRESULT hr;
2250 *ret = NULL;
2252 layout = heap_alloc(sizeof(struct dwrite_textlayout));
2253 if (!layout) return E_OUTOFMEMORY;
2255 hr = init_textlayout(str, len, format, maxwidth, maxheight, layout);
2256 if (hr == S_OK)
2257 *ret = (IDWriteTextLayout*)&layout->IDWriteTextLayout2_iface;
2259 return hr;
2262 HRESULT create_gdicompat_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, FLOAT maxwidth, FLOAT maxheight,
2263 FLOAT pixels_per_dip, const DWRITE_MATRIX *transform, BOOL use_gdi_natural, IDWriteTextLayout **ret)
2265 struct dwrite_textlayout *layout;
2266 HRESULT hr;
2268 *ret = NULL;
2270 layout = heap_alloc(sizeof(struct dwrite_textlayout));
2271 if (!layout) return E_OUTOFMEMORY;
2273 hr = init_textlayout(str, len, format, maxwidth, maxheight, layout);
2274 if (hr == S_OK) {
2275 /* set gdi-specific properties */
2276 layout->gdicompatible = TRUE;
2277 layout->pixels_per_dip = pixels_per_dip;
2278 layout->use_gdi_natural = use_gdi_natural;
2279 layout->transform = transform ? *transform : identity;
2281 *ret = (IDWriteTextLayout*)&layout->IDWriteTextLayout2_iface;
2284 return hr;
2287 static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
2289 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2291 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2293 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
2294 *obj = iface;
2295 IDWriteInlineObject_AddRef(iface);
2296 return S_OK;
2299 *obj = NULL;
2300 return E_NOINTERFACE;
2304 static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
2306 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2307 ULONG ref = InterlockedIncrement(&This->ref);
2308 TRACE("(%p)->(%d)\n", This, ref);
2309 return ref;
2312 static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
2314 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2315 ULONG ref = InterlockedDecrement(&This->ref);
2317 TRACE("(%p)->(%d)\n", This, ref);
2319 if (!ref)
2320 heap_free(This);
2322 return ref;
2325 static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
2326 FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *drawing_effect)
2328 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2329 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This, context, renderer, originX, originY, is_sideways, is_rtl, drawing_effect);
2330 return E_NOTIMPL;
2333 static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *metrics)
2335 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2336 FIXME("(%p)->(%p): stub\n", This, metrics);
2337 return E_NOTIMPL;
2340 static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
2342 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2343 FIXME("(%p)->(%p): stub\n", This, overhangs);
2344 return E_NOTIMPL;
2347 static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
2348 DWRITE_BREAK_CONDITION *after)
2350 struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
2352 TRACE("(%p)->(%p %p)\n", This, before, after);
2354 *before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
2355 return S_OK;
2358 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
2359 dwritetrimmingsign_QueryInterface,
2360 dwritetrimmingsign_AddRef,
2361 dwritetrimmingsign_Release,
2362 dwritetrimmingsign_Draw,
2363 dwritetrimmingsign_GetMetrics,
2364 dwritetrimmingsign_GetOverhangMetrics,
2365 dwritetrimmingsign_GetBreakConditions
2368 HRESULT create_trimmingsign(IDWriteInlineObject **sign)
2370 struct dwrite_trimmingsign *This;
2372 *sign = NULL;
2374 This = heap_alloc(sizeof(struct dwrite_trimmingsign));
2375 if (!This) return E_OUTOFMEMORY;
2377 This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
2378 This->ref = 1;
2380 *sign = &This->IDWriteInlineObject_iface;
2382 return S_OK;
2385 static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat1 *iface, REFIID riid, void **obj)
2387 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2389 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2391 if (IsEqualIID(riid, &IID_IDWriteTextFormat1) ||
2392 IsEqualIID(riid, &IID_IDWriteTextFormat) ||
2393 IsEqualIID(riid, &IID_IUnknown))
2395 *obj = iface;
2396 IDWriteTextFormat1_AddRef(iface);
2397 return S_OK;
2400 *obj = NULL;
2402 return E_NOINTERFACE;
2405 static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat1 *iface)
2407 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2408 ULONG ref = InterlockedIncrement(&This->ref);
2409 TRACE("(%p)->(%d)\n", This, ref);
2410 return ref;
2413 static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat1 *iface)
2415 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2416 ULONG ref = InterlockedDecrement(&This->ref);
2418 TRACE("(%p)->(%d)\n", This, ref);
2420 if (!ref)
2422 release_format_data(&This->format);
2423 heap_free(This);
2426 return ref;
2429 static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat1 *iface, DWRITE_TEXT_ALIGNMENT alignment)
2431 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2432 TRACE("(%p)->(%d)\n", This, alignment);
2433 This->format.textalignment = alignment;
2434 return S_OK;
2437 static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat1 *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
2439 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2440 TRACE("(%p)->(%d)\n", This, alignment);
2441 This->format.paralign = alignment;
2442 return S_OK;
2445 static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat1 *iface, DWRITE_WORD_WRAPPING wrapping)
2447 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2448 TRACE("(%p)->(%d)\n", This, wrapping);
2449 This->format.wrapping = wrapping;
2450 return S_OK;
2453 static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat1 *iface, DWRITE_READING_DIRECTION direction)
2455 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2456 TRACE("(%p)->(%d)\n", This, direction);
2457 This->format.readingdir = direction;
2458 return S_OK;
2461 static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat1 *iface, DWRITE_FLOW_DIRECTION direction)
2463 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2464 TRACE("(%p)->(%d)\n", This, direction);
2465 This->format.flow = direction;
2466 return S_OK;
2469 static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat1 *iface, FLOAT tabstop)
2471 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2472 FIXME("(%p)->(%f): stub\n", This, tabstop);
2473 return E_NOTIMPL;
2476 static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat1 *iface, DWRITE_TRIMMING const *trimming,
2477 IDWriteInlineObject *trimming_sign)
2479 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2480 TRACE("(%p)->(%p %p)\n", This, trimming, trimming_sign);
2482 This->format.trimming = *trimming;
2483 if (This->format.trimmingsign)
2484 IDWriteInlineObject_Release(This->format.trimmingsign);
2485 This->format.trimmingsign = trimming_sign;
2486 if (This->format.trimmingsign)
2487 IDWriteInlineObject_AddRef(This->format.trimmingsign);
2488 return S_OK;
2491 static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat1 *iface, DWRITE_LINE_SPACING_METHOD method,
2492 FLOAT spacing, FLOAT baseline)
2494 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2495 TRACE("(%p)->(%d %f %f)\n", This, method, spacing, baseline);
2496 This->format.spacingmethod = method;
2497 This->format.spacing = spacing;
2498 This->format.baseline = baseline;
2499 return S_OK;
2502 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat1 *iface)
2504 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2505 TRACE("(%p)\n", This);
2506 return This->format.textalignment;
2509 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat1 *iface)
2511 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2512 TRACE("(%p)\n", This);
2513 return This->format.paralign;
2516 static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat1 *iface)
2518 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2519 TRACE("(%p)\n", This);
2520 return This->format.wrapping;
2523 static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat1 *iface)
2525 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2526 TRACE("(%p)\n", This);
2527 return This->format.readingdir;
2530 static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat1 *iface)
2532 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2533 TRACE("(%p)\n", This);
2534 return This->format.flow;
2537 static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat1 *iface)
2539 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2540 FIXME("(%p): stub\n", This);
2541 return 0.0;
2544 static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat1 *iface, DWRITE_TRIMMING *options,
2545 IDWriteInlineObject **trimming_sign)
2547 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2548 TRACE("(%p)->(%p %p)\n", This, options, trimming_sign);
2550 *options = This->format.trimming;
2551 if ((*trimming_sign = This->format.trimmingsign))
2552 IDWriteInlineObject_AddRef(*trimming_sign);
2554 return S_OK;
2557 static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat1 *iface, DWRITE_LINE_SPACING_METHOD *method,
2558 FLOAT *spacing, FLOAT *baseline)
2560 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2561 TRACE("(%p)->(%p %p %p)\n", This, method, spacing, baseline);
2563 *method = This->format.spacingmethod;
2564 *spacing = This->format.spacing;
2565 *baseline = This->format.baseline;
2566 return S_OK;
2569 static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat1 *iface, IDWriteFontCollection **collection)
2571 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2573 TRACE("(%p)->(%p)\n", This, collection);
2575 *collection = This->format.collection;
2576 IDWriteFontCollection_AddRef(*collection);
2578 return S_OK;
2581 static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat1 *iface)
2583 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2584 TRACE("(%p)\n", This);
2585 return This->format.family_len;
2588 static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat1 *iface, WCHAR *name, UINT32 size)
2590 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2592 TRACE("(%p)->(%p %u)\n", This, name, size);
2594 if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
2595 strcpyW(name, This->format.family_name);
2596 return S_OK;
2599 static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat1 *iface)
2601 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2602 TRACE("(%p)\n", This);
2603 return This->format.weight;
2606 static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat1 *iface)
2608 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2609 TRACE("(%p)\n", This);
2610 return This->format.style;
2613 static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat1 *iface)
2615 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2616 TRACE("(%p)\n", This);
2617 return This->format.stretch;
2620 static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat1 *iface)
2622 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2623 TRACE("(%p)\n", This);
2624 return This->format.fontsize;
2627 static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat1 *iface)
2629 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2630 TRACE("(%p)\n", This);
2631 return This->format.locale_len;
2634 static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat1 *iface, WCHAR *name, UINT32 size)
2636 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2638 TRACE("(%p)->(%p %u)\n", This, name, size);
2640 if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
2641 strcpyW(name, This->format.locale);
2642 return S_OK;
2645 static HRESULT WINAPI dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat1 *iface, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation)
2647 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2648 FIXME("(%p)->(%d): stub\n", This, orientation);
2649 return E_NOTIMPL;
2652 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat1 *iface)
2654 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2655 FIXME("(%p): stub\n", This);
2656 return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
2659 static HRESULT WINAPI dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat1 *iface, BOOL lastline_wrapping_enabled)
2661 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2662 FIXME("(%p)->(%d): stub\n", This, lastline_wrapping_enabled);
2663 return E_NOTIMPL;
2666 static BOOL WINAPI dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat1 *iface)
2668 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2669 FIXME("(%p): stub\n", This);
2670 return FALSE;
2673 static HRESULT WINAPI dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat1 *iface, DWRITE_OPTICAL_ALIGNMENT alignment)
2675 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2676 FIXME("(%p)->(%d): stub\n", This, alignment);
2677 return E_NOTIMPL;
2680 static DWRITE_OPTICAL_ALIGNMENT WINAPI dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat1 *iface)
2682 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2683 FIXME("(%p): stub\n", This);
2684 return DWRITE_OPTICAL_ALIGNMENT_NONE;
2687 static HRESULT WINAPI dwritetextformat1_SetFontFallback(IDWriteTextFormat1 *iface, IDWriteFontFallback *fallback)
2689 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2690 FIXME("(%p)->(%p): stub\n", This, fallback);
2691 return E_NOTIMPL;
2694 static HRESULT WINAPI dwritetextformat1_GetFontFallback(IDWriteTextFormat1 *iface, IDWriteFontFallback **fallback)
2696 struct dwrite_textformat *This = impl_from_IDWriteTextFormat1(iface);
2697 FIXME("(%p)->(%p): stub\n", This, fallback);
2698 return E_NOTIMPL;
2701 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl = {
2702 dwritetextformat_QueryInterface,
2703 dwritetextformat_AddRef,
2704 dwritetextformat_Release,
2705 dwritetextformat_SetTextAlignment,
2706 dwritetextformat_SetParagraphAlignment,
2707 dwritetextformat_SetWordWrapping,
2708 dwritetextformat_SetReadingDirection,
2709 dwritetextformat_SetFlowDirection,
2710 dwritetextformat_SetIncrementalTabStop,
2711 dwritetextformat_SetTrimming,
2712 dwritetextformat_SetLineSpacing,
2713 dwritetextformat_GetTextAlignment,
2714 dwritetextformat_GetParagraphAlignment,
2715 dwritetextformat_GetWordWrapping,
2716 dwritetextformat_GetReadingDirection,
2717 dwritetextformat_GetFlowDirection,
2718 dwritetextformat_GetIncrementalTabStop,
2719 dwritetextformat_GetTrimming,
2720 dwritetextformat_GetLineSpacing,
2721 dwritetextformat_GetFontCollection,
2722 dwritetextformat_GetFontFamilyNameLength,
2723 dwritetextformat_GetFontFamilyName,
2724 dwritetextformat_GetFontWeight,
2725 dwritetextformat_GetFontStyle,
2726 dwritetextformat_GetFontStretch,
2727 dwritetextformat_GetFontSize,
2728 dwritetextformat_GetLocaleNameLength,
2729 dwritetextformat_GetLocaleName,
2730 dwritetextformat1_SetVerticalGlyphOrientation,
2731 dwritetextformat1_GetVerticalGlyphOrientation,
2732 dwritetextformat1_SetLastLineWrapping,
2733 dwritetextformat1_GetLastLineWrapping,
2734 dwritetextformat1_SetOpticalAlignment,
2735 dwritetextformat1_GetOpticalAlignment,
2736 dwritetextformat1_SetFontFallback,
2737 dwritetextformat1_GetFontFallback
2740 HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
2741 DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
2743 struct dwrite_textformat *This;
2745 *format = NULL;
2747 This = heap_alloc(sizeof(struct dwrite_textformat));
2748 if (!This) return E_OUTOFMEMORY;
2750 This->IDWriteTextFormat1_iface.lpVtbl = &dwritetextformatvtbl;
2751 This->ref = 1;
2752 This->format.family_name = heap_strdupW(family_name);
2753 This->format.family_len = strlenW(family_name);
2754 This->format.locale = heap_strdupW(locale);
2755 This->format.locale_len = strlenW(locale);
2756 This->format.weight = weight;
2757 This->format.style = style;
2758 This->format.fontsize = size;
2759 This->format.stretch = stretch;
2760 This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
2761 This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
2762 This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
2763 This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
2764 This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
2765 This->format.spacingmethod = DWRITE_LINE_SPACING_METHOD_DEFAULT;
2766 This->format.spacing = 0.0;
2767 This->format.baseline = 0.0;
2768 This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
2769 This->format.trimming.delimiter = 0;
2770 This->format.trimming.delimiterCount = 0;
2771 This->format.trimmingsign = NULL;
2772 This->format.collection = collection;
2773 IDWriteFontCollection_AddRef(collection);
2775 *format = (IDWriteTextFormat*)&This->IDWriteTextFormat1_iface;
2777 return S_OK;
2780 static HRESULT WINAPI dwritetypography_QueryInterface(IDWriteTypography *iface, REFIID riid, void **obj)
2782 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
2784 TRACE("(%p)->(%s %p)\n", typography, debugstr_guid(riid), obj);
2786 if (IsEqualIID(riid, &IID_IDWriteTypography) || IsEqualIID(riid, &IID_IUnknown)) {
2787 *obj = iface;
2788 IDWriteTypography_AddRef(iface);
2789 return S_OK;
2792 *obj = NULL;
2794 return E_NOINTERFACE;
2797 static ULONG WINAPI dwritetypography_AddRef(IDWriteTypography *iface)
2799 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
2800 ULONG ref = InterlockedIncrement(&typography->ref);
2801 TRACE("(%p)->(%d)\n", typography, ref);
2802 return ref;
2805 static ULONG WINAPI dwritetypography_Release(IDWriteTypography *iface)
2807 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
2808 ULONG ref = InterlockedDecrement(&typography->ref);
2810 TRACE("(%p)->(%d)\n", typography, ref);
2812 if (!ref) {
2813 heap_free(typography->features);
2814 heap_free(typography);
2817 return ref;
2820 static HRESULT WINAPI dwritetypography_AddFontFeature(IDWriteTypography *iface, DWRITE_FONT_FEATURE feature)
2822 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
2824 TRACE("(%p)->(%x %u)\n", typography, feature.nameTag, feature.parameter);
2826 if (typography->count == typography->allocated) {
2827 DWRITE_FONT_FEATURE *ptr = heap_realloc(typography->features, 2*typography->allocated*sizeof(DWRITE_FONT_FEATURE));
2828 if (!ptr)
2829 return E_OUTOFMEMORY;
2831 typography->features = ptr;
2832 typography->allocated *= 2;
2835 typography->features[typography->count++] = feature;
2836 return S_OK;
2839 static UINT32 WINAPI dwritetypography_GetFontFeatureCount(IDWriteTypography *iface)
2841 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
2842 TRACE("(%p)\n", typography);
2843 return typography->count;
2846 static HRESULT WINAPI dwritetypography_GetFontFeature(IDWriteTypography *iface, UINT32 index, DWRITE_FONT_FEATURE *feature)
2848 struct dwrite_typography *typography = impl_from_IDWriteTypography(iface);
2850 TRACE("(%p)->(%u %p)\n", typography, index, feature);
2852 if (index >= typography->count)
2853 return E_INVALIDARG;
2855 *feature = typography->features[index];
2856 return S_OK;
2859 static const IDWriteTypographyVtbl dwritetypographyvtbl = {
2860 dwritetypography_QueryInterface,
2861 dwritetypography_AddRef,
2862 dwritetypography_Release,
2863 dwritetypography_AddFontFeature,
2864 dwritetypography_GetFontFeatureCount,
2865 dwritetypography_GetFontFeature
2868 HRESULT create_typography(IDWriteTypography **ret)
2870 struct dwrite_typography *typography;
2872 *ret = NULL;
2874 typography = heap_alloc(sizeof(*typography));
2875 if (!typography)
2876 return E_OUTOFMEMORY;
2878 typography->IDWriteTypography_iface.lpVtbl = &dwritetypographyvtbl;
2879 typography->ref = 1;
2880 typography->allocated = 2;
2881 typography->count = 0;
2883 typography->features = heap_alloc(typography->allocated*sizeof(DWRITE_FONT_FEATURE));
2884 if (!typography->features) {
2885 heap_free(typography);
2886 return E_OUTOFMEMORY;
2889 *ret = &typography->IDWriteTypography_iface;
2890 return S_OK;