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
28 #include "dwrite_private.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
34 struct dwrite_textformat_data
{
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
;
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_PAIR_KERNING
,
71 LAYOUT_RANGE_ATTR_FONTCOLL
,
72 LAYOUT_RANGE_ATTR_LOCALE
,
73 LAYOUT_RANGE_ATTR_FONTFAMILY
76 struct layout_range_attr_value
{
77 DWRITE_TEXT_RANGE range
;
79 DWRITE_FONT_WEIGHT weight
;
80 DWRITE_FONT_STYLE style
;
81 DWRITE_FONT_STRETCH stretch
;
83 IDWriteInlineObject
*object
;
88 IDWriteFontCollection
*collection
;
90 const WCHAR
*fontfamily
;
96 DWRITE_TEXT_RANGE range
;
97 DWRITE_FONT_WEIGHT weight
;
98 DWRITE_FONT_STYLE style
;
100 DWRITE_FONT_STRETCH stretch
;
101 IDWriteInlineObject
*object
;
106 IDWriteFontCollection
*collection
;
107 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
113 DWRITE_GLYPH_RUN_DESCRIPTION descr
;
114 DWRITE_GLYPH_RUN run
;
115 DWRITE_SCRIPT_ANALYSIS sa
;
119 DWRITE_GLYPH_OFFSET
*offsets
;
122 struct dwrite_textlayout
{
123 IDWriteTextLayout2 IDWriteTextLayout2_iface
;
124 IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface
;
125 IDWriteTextAnalysisSource IDWriteTextAnalysisSource_iface
;
130 struct dwrite_textformat_data format
;
137 DWRITE_LINE_BREAKPOINT
*nominal_breakpoints
;
138 DWRITE_LINE_BREAKPOINT
*actual_breakpoints
;
140 DWRITE_CLUSTER_METRICS
*clusters
;
141 UINT32 clusters_count
;
143 /* gdi-compatible layout specifics */
145 FLOAT pixels_per_dip
;
146 BOOL use_gdi_natural
;
147 DWRITE_MATRIX transform
;
150 struct dwrite_textformat
{
151 IDWriteTextFormat1 IDWriteTextFormat1_iface
;
153 struct dwrite_textformat_data format
;
156 struct dwrite_trimmingsign
{
157 IDWriteInlineObject IDWriteInlineObject_iface
;
161 struct dwrite_typography
{
162 IDWriteTypography IDWriteTypography_iface
;
165 DWRITE_FONT_FEATURE
*features
;
170 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl
;
172 static void release_format_data(struct dwrite_textformat_data
*data
)
174 if (data
->collection
) IDWriteFontCollection_Release(data
->collection
);
175 if (data
->trimmingsign
) IDWriteInlineObject_Release(data
->trimmingsign
);
176 heap_free(data
->family_name
);
177 heap_free(data
->locale
);
180 static inline struct dwrite_textlayout
*impl_from_IDWriteTextLayout2(IDWriteTextLayout2
*iface
)
182 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextLayout2_iface
);
185 static inline struct dwrite_textlayout
*impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink
*iface
)
187 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextAnalysisSink_iface
);
190 static inline struct dwrite_textlayout
*impl_from_IDWriteTextAnalysisSource(IDWriteTextAnalysisSource
*iface
)
192 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextAnalysisSource_iface
);
195 static inline struct dwrite_textformat
*impl_from_IDWriteTextFormat1(IDWriteTextFormat1
*iface
)
197 return CONTAINING_RECORD(iface
, struct dwrite_textformat
, IDWriteTextFormat1_iface
);
200 static inline struct dwrite_textformat
*unsafe_impl_from_IDWriteTextFormat1(IDWriteTextFormat1
*iface
)
202 return iface
->lpVtbl
== &dwritetextformatvtbl
? impl_from_IDWriteTextFormat1(iface
) : NULL
;
205 static inline struct dwrite_trimmingsign
*impl_from_IDWriteInlineObject(IDWriteInlineObject
*iface
)
207 return CONTAINING_RECORD(iface
, struct dwrite_trimmingsign
, IDWriteInlineObject_iface
);
210 static inline struct dwrite_typography
*impl_from_IDWriteTypography(IDWriteTypography
*iface
)
212 return CONTAINING_RECORD(iface
, struct dwrite_typography
, IDWriteTypography_iface
);
215 static inline const char *debugstr_run(const struct layout_run
*run
)
217 return wine_dbg_sprintf("[%u,%u]", run
->descr
.textPosition
, run
->descr
.textPosition
+
218 run
->descr
.stringLength
);
221 static struct layout_run
*alloc_layout_run(void)
223 struct layout_run
*ret
;
225 ret
= heap_alloc(sizeof(*ret
));
226 if (!ret
) return NULL
;
228 ret
->descr
.localeName
= NULL
;
229 ret
->descr
.string
= NULL
;
230 ret
->descr
.stringLength
= 0;
231 ret
->descr
.clusterMap
= NULL
;
232 ret
->descr
.textPosition
= 0;
234 ret
->run
.fontFace
= NULL
;
235 ret
->run
.fontEmSize
= 0.0;
236 ret
->run
.glyphCount
= 0;
237 ret
->run
.glyphIndices
= NULL
;
238 ret
->run
.glyphAdvances
= NULL
;
239 ret
->run
.glyphOffsets
= NULL
;
240 ret
->run
.isSideways
= FALSE
;
241 ret
->run
.bidiLevel
= 0;
243 ret
->sa
.script
= Script_Unknown
;
244 ret
->sa
.shapes
= DWRITE_SCRIPT_SHAPES_DEFAULT
;
247 ret
->clustermap
= NULL
;
248 ret
->advances
= NULL
;
254 static void free_layout_runs(struct dwrite_textlayout
*layout
)
256 struct layout_run
*cur
, *cur2
;
257 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->runs
, struct layout_run
, entry
) {
258 list_remove(&cur
->entry
);
259 if (cur
->run
.fontFace
)
260 IDWriteFontFace_Release(cur
->run
.fontFace
);
261 heap_free(cur
->glyphs
);
262 heap_free(cur
->clustermap
);
263 heap_free(cur
->advances
);
264 heap_free(cur
->offsets
);
269 /* Used to resolve break condition by forcing stronger condition over weaker. */
270 static inline DWRITE_BREAK_CONDITION
override_break_condition(DWRITE_BREAK_CONDITION existingbreak
, DWRITE_BREAK_CONDITION newbreak
)
272 switch (existingbreak
) {
273 case DWRITE_BREAK_CONDITION_NEUTRAL
:
275 case DWRITE_BREAK_CONDITION_CAN_BREAK
:
276 return newbreak
== DWRITE_BREAK_CONDITION_NEUTRAL
? existingbreak
: newbreak
;
277 /* let's keep stronger conditions as is */
278 case DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
:
279 case DWRITE_BREAK_CONDITION_MUST_BREAK
:
282 ERR("unknown break condition %d\n", existingbreak
);
285 return existingbreak
;
288 /* Actual breakpoint data gets updated with break condition required by inline object set for range 'cur'. */
289 static HRESULT
layout_update_breakpoints_range(struct dwrite_textlayout
*layout
, const struct layout_range
*cur
)
291 DWRITE_BREAK_CONDITION before
, after
;
295 hr
= IDWriteInlineObject_GetBreakConditions(cur
->object
, &before
, &after
);
299 if (!layout
->actual_breakpoints
) {
300 layout
->actual_breakpoints
= heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
301 if (!layout
->actual_breakpoints
)
302 return E_OUTOFMEMORY
;
304 memcpy(layout
->actual_breakpoints
, layout
->nominal_breakpoints
, sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
306 for (i
= cur
->range
.startPosition
; i
< cur
->range
.length
+ cur
->range
.startPosition
; i
++) {
307 UINT32 j
= i
+ cur
->range
.startPosition
;
310 layout
->actual_breakpoints
[j
].breakConditionBefore
= layout
->actual_breakpoints
[j
-1].breakConditionAfter
=
311 override_break_condition(layout
->actual_breakpoints
[j
-1].breakConditionAfter
, before
);
313 layout
->actual_breakpoints
[j
].breakConditionBefore
= before
;
315 layout
->actual_breakpoints
[j
].breakConditionAfter
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
318 layout
->actual_breakpoints
[j
].isWhitespace
= 0;
319 layout
->actual_breakpoints
[j
].isSoftHyphen
= 0;
321 if (i
== cur
->range
.length
- 1) {
322 layout
->actual_breakpoints
[j
].breakConditionBefore
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
323 if (j
< layout
->len
- 1)
324 layout
->actual_breakpoints
[j
].breakConditionAfter
= layout
->actual_breakpoints
[j
+1].breakConditionAfter
=
325 override_break_condition(layout
->actual_breakpoints
[j
+1].breakConditionAfter
, before
);
327 layout
->actual_breakpoints
[j
].breakConditionAfter
= before
;
334 static struct layout_range
*get_layout_range_by_pos(struct dwrite_textlayout
*layout
, UINT32 pos
);
336 static void init_cluster_metrics(const struct layout_run
*run
, DWRITE_CLUSTER_METRICS
*metrics
)
338 metrics
->width
= 0.0;
340 metrics
->canWrapLineAfter
= FALSE
;
341 metrics
->isWhitespace
= FALSE
;
342 metrics
->isNewline
= FALSE
;
343 metrics
->isSoftHyphen
= FALSE
;
344 metrics
->isRightToLeft
= run
->run
.bidiLevel
& 1;
345 metrics
->padding
= 0;
350 All clusters in a 'run' will be added to 'layout' data, starting at index pointed to by 'cluster'.
351 On return 'cluster' is updated to point to next metrics struct to be filled in on next call.
354 static void layout_set_cluster_metrics(struct dwrite_textlayout
*layout
, const struct layout_run
*run
, UINT32
*cluster
)
356 DWRITE_CLUSTER_METRICS
*metrics
= &layout
->clusters
[*cluster
];
360 glyph
= run
->descr
.clusterMap
[0];
361 init_cluster_metrics(run
, metrics
);
363 for (i
= 0; i
< run
->descr
.stringLength
; i
++) {
364 BOOL newcluster
= glyph
!= run
->descr
.clusterMap
[i
];
366 /* add new cluster on starting glyph change or simply when run is over */
367 if (newcluster
|| i
== run
->descr
.stringLength
- 1) {
368 UINT8 breakcondition
;
371 for (j
= glyph
; j
< run
->descr
.clusterMap
[i
]; j
++)
372 metrics
->width
+= run
->run
.glyphAdvances
[j
];
374 /* FIXME: also set isWhitespace, isNewline and isSoftHyphen */
375 breakcondition
= newcluster
? layout
->nominal_breakpoints
[i
].breakConditionBefore
:
376 layout
->nominal_breakpoints
[i
].breakConditionAfter
;
377 metrics
->canWrapLineAfter
= breakcondition
== DWRITE_BREAK_CONDITION_CAN_BREAK
||
378 breakcondition
== DWRITE_BREAK_CONDITION_MUST_BREAK
;
380 /* advance to next cluster */
381 glyph
= run
->descr
.clusterMap
[i
];
384 init_cluster_metrics(run
, metrics
);
391 static HRESULT
layout_compute_runs(struct dwrite_textlayout
*layout
)
393 IDWriteTextAnalyzer
*analyzer
;
394 struct layout_range
*range
;
395 struct layout_run
*run
;
399 free_layout_runs(layout
);
400 heap_free(layout
->clusters
);
401 layout
->clusters_count
= 0;
402 layout
->clusters
= heap_alloc(layout
->len
*sizeof(DWRITE_CLUSTER_METRICS
));
403 if (!layout
->clusters
)
404 return E_OUTOFMEMORY
;
406 hr
= get_textanalyzer(&analyzer
);
410 LIST_FOR_EACH_ENTRY(range
, &layout
->ranges
, struct layout_range
, entry
) {
411 /* inline objects override actual text in a range */
413 hr
= layout_update_breakpoints_range(layout
, range
);
419 /* initial splitting by script */
420 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
421 range
->range
.startPosition
, range
->range
.length
, &layout
->IDWriteTextAnalysisSink_iface
);
425 /* this splits it further */
426 hr
= IDWriteTextAnalyzer_AnalyzeBidi(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
427 range
->range
.startPosition
, range
->range
.length
, &layout
->IDWriteTextAnalysisSink_iface
);
433 LIST_FOR_EACH_ENTRY(run
, &layout
->runs
, struct layout_run
, entry
) {
434 DWRITE_SHAPING_GLYPH_PROPERTIES
*glyph_props
= NULL
;
435 DWRITE_SHAPING_TEXT_PROPERTIES
*text_props
= NULL
;
436 IDWriteFontFamily
*family
;
437 UINT32 index
, max_count
;
441 range
= get_layout_range_by_pos(layout
, run
->descr
.textPosition
);
443 hr
= IDWriteFontCollection_FindFamilyName(range
->collection
, range
->fontfamily
, &index
, &exists
);
444 if (FAILED(hr
) || !exists
) {
445 WARN("%s: family %s not found in collection %p\n", debugstr_run(run
), debugstr_w(range
->fontfamily
), range
->collection
);
449 hr
= IDWriteFontCollection_GetFontFamily(range
->collection
, index
, &family
);
453 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, range
->weight
, range
->stretch
, range
->style
, &font
);
454 IDWriteFontFamily_Release(family
);
456 WARN("%s: failed to get a matching font\n", debugstr_run(run
));
460 hr
= IDWriteFont_CreateFontFace(font
, &run
->run
.fontFace
);
461 IDWriteFont_Release(font
);
465 run
->run
.fontEmSize
= range
->fontsize
;
466 run
->descr
.localeName
= range
->locale
;
467 run
->clustermap
= heap_alloc(run
->descr
.stringLength
*sizeof(UINT16
));
469 max_count
= 3*run
->descr
.stringLength
/2 + 16;
470 run
->glyphs
= heap_alloc(max_count
*sizeof(UINT16
));
471 if (!run
->clustermap
|| !run
->glyphs
)
474 text_props
= heap_alloc(run
->descr
.stringLength
*sizeof(DWRITE_SHAPING_TEXT_PROPERTIES
));
475 glyph_props
= heap_alloc(max_count
*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES
));
476 if (!text_props
|| !glyph_props
)
480 hr
= IDWriteTextAnalyzer_GetGlyphs(analyzer
, run
->descr
.string
, run
->descr
.stringLength
,
481 run
->run
.fontFace
, FALSE
/* FIXME */, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
,
482 NULL
/* FIXME */, NULL
, NULL
, 0, max_count
, run
->clustermap
, text_props
, run
->glyphs
, glyph_props
,
483 &run
->run
.glyphCount
);
484 if (hr
== E_NOT_SUFFICIENT_BUFFER
) {
485 heap_free(run
->glyphs
);
486 heap_free(glyph_props
);
488 max_count
= run
->run
.glyphCount
;
490 run
->glyphs
= heap_alloc(max_count
*sizeof(UINT16
));
491 glyph_props
= heap_alloc(max_count
*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES
));
492 if (!run
->glyphs
|| !glyph_props
)
502 heap_free(text_props
);
503 heap_free(glyph_props
);
504 WARN("%s: shaping failed 0x%08x\n", debugstr_run(run
), hr
);
508 run
->run
.glyphIndices
= run
->glyphs
;
509 run
->descr
.clusterMap
= run
->clustermap
;
511 run
->advances
= heap_alloc(run
->run
.glyphCount
*sizeof(FLOAT
));
512 run
->offsets
= heap_alloc(run
->run
.glyphCount
*sizeof(DWRITE_GLYPH_OFFSET
));
513 if (!run
->advances
|| !run
->offsets
)
516 /* now set advances and offsets */
517 if (layout
->gdicompatible
)
518 hr
= IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer
, run
->descr
.string
, run
->descr
.clusterMap
,
519 text_props
, run
->descr
.stringLength
, run
->run
.glyphIndices
, glyph_props
, run
->run
.glyphCount
,
520 run
->run
.fontFace
, run
->run
.fontEmSize
, layout
->pixels_per_dip
, &layout
->transform
, layout
->use_gdi_natural
,
521 FALSE
/* FIXME */, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
, NULL
, NULL
, 0,
522 run
->advances
, run
->offsets
);
524 hr
= IDWriteTextAnalyzer_GetGlyphPlacements(analyzer
, run
->descr
.string
, run
->descr
.clusterMap
, text_props
,
525 run
->descr
.stringLength
, run
->run
.glyphIndices
, glyph_props
, run
->run
.glyphCount
, run
->run
.fontFace
,
526 run
->run
.fontEmSize
, FALSE
/* FIXME */, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
,
527 NULL
, NULL
, 0, run
->advances
, run
->offsets
);
529 heap_free(text_props
);
530 heap_free(glyph_props
);
532 WARN("%s: failed to get glyph placement info, 0x%08x\n", debugstr_run(run
), hr
);
534 run
->run
.glyphAdvances
= run
->advances
;
535 run
->run
.glyphOffsets
= run
->offsets
;
537 /* now set cluster metrics */
538 layout_set_cluster_metrics(layout
, run
, &cluster
);
543 heap_free(text_props
);
544 heap_free(glyph_props
);
545 heap_free(run
->clustermap
);
546 heap_free(run
->glyphs
);
547 heap_free(run
->advances
);
548 heap_free(run
->offsets
);
549 run
->advances
= NULL
;
551 run
->clustermap
= run
->glyphs
= NULL
;
557 layout
->clusters_count
= cluster
+ 1;
559 IDWriteTextAnalyzer_Release(analyzer
);
563 static HRESULT
layout_compute(struct dwrite_textlayout
*layout
)
567 if (!layout
->recompute
)
570 /* nominal breakpoints are evaluated only once, because string never changes */
571 if (!layout
->nominal_breakpoints
) {
572 IDWriteTextAnalyzer
*analyzer
;
575 layout
->nominal_breakpoints
= heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
576 if (!layout
->nominal_breakpoints
)
577 return E_OUTOFMEMORY
;
579 hr
= get_textanalyzer(&analyzer
);
583 hr
= IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
584 0, layout
->len
, &layout
->IDWriteTextAnalysisSink_iface
);
585 IDWriteTextAnalyzer_Release(analyzer
);
588 hr
= layout_compute_runs(layout
);
590 if (TRACE_ON(dwrite
)) {
591 struct layout_run
*cur
;
593 LIST_FOR_EACH_ENTRY(cur
, &layout
->runs
, struct layout_run
, entry
) {
594 TRACE("run [%u,%u], len %u, bidilevel %u\n", cur
->descr
.textPosition
, cur
->descr
.textPosition
+cur
->descr
.stringLength
-1,
595 cur
->descr
.stringLength
, cur
->run
.bidiLevel
);
599 layout
->recompute
= FALSE
;
603 /* To be used in IDWriteTextLayout methods to validate and fix passed range */
604 static inline BOOL
validate_text_range(struct dwrite_textlayout
*layout
, DWRITE_TEXT_RANGE
*r
)
606 if (r
->startPosition
>= layout
->len
)
609 if (r
->startPosition
+ r
->length
> layout
->len
)
610 r
->length
= layout
->len
- r
->startPosition
;
615 static BOOL
is_same_layout_attrvalue(struct layout_range
const *range
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
618 case LAYOUT_RANGE_ATTR_WEIGHT
:
619 return range
->weight
== value
->u
.weight
;
620 case LAYOUT_RANGE_ATTR_STYLE
:
621 return range
->style
== value
->u
.style
;
622 case LAYOUT_RANGE_ATTR_STRETCH
:
623 return range
->stretch
== value
->u
.stretch
;
624 case LAYOUT_RANGE_ATTR_FONTSIZE
:
625 return range
->fontsize
== value
->u
.fontsize
;
626 case LAYOUT_RANGE_ATTR_INLINE
:
627 return range
->object
== value
->u
.object
;
628 case LAYOUT_RANGE_ATTR_EFFECT
:
629 return range
->effect
== value
->u
.effect
;
630 case LAYOUT_RANGE_ATTR_UNDERLINE
:
631 return range
->underline
== value
->u
.underline
;
632 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
633 return range
->strikethrough
== value
->u
.strikethrough
;
634 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
635 return range
->pair_kerning
== value
->u
.pair_kerning
;
636 case LAYOUT_RANGE_ATTR_FONTCOLL
:
637 return range
->collection
== value
->u
.collection
;
638 case LAYOUT_RANGE_ATTR_LOCALE
:
639 return strcmpW(range
->locale
, value
->u
.locale
) == 0;
640 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
641 return strcmpW(range
->fontfamily
, value
->u
.fontfamily
) == 0;
649 static inline BOOL
is_same_layout_attributes(struct layout_range
const *left
, struct layout_range
const *right
)
651 return left
->weight
== right
->weight
&&
652 left
->style
== right
->style
&&
653 left
->stretch
== right
->stretch
&&
654 left
->fontsize
== right
->fontsize
&&
655 left
->object
== right
->object
&&
656 left
->effect
== right
->effect
&&
657 left
->underline
== right
->underline
&&
658 left
->strikethrough
== right
->strikethrough
&&
659 left
->pair_kerning
== right
->pair_kerning
&&
660 left
->collection
== right
->collection
&&
661 !strcmpW(left
->locale
, right
->locale
) &&
662 !strcmpW(left
->fontfamily
, right
->fontfamily
);
665 static inline BOOL
is_same_text_range(const DWRITE_TEXT_RANGE
*left
, const DWRITE_TEXT_RANGE
*right
)
667 return left
->startPosition
== right
->startPosition
&& left
->length
== right
->length
;
670 /* Allocates range and inits it with default values from text format. */
671 static struct layout_range
*alloc_layout_range(struct dwrite_textlayout
*layout
, const DWRITE_TEXT_RANGE
*r
)
673 struct layout_range
*range
;
675 range
= heap_alloc(sizeof(*range
));
676 if (!range
) return NULL
;
679 range
->weight
= layout
->format
.weight
;
680 range
->style
= layout
->format
.style
;
681 range
->stretch
= layout
->format
.stretch
;
682 range
->fontsize
= layout
->format
.fontsize
;
683 range
->object
= NULL
;
684 range
->effect
= NULL
;
685 range
->underline
= FALSE
;
686 range
->strikethrough
= FALSE
;
687 range
->pair_kerning
= FALSE
;
689 range
->fontfamily
= heap_strdupW(layout
->format
.family_name
);
690 if (!range
->fontfamily
) {
695 range
->collection
= layout
->format
.collection
;
696 if (range
->collection
)
697 IDWriteFontCollection_AddRef(range
->collection
);
698 strcpyW(range
->locale
, layout
->format
.locale
);
703 static struct layout_range
*alloc_layout_range_from(struct layout_range
*from
, const DWRITE_TEXT_RANGE
*r
)
705 struct layout_range
*range
;
707 range
= heap_alloc(sizeof(*range
));
708 if (!range
) return NULL
;
713 range
->fontfamily
= heap_strdupW(from
->fontfamily
);
714 if (!range
->fontfamily
) {
719 /* update refcounts */
721 IDWriteInlineObject_AddRef(range
->object
);
723 IUnknown_AddRef(range
->effect
);
724 if (range
->collection
)
725 IDWriteFontCollection_AddRef(range
->collection
);
730 static void free_layout_range(struct layout_range
*range
)
735 IDWriteInlineObject_Release(range
->object
);
737 IUnknown_Release(range
->effect
);
738 if (range
->collection
)
739 IDWriteFontCollection_Release(range
->collection
);
740 heap_free(range
->fontfamily
);
744 static void free_layout_ranges_list(struct dwrite_textlayout
*layout
)
746 struct layout_range
*cur
, *cur2
;
747 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->ranges
, struct layout_range
, entry
) {
748 list_remove(&cur
->entry
);
749 free_layout_range(cur
);
753 static struct layout_range
*find_outer_range(struct dwrite_textlayout
*layout
, const DWRITE_TEXT_RANGE
*range
)
755 struct layout_range
*cur
;
757 LIST_FOR_EACH_ENTRY(cur
, &layout
->ranges
, struct layout_range
, entry
) {
759 if (cur
->range
.startPosition
> range
->startPosition
)
762 if ((cur
->range
.startPosition
+ cur
->range
.length
< range
->startPosition
+ range
->length
) &&
763 (range
->startPosition
< cur
->range
.startPosition
+ cur
->range
.length
))
765 if (cur
->range
.startPosition
+ cur
->range
.length
>= range
->startPosition
+ range
->length
)
772 static struct layout_range
*get_layout_range_by_pos(struct dwrite_textlayout
*layout
, UINT32 pos
)
774 struct layout_range
*cur
;
776 LIST_FOR_EACH_ENTRY(cur
, &layout
->ranges
, struct layout_range
, entry
) {
777 DWRITE_TEXT_RANGE
*r
= &cur
->range
;
778 if (r
->startPosition
<= pos
&& pos
< r
->startPosition
+ r
->length
)
785 static inline BOOL
set_layout_range_iface_attr(IUnknown
**dest
, IUnknown
*value
)
787 if (*dest
== value
) return FALSE
;
790 IUnknown_Release(*dest
);
793 IUnknown_AddRef(*dest
);
798 static BOOL
set_layout_range_attrval(struct layout_range
*dest
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
800 BOOL changed
= FALSE
;
803 case LAYOUT_RANGE_ATTR_WEIGHT
:
804 changed
= dest
->weight
!= value
->u
.weight
;
805 dest
->weight
= value
->u
.weight
;
807 case LAYOUT_RANGE_ATTR_STYLE
:
808 changed
= dest
->style
!= value
->u
.style
;
809 dest
->style
= value
->u
.style
;
811 case LAYOUT_RANGE_ATTR_STRETCH
:
812 changed
= dest
->stretch
!= value
->u
.stretch
;
813 dest
->stretch
= value
->u
.stretch
;
815 case LAYOUT_RANGE_ATTR_FONTSIZE
:
816 changed
= dest
->fontsize
!= value
->u
.fontsize
;
817 dest
->fontsize
= value
->u
.fontsize
;
819 case LAYOUT_RANGE_ATTR_INLINE
:
820 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->object
, (IUnknown
*)value
->u
.object
);
822 case LAYOUT_RANGE_ATTR_EFFECT
:
823 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->effect
, (IUnknown
*)value
->u
.effect
);
825 case LAYOUT_RANGE_ATTR_UNDERLINE
:
826 changed
= dest
->underline
!= value
->u
.underline
;
827 dest
->underline
= value
->u
.underline
;
829 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
830 changed
= dest
->strikethrough
!= value
->u
.strikethrough
;
831 dest
->strikethrough
= value
->u
.strikethrough
;
833 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
834 changed
= dest
->pair_kerning
!= value
->u
.pair_kerning
;
835 dest
->pair_kerning
= value
->u
.pair_kerning
;
837 case LAYOUT_RANGE_ATTR_FONTCOLL
:
838 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->collection
, (IUnknown
*)value
->u
.collection
);
840 case LAYOUT_RANGE_ATTR_LOCALE
:
841 changed
= strcmpW(dest
->locale
, value
->u
.locale
) != 0;
843 strcpyW(dest
->locale
, value
->u
.locale
);
845 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
846 changed
= strcmpW(dest
->fontfamily
, value
->u
.fontfamily
) != 0;
848 heap_free(dest
->fontfamily
);
849 dest
->fontfamily
= heap_strdupW(value
->u
.fontfamily
);
859 static inline BOOL
is_in_layout_range(const DWRITE_TEXT_RANGE
*outer
, const DWRITE_TEXT_RANGE
*inner
)
861 return (inner
->startPosition
>= outer
->startPosition
) &&
862 (inner
->startPosition
+ inner
->length
<= outer
->startPosition
+ outer
->length
);
865 static inline HRESULT
return_range(const struct layout_range
*range
, DWRITE_TEXT_RANGE
*r
)
867 if (r
) *r
= range
->range
;
871 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
872 static HRESULT
set_layout_range_attr(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
874 struct layout_range
*outer
, *right
, *left
, *cur
;
875 struct list
*ranges
= &layout
->ranges
;
876 BOOL changed
= FALSE
;
879 if (!validate_text_range(layout
, &value
->range
))
882 /* If new range is completely within existing range, split existing range in two */
883 if ((outer
= find_outer_range(layout
, &value
->range
))) {
885 /* no need to add same range */
886 if (is_same_layout_attrvalue(outer
, attr
, value
))
889 /* for matching range bounds just replace data */
890 if (is_same_text_range(&outer
->range
, &value
->range
)) {
891 changed
= set_layout_range_attrval(outer
, attr
, value
);
895 /* add new range to the left */
896 if (value
->range
.startPosition
== outer
->range
.startPosition
) {
897 left
= alloc_layout_range_from(outer
, &value
->range
);
898 if (!left
) return E_OUTOFMEMORY
;
900 changed
= set_layout_range_attrval(left
, attr
, value
);
901 list_add_before(&outer
->entry
, &left
->entry
);
902 outer
->range
.startPosition
+= value
->range
.length
;
903 outer
->range
.length
-= value
->range
.length
;
907 /* add new range to the right */
908 if (value
->range
.startPosition
+ value
->range
.length
== outer
->range
.startPosition
+ outer
->range
.length
) {
909 right
= alloc_layout_range_from(outer
, &value
->range
);
910 if (!right
) return E_OUTOFMEMORY
;
912 changed
= set_layout_range_attrval(right
, attr
, value
);
913 list_add_after(&outer
->entry
, &right
->entry
);
914 outer
->range
.length
-= value
->range
.length
;
918 r
.startPosition
= value
->range
.startPosition
+ value
->range
.length
;
919 r
.length
= outer
->range
.length
+ outer
->range
.startPosition
- r
.startPosition
;
922 right
= alloc_layout_range_from(outer
, &r
);
923 /* new range in the middle */
924 cur
= alloc_layout_range_from(outer
, &value
->range
);
925 if (!right
|| !cur
) {
926 free_layout_range(right
);
927 free_layout_range(cur
);
928 return E_OUTOFMEMORY
;
931 /* reuse container range as a left part */
932 outer
->range
.length
= value
->range
.startPosition
- outer
->range
.startPosition
;
935 set_layout_range_attrval(cur
, attr
, value
);
937 list_add_after(&outer
->entry
, &cur
->entry
);
938 list_add_after(&cur
->entry
, &right
->entry
);
943 /* Now it's only possible that given range contains some existing ranges, fully or partially.
944 Update all of them. */
945 left
= get_layout_range_by_pos(layout
, value
->range
.startPosition
);
946 if (left
->range
.startPosition
== value
->range
.startPosition
)
947 changed
= set_layout_range_attrval(left
, attr
, value
);
948 else /* need to split */ {
949 r
.startPosition
= value
->range
.startPosition
;
950 r
.length
= left
->range
.length
- value
->range
.startPosition
+ left
->range
.startPosition
;
951 left
->range
.length
-= r
.length
;
952 cur
= alloc_layout_range_from(left
, &r
);
953 changed
= set_layout_range_attrval(cur
, attr
, value
);
954 list_add_after(&left
->entry
, &cur
->entry
);
956 cur
= LIST_ENTRY(list_next(ranges
, &left
->entry
), struct layout_range
, entry
);
958 /* for all existing ranges covered by new one update value */
959 while (is_in_layout_range(&value
->range
, &cur
->range
)) {
960 changed
= set_layout_range_attrval(cur
, attr
, value
);
961 cur
= LIST_ENTRY(list_next(ranges
, &cur
->entry
), struct layout_range
, entry
);
964 /* it's possible rightmost range intersects */
965 if (cur
&& (cur
->range
.startPosition
< value
->range
.startPosition
+ value
->range
.length
)) {
966 r
.startPosition
= cur
->range
.startPosition
;
967 r
.length
= value
->range
.startPosition
+ value
->range
.length
- cur
->range
.startPosition
;
968 left
= alloc_layout_range_from(cur
, &r
);
969 changed
= set_layout_range_attrval(left
, attr
, value
);
970 cur
->range
.startPosition
+= left
->range
.length
;
971 cur
->range
.length
-= left
->range
.length
;
972 list_add_before(&cur
->entry
, &left
->entry
);
977 struct list
*next
, *i
;
979 layout
->recompute
= TRUE
;
980 i
= list_head(ranges
);
981 while ((next
= list_next(ranges
, i
))) {
982 struct layout_range
*next_range
= LIST_ENTRY(next
, struct layout_range
, entry
);
984 cur
= LIST_ENTRY(i
, struct layout_range
, entry
);
985 if (is_same_layout_attributes(cur
, next_range
)) {
986 /* remove similar range */
987 cur
->range
.length
+= next_range
->range
.length
;
989 free_layout_range(next_range
);
992 i
= list_next(ranges
, i
);
999 static inline const WCHAR
*get_string_attribute_ptr(struct layout_range
*range
, enum layout_range_attr_kind kind
)
1004 case LAYOUT_RANGE_ATTR_LOCALE
:
1005 str
= range
->locale
;
1007 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1008 str
= range
->fontfamily
;
1017 static HRESULT
get_string_attribute_length(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind kind
, UINT32 position
,
1018 UINT32
*length
, DWRITE_TEXT_RANGE
*r
)
1020 struct layout_range
*range
;
1023 range
= get_layout_range_by_pos(layout
, position
);
1029 str
= get_string_attribute_ptr(range
, kind
);
1030 *length
= strlenW(str
);
1031 return return_range(range
, r
);
1034 static HRESULT
get_string_attribute_value(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind kind
, UINT32 position
,
1035 WCHAR
*ret
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1037 struct layout_range
*range
;
1041 return E_INVALIDARG
;
1044 range
= get_layout_range_by_pos(layout
, position
);
1046 return E_INVALIDARG
;
1048 str
= get_string_attribute_ptr(range
, kind
);
1049 if (length
< strlenW(str
) + 1)
1050 return E_NOT_SUFFICIENT_BUFFER
;
1053 return return_range(range
, r
);
1056 static HRESULT WINAPI
dwritetextlayout_QueryInterface(IDWriteTextLayout2
*iface
, REFIID riid
, void **obj
)
1058 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1060 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1062 if (IsEqualIID(riid
, &IID_IDWriteTextLayout2
) ||
1063 IsEqualIID(riid
, &IID_IDWriteTextLayout1
) ||
1064 IsEqualIID(riid
, &IID_IDWriteTextLayout
) ||
1065 IsEqualIID(riid
, &IID_IDWriteTextFormat
) ||
1066 IsEqualIID(riid
, &IID_IUnknown
))
1069 IDWriteTextLayout2_AddRef(iface
);
1075 return E_NOINTERFACE
;
1078 static ULONG WINAPI
dwritetextlayout_AddRef(IDWriteTextLayout2
*iface
)
1080 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1081 ULONG ref
= InterlockedIncrement(&This
->ref
);
1082 TRACE("(%p)->(%d)\n", This
, ref
);
1086 static ULONG WINAPI
dwritetextlayout_Release(IDWriteTextLayout2
*iface
)
1088 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1089 ULONG ref
= InterlockedDecrement(&This
->ref
);
1091 TRACE("(%p)->(%d)\n", This
, ref
);
1094 free_layout_ranges_list(This
);
1095 free_layout_runs(This
);
1096 release_format_data(&This
->format
);
1097 heap_free(This
->nominal_breakpoints
);
1098 heap_free(This
->actual_breakpoints
);
1099 heap_free(This
->clusters
);
1100 heap_free(This
->str
);
1107 static HRESULT WINAPI
dwritetextlayout_SetTextAlignment(IDWriteTextLayout2
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
1109 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1110 FIXME("(%p)->(%d): stub\n", This
, alignment
);
1114 static HRESULT WINAPI
dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout2
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
1116 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1117 FIXME("(%p)->(%d): stub\n", This
, alignment
);
1121 static HRESULT WINAPI
dwritetextlayout_SetWordWrapping(IDWriteTextLayout2
*iface
, DWRITE_WORD_WRAPPING wrapping
)
1123 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1124 FIXME("(%p)->(%d): stub\n", This
, wrapping
);
1128 static HRESULT WINAPI
dwritetextlayout_SetReadingDirection(IDWriteTextLayout2
*iface
, DWRITE_READING_DIRECTION direction
)
1130 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1131 FIXME("(%p)->(%d): stub\n", This
, direction
);
1135 static HRESULT WINAPI
dwritetextlayout_SetFlowDirection(IDWriteTextLayout2
*iface
, DWRITE_FLOW_DIRECTION direction
)
1137 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1138 FIXME("(%p)->(%d): stub\n", This
, direction
);
1142 static HRESULT WINAPI
dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout2
*iface
, FLOAT tabstop
)
1144 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1145 FIXME("(%p)->(%f): stub\n", This
, tabstop
);
1149 static HRESULT WINAPI
dwritetextlayout_SetTrimming(IDWriteTextLayout2
*iface
, DWRITE_TRIMMING
const *trimming
,
1150 IDWriteInlineObject
*trimming_sign
)
1152 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1153 FIXME("(%p)->(%p %p): stub\n", This
, trimming
, trimming_sign
);
1157 static HRESULT WINAPI
dwritetextlayout_SetLineSpacing(IDWriteTextLayout2
*iface
, DWRITE_LINE_SPACING_METHOD spacing
,
1158 FLOAT line_spacing
, FLOAT baseline
)
1160 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1161 FIXME("(%p)->(%d %f %f): stub\n", This
, spacing
, line_spacing
, baseline
);
1165 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextlayout_GetTextAlignment(IDWriteTextLayout2
*iface
)
1167 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1168 TRACE("(%p)\n", This
);
1169 return This
->format
.textalignment
;
1172 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout2
*iface
)
1174 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1175 TRACE("(%p)\n", This
);
1176 return This
->format
.paralign
;
1179 static DWRITE_WORD_WRAPPING WINAPI
dwritetextlayout_GetWordWrapping(IDWriteTextLayout2
*iface
)
1181 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1182 FIXME("(%p): stub\n", This
);
1183 return This
->format
.wrapping
;
1186 static DWRITE_READING_DIRECTION WINAPI
dwritetextlayout_GetReadingDirection(IDWriteTextLayout2
*iface
)
1188 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1189 TRACE("(%p)\n", This
);
1190 return This
->format
.readingdir
;
1193 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextlayout_GetFlowDirection(IDWriteTextLayout2
*iface
)
1195 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1196 TRACE("(%p)\n", This
);
1197 return This
->format
.flow
;
1200 static FLOAT WINAPI
dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout2
*iface
)
1202 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1203 FIXME("(%p): stub\n", This
);
1207 static HRESULT WINAPI
dwritetextlayout_GetTrimming(IDWriteTextLayout2
*iface
, DWRITE_TRIMMING
*options
,
1208 IDWriteInlineObject
**trimming_sign
)
1210 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1212 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
1214 *options
= This
->format
.trimming
;
1215 *trimming_sign
= This
->format
.trimmingsign
;
1217 IDWriteInlineObject_AddRef(*trimming_sign
);
1221 static HRESULT WINAPI
dwritetextlayout_GetLineSpacing(IDWriteTextLayout2
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
1222 FLOAT
*spacing
, FLOAT
*baseline
)
1224 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1226 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
1228 *method
= This
->format
.spacingmethod
;
1229 *spacing
= This
->format
.spacing
;
1230 *baseline
= This
->format
.baseline
;
1234 static HRESULT WINAPI
dwritetextlayout_GetFontCollection(IDWriteTextLayout2
*iface
, IDWriteFontCollection
**collection
)
1236 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1238 TRACE("(%p)->(%p)\n", This
, collection
);
1240 *collection
= This
->format
.collection
;
1242 IDWriteFontCollection_AddRef(*collection
);
1246 static UINT32 WINAPI
dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout2
*iface
)
1248 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1249 TRACE("(%p)\n", This
);
1250 return This
->format
.family_len
;
1253 static HRESULT WINAPI
dwritetextlayout_GetFontFamilyName(IDWriteTextLayout2
*iface
, WCHAR
*name
, UINT32 size
)
1255 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1257 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
1259 if (size
<= This
->format
.family_len
) return E_NOT_SUFFICIENT_BUFFER
;
1260 strcpyW(name
, This
->format
.family_name
);
1264 static DWRITE_FONT_WEIGHT WINAPI
dwritetextlayout_GetFontWeight(IDWriteTextLayout2
*iface
)
1266 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1267 TRACE("(%p)\n", This
);
1268 return This
->format
.weight
;
1271 static DWRITE_FONT_STYLE WINAPI
dwritetextlayout_GetFontStyle(IDWriteTextLayout2
*iface
)
1273 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1274 TRACE("(%p)\n", This
);
1275 return This
->format
.style
;
1278 static DWRITE_FONT_STRETCH WINAPI
dwritetextlayout_GetFontStretch(IDWriteTextLayout2
*iface
)
1280 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1281 TRACE("(%p)\n", This
);
1282 return This
->format
.stretch
;
1285 static FLOAT WINAPI
dwritetextlayout_GetFontSize(IDWriteTextLayout2
*iface
)
1287 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1288 TRACE("(%p)\n", This
);
1289 return This
->format
.fontsize
;
1292 static UINT32 WINAPI
dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout2
*iface
)
1294 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1295 TRACE("(%p)\n", This
);
1296 return This
->format
.locale_len
;
1299 static HRESULT WINAPI
dwritetextlayout_GetLocaleName(IDWriteTextLayout2
*iface
, WCHAR
*name
, UINT32 size
)
1301 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1303 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
1305 if (size
<= This
->format
.locale_len
) return E_NOT_SUFFICIENT_BUFFER
;
1306 strcpyW(name
, This
->format
.locale
);
1310 static HRESULT WINAPI
dwritetextlayout_SetMaxWidth(IDWriteTextLayout2
*iface
, FLOAT maxWidth
)
1312 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1313 TRACE("(%p)->(%.1f)\n", This
, maxWidth
);
1316 return E_INVALIDARG
;
1318 This
->maxwidth
= maxWidth
;
1322 static HRESULT WINAPI
dwritetextlayout_SetMaxHeight(IDWriteTextLayout2
*iface
, FLOAT maxHeight
)
1324 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1325 TRACE("(%p)->(%.1f)\n", This
, maxHeight
);
1327 if (maxHeight
< 0.0)
1328 return E_INVALIDARG
;
1330 This
->maxheight
= maxHeight
;
1334 static HRESULT WINAPI
dwritetextlayout_SetFontCollection(IDWriteTextLayout2
*iface
, IDWriteFontCollection
* collection
, DWRITE_TEXT_RANGE range
)
1336 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1337 struct layout_range_attr_value value
;
1339 TRACE("(%p)->(%p %s)\n", This
, collection
, debugstr_range(&range
));
1341 value
.range
= range
;
1342 value
.u
.collection
= collection
;
1343 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTCOLL
, &value
);
1346 static HRESULT WINAPI
dwritetextlayout_SetFontFamilyName(IDWriteTextLayout2
*iface
, WCHAR
const *name
, DWRITE_TEXT_RANGE range
)
1348 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1349 struct layout_range_attr_value value
;
1351 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(name
), debugstr_range(&range
));
1354 return E_INVALIDARG
;
1356 value
.range
= range
;
1357 value
.u
.fontfamily
= name
;
1358 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, &value
);
1361 static HRESULT WINAPI
dwritetextlayout_SetFontWeight(IDWriteTextLayout2
*iface
, DWRITE_FONT_WEIGHT weight
, DWRITE_TEXT_RANGE range
)
1363 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1364 struct layout_range_attr_value value
;
1366 TRACE("(%p)->(%d %s)\n", This
, weight
, debugstr_range(&range
));
1368 value
.range
= range
;
1369 value
.u
.weight
= weight
;
1370 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_WEIGHT
, &value
);
1373 static HRESULT WINAPI
dwritetextlayout_SetFontStyle(IDWriteTextLayout2
*iface
, DWRITE_FONT_STYLE style
, DWRITE_TEXT_RANGE range
)
1375 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1376 struct layout_range_attr_value value
;
1378 TRACE("(%p)->(%d %s)\n", This
, style
, debugstr_range(&range
));
1380 value
.range
= range
;
1381 value
.u
.style
= style
;
1382 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STYLE
, &value
);
1385 static HRESULT WINAPI
dwritetextlayout_SetFontStretch(IDWriteTextLayout2
*iface
, DWRITE_FONT_STRETCH stretch
, DWRITE_TEXT_RANGE range
)
1387 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1388 struct layout_range_attr_value value
;
1390 TRACE("(%p)->(%d %s)\n", This
, stretch
, debugstr_range(&range
));
1392 value
.range
= range
;
1393 value
.u
.stretch
= stretch
;
1394 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STRETCH
, &value
);
1397 static HRESULT WINAPI
dwritetextlayout_SetFontSize(IDWriteTextLayout2
*iface
, FLOAT size
, DWRITE_TEXT_RANGE range
)
1399 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1400 struct layout_range_attr_value value
;
1402 TRACE("(%p)->(%.2f %s)\n", This
, size
, debugstr_range(&range
));
1404 value
.range
= range
;
1405 value
.u
.fontsize
= size
;
1406 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTSIZE
, &value
);
1409 static HRESULT WINAPI
dwritetextlayout_SetUnderline(IDWriteTextLayout2
*iface
, BOOL underline
, DWRITE_TEXT_RANGE range
)
1411 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1412 struct layout_range_attr_value value
;
1414 TRACE("(%p)->(%d %s)\n", This
, underline
, debugstr_range(&range
));
1416 value
.range
= range
;
1417 value
.u
.underline
= underline
;
1418 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_UNDERLINE
, &value
);
1421 static HRESULT WINAPI
dwritetextlayout_SetStrikethrough(IDWriteTextLayout2
*iface
, BOOL strikethrough
, DWRITE_TEXT_RANGE range
)
1423 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1424 struct layout_range_attr_value value
;
1426 TRACE("(%p)->(%d %s)\n", This
, strikethrough
, debugstr_range(&range
));
1428 value
.range
= range
;
1429 value
.u
.underline
= strikethrough
;
1430 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STRIKETHROUGH
, &value
);
1433 static HRESULT WINAPI
dwritetextlayout_SetDrawingEffect(IDWriteTextLayout2
*iface
, IUnknown
* effect
, DWRITE_TEXT_RANGE range
)
1435 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1436 struct layout_range_attr_value value
;
1438 TRACE("(%p)->(%p %s)\n", This
, effect
, debugstr_range(&range
));
1440 value
.range
= range
;
1441 value
.u
.effect
= effect
;
1442 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_EFFECT
, &value
);
1445 static HRESULT WINAPI
dwritetextlayout_SetInlineObject(IDWriteTextLayout2
*iface
, IDWriteInlineObject
*object
, DWRITE_TEXT_RANGE range
)
1447 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1448 struct layout_range_attr_value value
;
1450 TRACE("(%p)->(%p %s)\n", This
, object
, debugstr_range(&range
));
1452 value
.range
= range
;
1453 value
.u
.object
= object
;
1454 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_INLINE
, &value
);
1457 static HRESULT WINAPI
dwritetextlayout_SetTypography(IDWriteTextLayout2
*iface
, IDWriteTypography
* typography
, DWRITE_TEXT_RANGE range
)
1459 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1460 FIXME("(%p)->(%p %s): stub\n", This
, typography
, debugstr_range(&range
));
1464 static HRESULT WINAPI
dwritetextlayout_SetLocaleName(IDWriteTextLayout2
*iface
, WCHAR
const* locale
, DWRITE_TEXT_RANGE range
)
1466 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1467 struct layout_range_attr_value value
;
1469 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(locale
), debugstr_range(&range
));
1471 if (!locale
|| strlenW(locale
) > LOCALE_NAME_MAX_LENGTH
-1)
1472 return E_INVALIDARG
;
1474 value
.range
= range
;
1475 value
.u
.locale
= locale
;
1476 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_LOCALE
, &value
);
1479 static FLOAT WINAPI
dwritetextlayout_GetMaxWidth(IDWriteTextLayout2
*iface
)
1481 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1482 TRACE("(%p)\n", This
);
1483 return This
->maxwidth
;
1486 static FLOAT WINAPI
dwritetextlayout_GetMaxHeight(IDWriteTextLayout2
*iface
)
1488 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1489 TRACE("(%p)\n", This
);
1490 return This
->maxheight
;
1493 static HRESULT WINAPI
dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout2
*iface
, UINT32 position
,
1494 IDWriteFontCollection
** collection
, DWRITE_TEXT_RANGE
*r
)
1496 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1497 struct layout_range
*range
;
1499 TRACE("(%p)->(%u %p %p)\n", This
, position
, collection
, r
);
1501 range
= get_layout_range_by_pos(This
, position
);
1502 *collection
= range
? range
->collection
: NULL
;
1504 IDWriteFontCollection_AddRef(*collection
);
1506 return return_range(range
, r
);
1509 static HRESULT WINAPI
dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout2
*iface
,
1510 UINT32 position
, UINT32
*length
, DWRITE_TEXT_RANGE
*r
)
1512 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1513 TRACE("(%p)->(%d %p %p)\n", This
, position
, length
, r
);
1514 return get_string_attribute_length(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, position
, length
, r
);
1517 static HRESULT WINAPI
dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout2
*iface
,
1518 UINT32 position
, WCHAR
*name
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1520 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1521 TRACE("(%p)->(%u %p %u %p)\n", This
, position
, name
, length
, r
);
1522 return get_string_attribute_value(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, position
, name
, length
, r
);
1525 static HRESULT WINAPI
dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout2
*iface
,
1526 UINT32 position
, DWRITE_FONT_WEIGHT
*weight
, DWRITE_TEXT_RANGE
*r
)
1528 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1529 struct layout_range
*range
;
1531 TRACE("(%p)->(%u %p %p)\n", This
, position
, weight
, r
);
1533 if (position
>= This
->len
)
1536 range
= get_layout_range_by_pos(This
, position
);
1537 *weight
= range
->weight
;
1539 return return_range(range
, r
);
1542 static HRESULT WINAPI
dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout2
*iface
,
1543 UINT32 position
, DWRITE_FONT_STYLE
*style
, DWRITE_TEXT_RANGE
*r
)
1545 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1546 struct layout_range
*range
;
1548 TRACE("(%p)->(%u %p %p)\n", This
, position
, style
, r
);
1550 if (position
>= This
->len
)
1553 range
= get_layout_range_by_pos(This
, position
);
1554 *style
= range
->style
;
1556 return return_range(range
, r
);
1559 static HRESULT WINAPI
dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout2
*iface
,
1560 UINT32 position
, DWRITE_FONT_STRETCH
*stretch
, DWRITE_TEXT_RANGE
*r
)
1562 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1563 struct layout_range
*range
;
1565 TRACE("(%p)->(%u %p %p)\n", This
, position
, stretch
, r
);
1567 if (position
>= This
->len
)
1570 range
= get_layout_range_by_pos(This
, position
);
1571 *stretch
= range
->stretch
;
1573 return return_range(range
, r
);
1576 static HRESULT WINAPI
dwritetextlayout_layout_GetFontSize(IDWriteTextLayout2
*iface
,
1577 UINT32 position
, FLOAT
*size
, DWRITE_TEXT_RANGE
*r
)
1579 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1580 struct layout_range
*range
;
1582 TRACE("(%p)->(%u %p %p)\n", This
, position
, size
, r
);
1584 if (position
>= This
->len
)
1587 range
= get_layout_range_by_pos(This
, position
);
1588 *size
= range
->fontsize
;
1590 return return_range(range
, r
);
1593 static HRESULT WINAPI
dwritetextlayout_GetUnderline(IDWriteTextLayout2
*iface
,
1594 UINT32 position
, BOOL
*underline
, DWRITE_TEXT_RANGE
*r
)
1596 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1597 struct layout_range
*range
;
1599 TRACE("(%p)->(%u %p %p)\n", This
, position
, underline
, r
);
1601 if (position
>= This
->len
)
1604 range
= get_layout_range_by_pos(This
, position
);
1605 *underline
= range
->underline
;
1607 return return_range(range
, r
);
1610 static HRESULT WINAPI
dwritetextlayout_GetStrikethrough(IDWriteTextLayout2
*iface
,
1611 UINT32 position
, BOOL
*strikethrough
, DWRITE_TEXT_RANGE
*r
)
1613 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1614 struct layout_range
*range
;
1616 TRACE("(%p)->(%u %p %p)\n", This
, position
, strikethrough
, r
);
1618 if (position
>= This
->len
)
1621 range
= get_layout_range_by_pos(This
, position
);
1622 *strikethrough
= range
->strikethrough
;
1624 return return_range(range
, r
);
1627 static HRESULT WINAPI
dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2
*iface
,
1628 UINT32 position
, IUnknown
**effect
, DWRITE_TEXT_RANGE
*r
)
1630 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1631 struct layout_range
*range
;
1633 TRACE("(%p)->(%u %p %p)\n", This
, position
, effect
, r
);
1635 if (position
>= This
->len
)
1638 range
= get_layout_range_by_pos(This
, position
);
1639 *effect
= range
->effect
;
1641 IUnknown_AddRef(*effect
);
1643 return return_range(range
, r
);
1646 static HRESULT WINAPI
dwritetextlayout_GetInlineObject(IDWriteTextLayout2
*iface
,
1647 UINT32 position
, IDWriteInlineObject
**object
, DWRITE_TEXT_RANGE
*r
)
1649 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1650 struct layout_range
*range
;
1652 TRACE("(%p)->(%u %p %p)\n", This
, position
, object
, r
);
1654 range
= get_layout_range_by_pos(This
, position
);
1655 *object
= range
? range
->object
: NULL
;
1657 IDWriteInlineObject_AddRef(*object
);
1659 return return_range(range
, r
);
1662 static HRESULT WINAPI
dwritetextlayout_GetTypography(IDWriteTextLayout2
*iface
,
1663 UINT32 position
, IDWriteTypography
** typography
, DWRITE_TEXT_RANGE
*range
)
1665 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1666 FIXME("(%p)->(%u %p %p): stub\n", This
, position
, typography
, range
);
1670 static HRESULT WINAPI
dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2
*iface
,
1671 UINT32 position
, UINT32
* length
, DWRITE_TEXT_RANGE
*r
)
1673 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1674 TRACE("(%p)->(%u %p %p)\n", This
, position
, length
, r
);
1675 return get_string_attribute_length(This
, LAYOUT_RANGE_ATTR_LOCALE
, position
, length
, r
);
1678 static HRESULT WINAPI
dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout2
*iface
,
1679 UINT32 position
, WCHAR
* locale
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1681 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1682 TRACE("(%p)->(%u %p %u %p)\n", This
, position
, locale
, length
, r
);
1683 return get_string_attribute_value(This
, LAYOUT_RANGE_ATTR_LOCALE
, position
, locale
, length
, r
);
1686 static HRESULT WINAPI
dwritetextlayout_Draw(IDWriteTextLayout2
*iface
,
1687 void *context
, IDWriteTextRenderer
* renderer
, FLOAT originX
, FLOAT originY
)
1689 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1690 FIXME("(%p)->(%p %p %f %f): stub\n", This
, context
, renderer
, originX
, originY
);
1694 static HRESULT WINAPI
dwritetextlayout_GetLineMetrics(IDWriteTextLayout2
*iface
,
1695 DWRITE_LINE_METRICS
*metrics
, UINT32 max_count
, UINT32
*actual_count
)
1697 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1698 FIXME("(%p)->(%p %u %p): stub\n", This
, metrics
, max_count
, actual_count
);
1702 static HRESULT WINAPI
dwritetextlayout_GetMetrics(IDWriteTextLayout2
*iface
, DWRITE_TEXT_METRICS
*metrics
)
1704 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1705 FIXME("(%p)->(%p): stub\n", This
, metrics
);
1709 static HRESULT WINAPI
dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout2
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
1711 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1712 FIXME("(%p)->(%p): stub\n", This
, overhangs
);
1716 static HRESULT WINAPI
dwritetextlayout_GetClusterMetrics(IDWriteTextLayout2
*iface
,
1717 DWRITE_CLUSTER_METRICS
*metrics
, UINT32 max_count
, UINT32
*count
)
1719 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1722 TRACE("(%p)->(%p %u %p)\n", This
, metrics
, max_count
, count
);
1724 hr
= layout_compute(This
);
1729 memcpy(metrics
, This
->clusters
, sizeof(DWRITE_CLUSTER_METRICS
)*min(max_count
, This
->clusters_count
));
1731 *count
= This
->clusters_count
;
1732 return max_count
< This
->clusters_count
? S_OK
: E_NOT_SUFFICIENT_BUFFER
;
1735 static HRESULT WINAPI
dwritetextlayout_DetermineMinWidth(IDWriteTextLayout2
*iface
, FLOAT
* min_width
)
1737 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1738 FIXME("(%p)->(%p): stub\n", This
, min_width
);
1742 static HRESULT WINAPI
dwritetextlayout_HitTestPoint(IDWriteTextLayout2
*iface
,
1743 FLOAT pointX
, FLOAT pointY
, BOOL
* is_trailinghit
, BOOL
* is_inside
, DWRITE_HIT_TEST_METRICS
*metrics
)
1745 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1746 FIXME("(%p)->(%f %f %p %p %p): stub\n", This
, pointX
, pointY
, is_trailinghit
, is_inside
, metrics
);
1750 static HRESULT WINAPI
dwritetextlayout_HitTestTextPosition(IDWriteTextLayout2
*iface
,
1751 UINT32 textPosition
, BOOL is_trailinghit
, FLOAT
* pointX
, FLOAT
* pointY
, DWRITE_HIT_TEST_METRICS
*metrics
)
1753 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1754 FIXME("(%p)->(%u %d %p %p %p): stub\n", This
, textPosition
, is_trailinghit
, pointX
, pointY
, metrics
);
1758 static HRESULT WINAPI
dwritetextlayout_HitTestTextRange(IDWriteTextLayout2
*iface
,
1759 UINT32 textPosition
, UINT32 textLength
, FLOAT originX
, FLOAT originY
,
1760 DWRITE_HIT_TEST_METRICS
*metrics
, UINT32 max_metricscount
, UINT32
* actual_metricscount
)
1762 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1763 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This
, textPosition
, textLength
, originX
, originY
, metrics
,
1764 max_metricscount
, actual_metricscount
);
1768 static HRESULT WINAPI
dwritetextlayout1_SetPairKerning(IDWriteTextLayout2
*iface
, BOOL is_pairkerning_enabled
,
1769 DWRITE_TEXT_RANGE range
)
1771 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1772 struct layout_range_attr_value value
;
1774 TRACE("(%p)->(%d %s)\n", This
, is_pairkerning_enabled
, debugstr_range(&range
));
1776 value
.range
= range
;
1777 value
.u
.pair_kerning
= !!is_pairkerning_enabled
;
1778 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_PAIR_KERNING
, &value
);
1781 static HRESULT WINAPI
dwritetextlayout1_GetPairKerning(IDWriteTextLayout2
*iface
, UINT32 position
, BOOL
*is_pairkerning_enabled
,
1782 DWRITE_TEXT_RANGE
*r
)
1784 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1785 struct layout_range
*range
;
1787 TRACE("(%p)->(%u %p %p)\n", This
, position
, is_pairkerning_enabled
, r
);
1789 if (position
>= This
->len
)
1792 range
= get_layout_range_by_pos(This
, position
);
1793 *is_pairkerning_enabled
= range
->pair_kerning
;
1795 return return_range(range
, r
);
1798 static HRESULT WINAPI
dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2
*iface
, FLOAT leading_spacing
, FLOAT trailing_spacing
,
1799 FLOAT minimum_advance_width
, DWRITE_TEXT_RANGE range
)
1801 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1802 FIXME("(%p)->(%f %f %f %s): stub\n", This
, leading_spacing
, trailing_spacing
, minimum_advance_width
, debugstr_range(&range
));
1806 static HRESULT WINAPI
dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2
*iface
, UINT32 position
, FLOAT
* leading_spacing
,
1807 FLOAT
* trailing_spacing
, FLOAT
* minimum_advance_width
, DWRITE_TEXT_RANGE
*range
)
1809 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1810 FIXME("(%p)->(%u %p %p %p %p): stub\n", This
, position
, leading_spacing
, trailing_spacing
, minimum_advance_width
, range
);
1814 static HRESULT WINAPI
dwritetextlayout2_GetMetrics(IDWriteTextLayout2
*iface
, DWRITE_TEXT_METRICS1
*metrics
)
1816 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1817 FIXME("(%p)->(%p): stub\n", This
, metrics
);
1821 static HRESULT WINAPI
dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout2
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
1823 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1824 FIXME("(%p)->(%d): stub\n", This
, orientation
);
1828 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextlayout2_GetVerticalGlyphOrientation(IDWriteTextLayout2
*iface
)
1830 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1831 FIXME("(%p): stub\n", This
);
1832 return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
1835 static HRESULT WINAPI
dwritetextlayout2_SetLastLineWrapping(IDWriteTextLayout2
*iface
, BOOL lastline_wrapping_enabled
)
1837 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1838 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
1842 static BOOL WINAPI
dwritetextlayout2_GetLastLineWrapping(IDWriteTextLayout2
*iface
)
1844 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1845 FIXME("(%p): stub\n", This
);
1849 static HRESULT WINAPI
dwritetextlayout2_SetOpticalAlignment(IDWriteTextLayout2
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
1851 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1852 FIXME("(%p)->(%d): stub\n", This
, alignment
);
1856 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextlayout2_GetOpticalAlignment(IDWriteTextLayout2
*iface
)
1858 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1859 FIXME("(%p): stub\n", This
);
1860 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
1863 static HRESULT WINAPI
dwritetextlayout2_SetFontFallback(IDWriteTextLayout2
*iface
, IDWriteFontFallback
*fallback
)
1865 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1866 FIXME("(%p)->(%p): stub\n", This
, fallback
);
1870 static HRESULT WINAPI
dwritetextlayout2_GetFontFallback(IDWriteTextLayout2
*iface
, IDWriteFontFallback
**fallback
)
1872 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1873 FIXME("(%p)->(%p): stub\n", This
, fallback
);
1877 static const IDWriteTextLayout2Vtbl dwritetextlayoutvtbl
= {
1878 dwritetextlayout_QueryInterface
,
1879 dwritetextlayout_AddRef
,
1880 dwritetextlayout_Release
,
1881 dwritetextlayout_SetTextAlignment
,
1882 dwritetextlayout_SetParagraphAlignment
,
1883 dwritetextlayout_SetWordWrapping
,
1884 dwritetextlayout_SetReadingDirection
,
1885 dwritetextlayout_SetFlowDirection
,
1886 dwritetextlayout_SetIncrementalTabStop
,
1887 dwritetextlayout_SetTrimming
,
1888 dwritetextlayout_SetLineSpacing
,
1889 dwritetextlayout_GetTextAlignment
,
1890 dwritetextlayout_GetParagraphAlignment
,
1891 dwritetextlayout_GetWordWrapping
,
1892 dwritetextlayout_GetReadingDirection
,
1893 dwritetextlayout_GetFlowDirection
,
1894 dwritetextlayout_GetIncrementalTabStop
,
1895 dwritetextlayout_GetTrimming
,
1896 dwritetextlayout_GetLineSpacing
,
1897 dwritetextlayout_GetFontCollection
,
1898 dwritetextlayout_GetFontFamilyNameLength
,
1899 dwritetextlayout_GetFontFamilyName
,
1900 dwritetextlayout_GetFontWeight
,
1901 dwritetextlayout_GetFontStyle
,
1902 dwritetextlayout_GetFontStretch
,
1903 dwritetextlayout_GetFontSize
,
1904 dwritetextlayout_GetLocaleNameLength
,
1905 dwritetextlayout_GetLocaleName
,
1906 dwritetextlayout_SetMaxWidth
,
1907 dwritetextlayout_SetMaxHeight
,
1908 dwritetextlayout_SetFontCollection
,
1909 dwritetextlayout_SetFontFamilyName
,
1910 dwritetextlayout_SetFontWeight
,
1911 dwritetextlayout_SetFontStyle
,
1912 dwritetextlayout_SetFontStretch
,
1913 dwritetextlayout_SetFontSize
,
1914 dwritetextlayout_SetUnderline
,
1915 dwritetextlayout_SetStrikethrough
,
1916 dwritetextlayout_SetDrawingEffect
,
1917 dwritetextlayout_SetInlineObject
,
1918 dwritetextlayout_SetTypography
,
1919 dwritetextlayout_SetLocaleName
,
1920 dwritetextlayout_GetMaxWidth
,
1921 dwritetextlayout_GetMaxHeight
,
1922 dwritetextlayout_layout_GetFontCollection
,
1923 dwritetextlayout_layout_GetFontFamilyNameLength
,
1924 dwritetextlayout_layout_GetFontFamilyName
,
1925 dwritetextlayout_layout_GetFontWeight
,
1926 dwritetextlayout_layout_GetFontStyle
,
1927 dwritetextlayout_layout_GetFontStretch
,
1928 dwritetextlayout_layout_GetFontSize
,
1929 dwritetextlayout_GetUnderline
,
1930 dwritetextlayout_GetStrikethrough
,
1931 dwritetextlayout_GetDrawingEffect
,
1932 dwritetextlayout_GetInlineObject
,
1933 dwritetextlayout_GetTypography
,
1934 dwritetextlayout_layout_GetLocaleNameLength
,
1935 dwritetextlayout_layout_GetLocaleName
,
1936 dwritetextlayout_Draw
,
1937 dwritetextlayout_GetLineMetrics
,
1938 dwritetextlayout_GetMetrics
,
1939 dwritetextlayout_GetOverhangMetrics
,
1940 dwritetextlayout_GetClusterMetrics
,
1941 dwritetextlayout_DetermineMinWidth
,
1942 dwritetextlayout_HitTestPoint
,
1943 dwritetextlayout_HitTestTextPosition
,
1944 dwritetextlayout_HitTestTextRange
,
1945 dwritetextlayout1_SetPairKerning
,
1946 dwritetextlayout1_GetPairKerning
,
1947 dwritetextlayout1_SetCharacterSpacing
,
1948 dwritetextlayout1_GetCharacterSpacing
,
1949 dwritetextlayout2_GetMetrics
,
1950 dwritetextlayout2_SetVerticalGlyphOrientation
,
1951 dwritetextlayout2_GetVerticalGlyphOrientation
,
1952 dwritetextlayout2_SetLastLineWrapping
,
1953 dwritetextlayout2_GetLastLineWrapping
,
1954 dwritetextlayout2_SetOpticalAlignment
,
1955 dwritetextlayout2_GetOpticalAlignment
,
1956 dwritetextlayout2_SetFontFallback
,
1957 dwritetextlayout2_GetFontFallback
1960 static HRESULT WINAPI
dwritetextlayout_sink_QueryInterface(IDWriteTextAnalysisSink
*iface
,
1961 REFIID riid
, void **obj
)
1963 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
)) {
1965 IDWriteTextAnalysisSink_AddRef(iface
);
1970 return E_NOINTERFACE
;
1973 static ULONG WINAPI
dwritetextlayout_sink_AddRef(IDWriteTextAnalysisSink
*iface
)
1978 static ULONG WINAPI
dwritetextlayout_sink_Release(IDWriteTextAnalysisSink
*iface
)
1983 static HRESULT WINAPI
dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
1984 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
1986 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
1987 struct layout_run
*run
;
1989 TRACE("%u %u script=%d\n", position
, length
, sa
->script
);
1991 run
= alloc_layout_run();
1993 return E_OUTOFMEMORY
;
1995 run
->descr
.string
= &layout
->str
[position
];
1996 run
->descr
.stringLength
= length
;
1997 run
->descr
.textPosition
= position
;
1999 list_add_head(&layout
->runs
, &run
->entry
);
2003 static HRESULT WINAPI
dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
2004 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
2006 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
2008 if (position
+ length
> layout
->len
)
2011 memcpy(&layout
->nominal_breakpoints
[position
], breakpoints
, length
*sizeof(DWRITE_LINE_BREAKPOINT
));
2015 static HRESULT WINAPI
dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
, UINT32 position
,
2016 UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
2018 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
2019 struct layout_run
*cur
;
2021 LIST_FOR_EACH_ENTRY(cur
, &layout
->runs
, struct layout_run
, entry
) {
2022 struct layout_run
*run
, *run2
;
2024 /* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */
2025 if (position
< cur
->descr
.textPosition
|| position
> cur
->descr
.textPosition
+ cur
->descr
.stringLength
)
2028 /* full hit - just set run level */
2029 if (cur
->descr
.textPosition
== position
&& cur
->descr
.stringLength
== length
) {
2030 cur
->run
.bidiLevel
= resolvedLevel
;
2034 /* current run is fully covered, move to next one */
2035 if (cur
->descr
.textPosition
== position
&& cur
->descr
.stringLength
< length
) {
2036 cur
->run
.bidiLevel
= resolvedLevel
;
2037 position
+= cur
->descr
.stringLength
;
2038 length
-= cur
->descr
.stringLength
;
2042 /* now starting point is in a run, so it splits it */
2043 run
= alloc_layout_run();
2045 return E_OUTOFMEMORY
;
2048 run
->descr
.textPosition
= position
;
2049 run
->descr
.stringLength
= cur
->descr
.stringLength
- position
+ cur
->descr
.textPosition
;
2050 run
->descr
.string
= &layout
->str
[position
];
2051 run
->run
.bidiLevel
= resolvedLevel
;
2052 cur
->descr
.stringLength
-= position
- cur
->descr
.textPosition
;
2054 list_add_after(&cur
->entry
, &run
->entry
);
2056 if (position
+ length
== run
->descr
.textPosition
+ run
->descr
.stringLength
)
2059 /* split second time */
2060 run2
= alloc_layout_run();
2062 return E_OUTOFMEMORY
;
2065 run2
->descr
.textPosition
= run
->descr
.textPosition
+ run
->descr
.stringLength
;
2066 run2
->descr
.stringLength
= cur
->descr
.textPosition
+ cur
->descr
.stringLength
- position
- length
;
2067 run2
->descr
.string
= &layout
->str
[run2
->descr
.textPosition
];
2068 run
->descr
.stringLength
-= run2
->descr
.stringLength
;
2070 list_add_after(&run
->entry
, &run2
->entry
);
2077 static HRESULT WINAPI
dwritetextlayout_sink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
2078 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
2083 static const IDWriteTextAnalysisSinkVtbl dwritetextlayoutsinkvtbl
= {
2084 dwritetextlayout_sink_QueryInterface
,
2085 dwritetextlayout_sink_AddRef
,
2086 dwritetextlayout_sink_Release
,
2087 dwritetextlayout_sink_SetScriptAnalysis
,
2088 dwritetextlayout_sink_SetLineBreakpoints
,
2089 dwritetextlayout_sink_SetBidiLevel
,
2090 dwritetextlayout_sink_SetNumberSubstitution
2093 static HRESULT WINAPI
dwritetextlayout_source_QueryInterface(IDWriteTextAnalysisSource
*iface
,
2094 REFIID riid
, void **obj
)
2096 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSource
) ||
2097 IsEqualIID(riid
, &IID_IUnknown
))
2100 IDWriteTextAnalysisSource_AddRef(iface
);
2105 return E_NOINTERFACE
;
2108 static ULONG WINAPI
dwritetextlayout_source_AddRef(IDWriteTextAnalysisSource
*iface
)
2113 static ULONG WINAPI
dwritetextlayout_source_Release(IDWriteTextAnalysisSource
*iface
)
2118 static HRESULT WINAPI
dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
2119 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
2121 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSource(iface
);
2123 TRACE("(%p)->(%u %p %p)\n", layout
, position
, text
, text_len
);
2125 if (position
< layout
->len
) {
2126 *text
= &layout
->str
[position
];
2127 *text_len
= layout
->len
- position
;
2137 static HRESULT WINAPI
dwritetextlayout_source_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
2138 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
2140 FIXME("%u %p %p: stub\n", position
, text
, text_len
);
2144 static DWRITE_READING_DIRECTION WINAPI
dwritetextlayout_source_GetParagraphReadingDirection(IDWriteTextAnalysisSource
*iface
)
2146 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSource(iface
);
2147 return IDWriteTextLayout2_GetReadingDirection(&layout
->IDWriteTextLayout2_iface
);
2150 static HRESULT WINAPI
dwritetextlayout_source_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
2151 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
2153 FIXME("%u %p %p: stub\n", position
, text_len
, locale
);
2157 static HRESULT WINAPI
dwritetextlayout_source_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
2158 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
2160 FIXME("%u %p %p: stub\n", position
, text_len
, substitution
);
2164 static const IDWriteTextAnalysisSourceVtbl dwritetextlayoutsourcevtbl
= {
2165 dwritetextlayout_source_QueryInterface
,
2166 dwritetextlayout_source_AddRef
,
2167 dwritetextlayout_source_Release
,
2168 dwritetextlayout_source_GetTextAtPosition
,
2169 dwritetextlayout_source_GetTextBeforePosition
,
2170 dwritetextlayout_source_GetParagraphReadingDirection
,
2171 dwritetextlayout_source_GetLocaleName
,
2172 dwritetextlayout_source_GetNumberSubstitution
2175 static HRESULT
layout_format_from_textformat(struct dwrite_textlayout
*layout
, IDWriteTextFormat
*format
)
2180 layout
->format
.weight
= IDWriteTextFormat_GetFontWeight(format
);
2181 layout
->format
.style
= IDWriteTextFormat_GetFontStyle(format
);
2182 layout
->format
.stretch
= IDWriteTextFormat_GetFontStretch(format
);
2183 layout
->format
.fontsize
= IDWriteTextFormat_GetFontSize(format
);
2184 layout
->format
.textalignment
= IDWriteTextFormat_GetTextAlignment(format
);
2185 layout
->format
.paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
2186 layout
->format
.wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
2187 layout
->format
.readingdir
= IDWriteTextFormat_GetReadingDirection(format
);
2188 layout
->format
.flow
= IDWriteTextFormat_GetFlowDirection(format
);
2189 hr
= IDWriteTextFormat_GetLineSpacing(format
, &layout
->format
.spacingmethod
,
2190 &layout
->format
.spacing
, &layout
->format
.baseline
);
2194 hr
= IDWriteTextFormat_GetTrimming(format
, &layout
->format
.trimming
, &layout
->format
.trimmingsign
);
2198 /* locale name and length */
2199 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
2200 layout
->format
.locale
= heap_alloc((len
+1)*sizeof(WCHAR
));
2201 if (!layout
->format
.locale
)
2202 return E_OUTOFMEMORY
;
2204 hr
= IDWriteTextFormat_GetLocaleName(format
, layout
->format
.locale
, len
+1);
2207 layout
->format
.locale_len
= len
;
2209 /* font family name and length */
2210 len
= IDWriteTextFormat_GetFontFamilyNameLength(format
);
2211 layout
->format
.family_name
= heap_alloc((len
+1)*sizeof(WCHAR
));
2212 if (!layout
->format
.family_name
)
2213 return E_OUTOFMEMORY
;
2215 hr
= IDWriteTextFormat_GetFontFamilyName(format
, layout
->format
.family_name
, len
+1);
2218 layout
->format
.family_len
= len
;
2220 return IDWriteTextFormat_GetFontCollection(format
, &layout
->format
.collection
);
2223 static HRESULT
init_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
, struct dwrite_textlayout
*layout
)
2225 DWRITE_TEXT_RANGE r
= { 0, len
};
2226 struct layout_range
*range
;
2229 layout
->IDWriteTextLayout2_iface
.lpVtbl
= &dwritetextlayoutvtbl
;
2230 layout
->IDWriteTextAnalysisSink_iface
.lpVtbl
= &dwritetextlayoutsinkvtbl
;
2231 layout
->IDWriteTextAnalysisSource_iface
.lpVtbl
= &dwritetextlayoutsourcevtbl
;
2234 layout
->maxwidth
= maxwidth
;
2235 layout
->maxheight
= maxheight
;
2236 layout
->recompute
= TRUE
;
2237 layout
->nominal_breakpoints
= NULL
;
2238 layout
->actual_breakpoints
= NULL
;
2239 layout
->clusters_count
= 0;
2240 layout
->clusters
= NULL
;
2241 list_init(&layout
->runs
);
2242 list_init(&layout
->ranges
);
2243 memset(&layout
->format
, 0, sizeof(layout
->format
));
2245 layout
->gdicompatible
= FALSE
;
2246 layout
->pixels_per_dip
= 0.0;
2247 layout
->use_gdi_natural
= FALSE
;
2248 memset(&layout
->transform
, 0, sizeof(layout
->transform
));
2250 layout
->str
= heap_strdupnW(str
, len
);
2251 if (len
&& !layout
->str
) {
2256 hr
= layout_format_from_textformat(layout
, format
);
2260 range
= alloc_layout_range(layout
, &r
);
2266 list_add_head(&layout
->ranges
, &range
->entry
);
2270 IDWriteTextLayout2_Release(&layout
->IDWriteTextLayout2_iface
);
2274 HRESULT
create_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
, IDWriteTextLayout
**ret
)
2276 struct dwrite_textlayout
*layout
;
2281 layout
= heap_alloc(sizeof(struct dwrite_textlayout
));
2282 if (!layout
) return E_OUTOFMEMORY
;
2284 hr
= init_textlayout(str
, len
, format
, maxwidth
, maxheight
, layout
);
2286 *ret
= (IDWriteTextLayout
*)&layout
->IDWriteTextLayout2_iface
;
2291 HRESULT
create_gdicompat_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
,
2292 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
, IDWriteTextLayout
**ret
)
2294 struct dwrite_textlayout
*layout
;
2299 layout
= heap_alloc(sizeof(struct dwrite_textlayout
));
2300 if (!layout
) return E_OUTOFMEMORY
;
2302 hr
= init_textlayout(str
, len
, format
, maxwidth
, maxheight
, layout
);
2304 /* set gdi-specific properties */
2305 layout
->gdicompatible
= TRUE
;
2306 layout
->pixels_per_dip
= pixels_per_dip
;
2307 layout
->use_gdi_natural
= use_gdi_natural
;
2308 layout
->transform
= transform
? *transform
: identity
;
2310 *ret
= (IDWriteTextLayout
*)&layout
->IDWriteTextLayout2_iface
;
2316 static HRESULT WINAPI
dwritetrimmingsign_QueryInterface(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
2318 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2320 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2322 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteInlineObject
)) {
2324 IDWriteInlineObject_AddRef(iface
);
2329 return E_NOINTERFACE
;
2333 static ULONG WINAPI
dwritetrimmingsign_AddRef(IDWriteInlineObject
*iface
)
2335 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2336 ULONG ref
= InterlockedIncrement(&This
->ref
);
2337 TRACE("(%p)->(%d)\n", This
, ref
);
2341 static ULONG WINAPI
dwritetrimmingsign_Release(IDWriteInlineObject
*iface
)
2343 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2344 ULONG ref
= InterlockedDecrement(&This
->ref
);
2346 TRACE("(%p)->(%d)\n", This
, ref
);
2354 static HRESULT WINAPI
dwritetrimmingsign_Draw(IDWriteInlineObject
*iface
, void *context
, IDWriteTextRenderer
*renderer
,
2355 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
2357 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2358 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This
, context
, renderer
, originX
, originY
, is_sideways
, is_rtl
, drawing_effect
);
2362 static HRESULT WINAPI
dwritetrimmingsign_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
2364 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2365 FIXME("(%p)->(%p): stub\n", This
, metrics
);
2369 static HRESULT WINAPI
dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
2371 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2372 FIXME("(%p)->(%p): stub\n", This
, overhangs
);
2376 static HRESULT WINAPI
dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
2377 DWRITE_BREAK_CONDITION
*after
)
2379 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
2381 TRACE("(%p)->(%p %p)\n", This
, before
, after
);
2383 *before
= *after
= DWRITE_BREAK_CONDITION_NEUTRAL
;
2387 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl
= {
2388 dwritetrimmingsign_QueryInterface
,
2389 dwritetrimmingsign_AddRef
,
2390 dwritetrimmingsign_Release
,
2391 dwritetrimmingsign_Draw
,
2392 dwritetrimmingsign_GetMetrics
,
2393 dwritetrimmingsign_GetOverhangMetrics
,
2394 dwritetrimmingsign_GetBreakConditions
2397 HRESULT
create_trimmingsign(IDWriteInlineObject
**sign
)
2399 struct dwrite_trimmingsign
*This
;
2403 This
= heap_alloc(sizeof(struct dwrite_trimmingsign
));
2404 if (!This
) return E_OUTOFMEMORY
;
2406 This
->IDWriteInlineObject_iface
.lpVtbl
= &dwritetrimmingsignvtbl
;
2409 *sign
= &This
->IDWriteInlineObject_iface
;
2414 static HRESULT WINAPI
dwritetextformat_QueryInterface(IDWriteTextFormat1
*iface
, REFIID riid
, void **obj
)
2416 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2418 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2420 if (IsEqualIID(riid
, &IID_IDWriteTextFormat1
) ||
2421 IsEqualIID(riid
, &IID_IDWriteTextFormat
) ||
2422 IsEqualIID(riid
, &IID_IUnknown
))
2425 IDWriteTextFormat1_AddRef(iface
);
2431 return E_NOINTERFACE
;
2434 static ULONG WINAPI
dwritetextformat_AddRef(IDWriteTextFormat1
*iface
)
2436 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2437 ULONG ref
= InterlockedIncrement(&This
->ref
);
2438 TRACE("(%p)->(%d)\n", This
, ref
);
2442 static ULONG WINAPI
dwritetextformat_Release(IDWriteTextFormat1
*iface
)
2444 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2445 ULONG ref
= InterlockedDecrement(&This
->ref
);
2447 TRACE("(%p)->(%d)\n", This
, ref
);
2451 release_format_data(&This
->format
);
2458 static HRESULT WINAPI
dwritetextformat_SetTextAlignment(IDWriteTextFormat1
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
2460 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2461 TRACE("(%p)->(%d)\n", This
, alignment
);
2462 This
->format
.textalignment
= alignment
;
2466 static HRESULT WINAPI
dwritetextformat_SetParagraphAlignment(IDWriteTextFormat1
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
2468 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2469 TRACE("(%p)->(%d)\n", This
, alignment
);
2470 This
->format
.paralign
= alignment
;
2474 static HRESULT WINAPI
dwritetextformat_SetWordWrapping(IDWriteTextFormat1
*iface
, DWRITE_WORD_WRAPPING wrapping
)
2476 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2477 TRACE("(%p)->(%d)\n", This
, wrapping
);
2478 This
->format
.wrapping
= wrapping
;
2482 static HRESULT WINAPI
dwritetextformat_SetReadingDirection(IDWriteTextFormat1
*iface
, DWRITE_READING_DIRECTION direction
)
2484 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2485 TRACE("(%p)->(%d)\n", This
, direction
);
2486 This
->format
.readingdir
= direction
;
2490 static HRESULT WINAPI
dwritetextformat_SetFlowDirection(IDWriteTextFormat1
*iface
, DWRITE_FLOW_DIRECTION direction
)
2492 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2493 TRACE("(%p)->(%d)\n", This
, direction
);
2494 This
->format
.flow
= direction
;
2498 static HRESULT WINAPI
dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat1
*iface
, FLOAT tabstop
)
2500 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2501 FIXME("(%p)->(%f): stub\n", This
, tabstop
);
2505 static HRESULT WINAPI
dwritetextformat_SetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
const *trimming
,
2506 IDWriteInlineObject
*trimming_sign
)
2508 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2509 TRACE("(%p)->(%p %p)\n", This
, trimming
, trimming_sign
);
2511 This
->format
.trimming
= *trimming
;
2512 if (This
->format
.trimmingsign
)
2513 IDWriteInlineObject_Release(This
->format
.trimmingsign
);
2514 This
->format
.trimmingsign
= trimming_sign
;
2515 if (This
->format
.trimmingsign
)
2516 IDWriteInlineObject_AddRef(This
->format
.trimmingsign
);
2520 static HRESULT WINAPI
dwritetextformat_SetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD method
,
2521 FLOAT spacing
, FLOAT baseline
)
2523 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2524 TRACE("(%p)->(%d %f %f)\n", This
, method
, spacing
, baseline
);
2525 This
->format
.spacingmethod
= method
;
2526 This
->format
.spacing
= spacing
;
2527 This
->format
.baseline
= baseline
;
2531 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextformat_GetTextAlignment(IDWriteTextFormat1
*iface
)
2533 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2534 TRACE("(%p)\n", This
);
2535 return This
->format
.textalignment
;
2538 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextformat_GetParagraphAlignment(IDWriteTextFormat1
*iface
)
2540 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2541 TRACE("(%p)\n", This
);
2542 return This
->format
.paralign
;
2545 static DWRITE_WORD_WRAPPING WINAPI
dwritetextformat_GetWordWrapping(IDWriteTextFormat1
*iface
)
2547 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2548 TRACE("(%p)\n", This
);
2549 return This
->format
.wrapping
;
2552 static DWRITE_READING_DIRECTION WINAPI
dwritetextformat_GetReadingDirection(IDWriteTextFormat1
*iface
)
2554 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2555 TRACE("(%p)\n", This
);
2556 return This
->format
.readingdir
;
2559 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextformat_GetFlowDirection(IDWriteTextFormat1
*iface
)
2561 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2562 TRACE("(%p)\n", This
);
2563 return This
->format
.flow
;
2566 static FLOAT WINAPI
dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat1
*iface
)
2568 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2569 FIXME("(%p): stub\n", This
);
2573 static HRESULT WINAPI
dwritetextformat_GetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
*options
,
2574 IDWriteInlineObject
**trimming_sign
)
2576 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2577 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
2579 *options
= This
->format
.trimming
;
2580 if ((*trimming_sign
= This
->format
.trimmingsign
))
2581 IDWriteInlineObject_AddRef(*trimming_sign
);
2586 static HRESULT WINAPI
dwritetextformat_GetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
2587 FLOAT
*spacing
, FLOAT
*baseline
)
2589 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2590 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
2592 *method
= This
->format
.spacingmethod
;
2593 *spacing
= This
->format
.spacing
;
2594 *baseline
= This
->format
.baseline
;
2598 static HRESULT WINAPI
dwritetextformat_GetFontCollection(IDWriteTextFormat1
*iface
, IDWriteFontCollection
**collection
)
2600 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2602 TRACE("(%p)->(%p)\n", This
, collection
);
2604 *collection
= This
->format
.collection
;
2605 IDWriteFontCollection_AddRef(*collection
);
2610 static UINT32 WINAPI
dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat1
*iface
)
2612 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2613 TRACE("(%p)\n", This
);
2614 return This
->format
.family_len
;
2617 static HRESULT WINAPI
dwritetextformat_GetFontFamilyName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
2619 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2621 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
2623 if (size
<= This
->format
.family_len
) return E_NOT_SUFFICIENT_BUFFER
;
2624 strcpyW(name
, This
->format
.family_name
);
2628 static DWRITE_FONT_WEIGHT WINAPI
dwritetextformat_GetFontWeight(IDWriteTextFormat1
*iface
)
2630 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2631 TRACE("(%p)\n", This
);
2632 return This
->format
.weight
;
2635 static DWRITE_FONT_STYLE WINAPI
dwritetextformat_GetFontStyle(IDWriteTextFormat1
*iface
)
2637 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2638 TRACE("(%p)\n", This
);
2639 return This
->format
.style
;
2642 static DWRITE_FONT_STRETCH WINAPI
dwritetextformat_GetFontStretch(IDWriteTextFormat1
*iface
)
2644 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2645 TRACE("(%p)\n", This
);
2646 return This
->format
.stretch
;
2649 static FLOAT WINAPI
dwritetextformat_GetFontSize(IDWriteTextFormat1
*iface
)
2651 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2652 TRACE("(%p)\n", This
);
2653 return This
->format
.fontsize
;
2656 static UINT32 WINAPI
dwritetextformat_GetLocaleNameLength(IDWriteTextFormat1
*iface
)
2658 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2659 TRACE("(%p)\n", This
);
2660 return This
->format
.locale_len
;
2663 static HRESULT WINAPI
dwritetextformat_GetLocaleName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
2665 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2667 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
2669 if (size
<= This
->format
.locale_len
) return E_NOT_SUFFICIENT_BUFFER
;
2670 strcpyW(name
, This
->format
.locale
);
2674 static HRESULT WINAPI
dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
2676 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2677 FIXME("(%p)->(%d): stub\n", This
, orientation
);
2681 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
)
2683 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2684 FIXME("(%p): stub\n", This
);
2685 return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
2688 static HRESULT WINAPI
dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat1
*iface
, BOOL lastline_wrapping_enabled
)
2690 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2691 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
2695 static BOOL WINAPI
dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat1
*iface
)
2697 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2698 FIXME("(%p): stub\n", This
);
2702 static HRESULT WINAPI
dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat1
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
2704 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2705 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2709 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat1
*iface
)
2711 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2712 FIXME("(%p): stub\n", This
);
2713 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
2716 static HRESULT WINAPI
dwritetextformat1_SetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
*fallback
)
2718 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2719 FIXME("(%p)->(%p): stub\n", This
, fallback
);
2723 static HRESULT WINAPI
dwritetextformat1_GetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
**fallback
)
2725 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
2726 FIXME("(%p)->(%p): stub\n", This
, fallback
);
2730 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl
= {
2731 dwritetextformat_QueryInterface
,
2732 dwritetextformat_AddRef
,
2733 dwritetextformat_Release
,
2734 dwritetextformat_SetTextAlignment
,
2735 dwritetextformat_SetParagraphAlignment
,
2736 dwritetextformat_SetWordWrapping
,
2737 dwritetextformat_SetReadingDirection
,
2738 dwritetextformat_SetFlowDirection
,
2739 dwritetextformat_SetIncrementalTabStop
,
2740 dwritetextformat_SetTrimming
,
2741 dwritetextformat_SetLineSpacing
,
2742 dwritetextformat_GetTextAlignment
,
2743 dwritetextformat_GetParagraphAlignment
,
2744 dwritetextformat_GetWordWrapping
,
2745 dwritetextformat_GetReadingDirection
,
2746 dwritetextformat_GetFlowDirection
,
2747 dwritetextformat_GetIncrementalTabStop
,
2748 dwritetextformat_GetTrimming
,
2749 dwritetextformat_GetLineSpacing
,
2750 dwritetextformat_GetFontCollection
,
2751 dwritetextformat_GetFontFamilyNameLength
,
2752 dwritetextformat_GetFontFamilyName
,
2753 dwritetextformat_GetFontWeight
,
2754 dwritetextformat_GetFontStyle
,
2755 dwritetextformat_GetFontStretch
,
2756 dwritetextformat_GetFontSize
,
2757 dwritetextformat_GetLocaleNameLength
,
2758 dwritetextformat_GetLocaleName
,
2759 dwritetextformat1_SetVerticalGlyphOrientation
,
2760 dwritetextformat1_GetVerticalGlyphOrientation
,
2761 dwritetextformat1_SetLastLineWrapping
,
2762 dwritetextformat1_GetLastLineWrapping
,
2763 dwritetextformat1_SetOpticalAlignment
,
2764 dwritetextformat1_GetOpticalAlignment
,
2765 dwritetextformat1_SetFontFallback
,
2766 dwritetextformat1_GetFontFallback
2769 HRESULT
create_textformat(const WCHAR
*family_name
, IDWriteFontCollection
*collection
, DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STYLE style
,
2770 DWRITE_FONT_STRETCH stretch
, FLOAT size
, const WCHAR
*locale
, IDWriteTextFormat
**format
)
2772 struct dwrite_textformat
*This
;
2776 This
= heap_alloc(sizeof(struct dwrite_textformat
));
2777 if (!This
) return E_OUTOFMEMORY
;
2779 This
->IDWriteTextFormat1_iface
.lpVtbl
= &dwritetextformatvtbl
;
2781 This
->format
.family_name
= heap_strdupW(family_name
);
2782 This
->format
.family_len
= strlenW(family_name
);
2783 This
->format
.locale
= heap_strdupW(locale
);
2784 This
->format
.locale_len
= strlenW(locale
);
2785 This
->format
.weight
= weight
;
2786 This
->format
.style
= style
;
2787 This
->format
.fontsize
= size
;
2788 This
->format
.stretch
= stretch
;
2789 This
->format
.textalignment
= DWRITE_TEXT_ALIGNMENT_LEADING
;
2790 This
->format
.paralign
= DWRITE_PARAGRAPH_ALIGNMENT_NEAR
;
2791 This
->format
.wrapping
= DWRITE_WORD_WRAPPING_WRAP
;
2792 This
->format
.readingdir
= DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
;
2793 This
->format
.flow
= DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
;
2794 This
->format
.spacingmethod
= DWRITE_LINE_SPACING_METHOD_DEFAULT
;
2795 This
->format
.spacing
= 0.0;
2796 This
->format
.baseline
= 0.0;
2797 This
->format
.trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_NONE
;
2798 This
->format
.trimming
.delimiter
= 0;
2799 This
->format
.trimming
.delimiterCount
= 0;
2800 This
->format
.trimmingsign
= NULL
;
2801 This
->format
.collection
= collection
;
2802 IDWriteFontCollection_AddRef(collection
);
2804 *format
= (IDWriteTextFormat
*)&This
->IDWriteTextFormat1_iface
;
2809 static HRESULT WINAPI
dwritetypography_QueryInterface(IDWriteTypography
*iface
, REFIID riid
, void **obj
)
2811 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
2813 TRACE("(%p)->(%s %p)\n", typography
, debugstr_guid(riid
), obj
);
2815 if (IsEqualIID(riid
, &IID_IDWriteTypography
) || IsEqualIID(riid
, &IID_IUnknown
)) {
2817 IDWriteTypography_AddRef(iface
);
2823 return E_NOINTERFACE
;
2826 static ULONG WINAPI
dwritetypography_AddRef(IDWriteTypography
*iface
)
2828 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
2829 ULONG ref
= InterlockedIncrement(&typography
->ref
);
2830 TRACE("(%p)->(%d)\n", typography
, ref
);
2834 static ULONG WINAPI
dwritetypography_Release(IDWriteTypography
*iface
)
2836 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
2837 ULONG ref
= InterlockedDecrement(&typography
->ref
);
2839 TRACE("(%p)->(%d)\n", typography
, ref
);
2842 heap_free(typography
->features
);
2843 heap_free(typography
);
2849 static HRESULT WINAPI
dwritetypography_AddFontFeature(IDWriteTypography
*iface
, DWRITE_FONT_FEATURE feature
)
2851 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
2853 TRACE("(%p)->(%x %u)\n", typography
, feature
.nameTag
, feature
.parameter
);
2855 if (typography
->count
== typography
->allocated
) {
2856 DWRITE_FONT_FEATURE
*ptr
= heap_realloc(typography
->features
, 2*typography
->allocated
*sizeof(DWRITE_FONT_FEATURE
));
2858 return E_OUTOFMEMORY
;
2860 typography
->features
= ptr
;
2861 typography
->allocated
*= 2;
2864 typography
->features
[typography
->count
++] = feature
;
2868 static UINT32 WINAPI
dwritetypography_GetFontFeatureCount(IDWriteTypography
*iface
)
2870 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
2871 TRACE("(%p)\n", typography
);
2872 return typography
->count
;
2875 static HRESULT WINAPI
dwritetypography_GetFontFeature(IDWriteTypography
*iface
, UINT32 index
, DWRITE_FONT_FEATURE
*feature
)
2877 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
2879 TRACE("(%p)->(%u %p)\n", typography
, index
, feature
);
2881 if (index
>= typography
->count
)
2882 return E_INVALIDARG
;
2884 *feature
= typography
->features
[index
];
2888 static const IDWriteTypographyVtbl dwritetypographyvtbl
= {
2889 dwritetypography_QueryInterface
,
2890 dwritetypography_AddRef
,
2891 dwritetypography_Release
,
2892 dwritetypography_AddFontFeature
,
2893 dwritetypography_GetFontFeatureCount
,
2894 dwritetypography_GetFontFeature
2897 HRESULT
create_typography(IDWriteTypography
**ret
)
2899 struct dwrite_typography
*typography
;
2903 typography
= heap_alloc(sizeof(*typography
));
2905 return E_OUTOFMEMORY
;
2907 typography
->IDWriteTypography_iface
.lpVtbl
= &dwritetypographyvtbl
;
2908 typography
->ref
= 1;
2909 typography
->allocated
= 2;
2910 typography
->count
= 0;
2912 typography
->features
= heap_alloc(typography
->allocated
*sizeof(DWRITE_FONT_FEATURE
));
2913 if (!typography
->features
) {
2914 heap_free(typography
);
2915 return E_OUTOFMEMORY
;
2918 *ret
= &typography
->IDWriteTypography_iface
;