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