2 * Text format and layout
4 * Copyright 2012, 2014-2015 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
;
50 DWRITE_VERTICAL_GLYPH_ORIENTATION vertical_orientation
;
56 DWRITE_TRIMMING trimming
;
57 IDWriteInlineObject
*trimmingsign
;
59 IDWriteFontCollection
*collection
;
60 IDWriteFontFallback
*fallback
;
63 enum layout_range_attr_kind
{
64 LAYOUT_RANGE_ATTR_WEIGHT
,
65 LAYOUT_RANGE_ATTR_STYLE
,
66 LAYOUT_RANGE_ATTR_STRETCH
,
67 LAYOUT_RANGE_ATTR_FONTSIZE
,
68 LAYOUT_RANGE_ATTR_EFFECT
,
69 LAYOUT_RANGE_ATTR_INLINE
,
70 LAYOUT_RANGE_ATTR_UNDERLINE
,
71 LAYOUT_RANGE_ATTR_STRIKETHROUGH
,
72 LAYOUT_RANGE_ATTR_PAIR_KERNING
,
73 LAYOUT_RANGE_ATTR_FONTCOLL
,
74 LAYOUT_RANGE_ATTR_LOCALE
,
75 LAYOUT_RANGE_ATTR_FONTFAMILY
78 struct layout_range_attr_value
{
79 DWRITE_TEXT_RANGE range
;
81 DWRITE_FONT_WEIGHT weight
;
82 DWRITE_FONT_STYLE style
;
83 DWRITE_FONT_STRETCH stretch
;
85 IDWriteInlineObject
*object
;
90 IDWriteFontCollection
*collection
;
92 const WCHAR
*fontfamily
;
98 DWRITE_TEXT_RANGE range
;
99 DWRITE_FONT_WEIGHT weight
;
100 DWRITE_FONT_STYLE style
;
102 DWRITE_FONT_STRETCH stretch
;
103 IDWriteInlineObject
*object
;
108 IDWriteFontCollection
*collection
;
109 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
113 enum layout_run_kind
{
118 struct inline_object_run
{
119 IDWriteInlineObject
*object
;
123 struct regular_layout_run
{
124 DWRITE_GLYPH_RUN_DESCRIPTION descr
;
125 DWRITE_GLYPH_RUN run
;
126 DWRITE_SCRIPT_ANALYSIS sa
;
130 DWRITE_GLYPH_OFFSET
*offsets
;
135 enum layout_run_kind kind
;
137 struct inline_object_run object
;
138 struct regular_layout_run regular
;
142 struct layout_effective_run
{
144 const struct layout_run
*run
; /* nominal run this one is based on */
145 UINT32 start
; /* relative text position, 0 means first text position of a nominal run */
146 UINT32 length
; /* length in codepoints that this run covers */
147 UINT32 glyphcount
; /* total glyph count in this run */
148 FLOAT origin_x
; /* baseline X position */
149 FLOAT origin_y
; /* baseline Y position */
150 UINT16
*clustermap
; /* effective clustermap, allocated separately, is not reused from nominal map */
153 struct layout_cluster
{
154 const struct layout_run
*run
; /* link to nominal run this cluster belongs to */
155 UINT32 position
; /* relative to run, first cluster has 0 position */
158 enum layout_recompute_mask
{
159 RECOMPUTE_NOMINAL_RUNS
= 1 << 0,
160 RECOMPUTE_MINIMAL_WIDTH
= 1 << 1,
161 RECOMPUTE_EFFECTIVE_RUNS
= 1 << 2,
162 RECOMPUTE_EVERYTHING
= 0xffff
165 struct dwrite_textlayout
{
166 IDWriteTextLayout2 IDWriteTextLayout2_iface
;
167 IDWriteTextFormat1 IDWriteTextFormat1_iface
;
168 IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface
;
169 IDWriteTextAnalysisSource IDWriteTextAnalysisSource_iface
;
174 struct dwrite_textformat_data format
;
182 DWRITE_LINE_BREAKPOINT
*nominal_breakpoints
;
183 DWRITE_LINE_BREAKPOINT
*actual_breakpoints
;
185 struct layout_cluster
*clusters
;
186 DWRITE_CLUSTER_METRICS
*clustermetrics
;
187 UINT32 cluster_count
;
190 DWRITE_LINE_METRICS
*lines
;
194 /* gdi-compatible layout specifics */
196 FLOAT pixels_per_dip
;
197 BOOL use_gdi_natural
;
198 DWRITE_MATRIX transform
;
201 struct dwrite_textformat
{
202 IDWriteTextFormat1 IDWriteTextFormat1_iface
;
204 struct dwrite_textformat_data format
;
207 struct dwrite_trimmingsign
{
208 IDWriteInlineObject IDWriteInlineObject_iface
;
212 struct dwrite_typography
{
213 IDWriteTypography IDWriteTypography_iface
;
216 DWRITE_FONT_FEATURE
*features
;
221 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl
;
223 static void release_format_data(struct dwrite_textformat_data
*data
)
225 if (data
->collection
) IDWriteFontCollection_Release(data
->collection
);
226 if (data
->fallback
) IDWriteFontFallback_Release(data
->fallback
);
227 if (data
->trimmingsign
) IDWriteInlineObject_Release(data
->trimmingsign
);
228 heap_free(data
->family_name
);
229 heap_free(data
->locale
);
232 static inline struct dwrite_textlayout
*impl_from_IDWriteTextLayout2(IDWriteTextLayout2
*iface
)
234 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextLayout2_iface
);
237 static inline struct dwrite_textlayout
*impl_layout_form_IDWriteTextFormat1(IDWriteTextFormat1
*iface
)
239 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextFormat1_iface
);
242 static inline struct dwrite_textlayout
*impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink
*iface
)
244 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextAnalysisSink_iface
);
247 static inline struct dwrite_textlayout
*impl_from_IDWriteTextAnalysisSource(IDWriteTextAnalysisSource
*iface
)
249 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextAnalysisSource_iface
);
252 static inline struct dwrite_textformat
*impl_from_IDWriteTextFormat1(IDWriteTextFormat1
*iface
)
254 return CONTAINING_RECORD(iface
, struct dwrite_textformat
, IDWriteTextFormat1_iface
);
257 static inline struct dwrite_trimmingsign
*impl_from_IDWriteInlineObject(IDWriteInlineObject
*iface
)
259 return CONTAINING_RECORD(iface
, struct dwrite_trimmingsign
, IDWriteInlineObject_iface
);
262 static inline struct dwrite_typography
*impl_from_IDWriteTypography(IDWriteTypography
*iface
)
264 return CONTAINING_RECORD(iface
, struct dwrite_typography
, IDWriteTypography_iface
);
267 static inline const char *debugstr_run(const struct regular_layout_run
*run
)
269 return wine_dbg_sprintf("[%u,%u)", run
->descr
.textPosition
, run
->descr
.textPosition
+
270 run
->descr
.stringLength
);
273 static HRESULT
get_fontfallback_from_format(const struct dwrite_textformat_data
*format
, IDWriteFontFallback
**fallback
)
275 *fallback
= format
->fallback
;
277 IDWriteFontFallback_AddRef(*fallback
);
281 static HRESULT
set_fontfallback_for_format(struct dwrite_textformat_data
*format
, IDWriteFontFallback
*fallback
)
283 if (format
->fallback
)
284 IDWriteFontFallback_Release(format
->fallback
);
285 format
->fallback
= fallback
;
287 IDWriteFontFallback_AddRef(fallback
);
291 static struct layout_run
*alloc_layout_run(enum layout_run_kind kind
)
293 struct layout_run
*ret
;
295 ret
= heap_alloc(sizeof(*ret
));
296 if (!ret
) return NULL
;
298 memset(ret
, 0, sizeof(*ret
));
300 if (kind
== LAYOUT_RUN_REGULAR
) {
301 ret
->u
.regular
.sa
.script
= Script_Unknown
;
302 ret
->u
.regular
.sa
.shapes
= DWRITE_SCRIPT_SHAPES_DEFAULT
;
308 static void free_layout_runs(struct dwrite_textlayout
*layout
)
310 struct layout_run
*cur
, *cur2
;
311 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->runs
, struct layout_run
, entry
) {
312 list_remove(&cur
->entry
);
313 if (cur
->kind
== LAYOUT_RUN_REGULAR
) {
314 if (cur
->u
.regular
.run
.fontFace
)
315 IDWriteFontFace_Release(cur
->u
.regular
.run
.fontFace
);
316 heap_free(cur
->u
.regular
.glyphs
);
317 heap_free(cur
->u
.regular
.clustermap
);
318 heap_free(cur
->u
.regular
.advances
);
319 heap_free(cur
->u
.regular
.offsets
);
325 static void free_layout_eruns(struct dwrite_textlayout
*layout
)
327 struct layout_effective_run
*cur
, *cur2
;
328 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->eruns
, struct layout_effective_run
, entry
) {
329 list_remove(&cur
->entry
);
330 heap_free(cur
->clustermap
);
335 /* Used to resolve break condition by forcing stronger condition over weaker. */
336 static inline DWRITE_BREAK_CONDITION
override_break_condition(DWRITE_BREAK_CONDITION existingbreak
, DWRITE_BREAK_CONDITION newbreak
)
338 switch (existingbreak
) {
339 case DWRITE_BREAK_CONDITION_NEUTRAL
:
341 case DWRITE_BREAK_CONDITION_CAN_BREAK
:
342 return newbreak
== DWRITE_BREAK_CONDITION_NEUTRAL
? existingbreak
: newbreak
;
343 /* let's keep stronger conditions as is */
344 case DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
:
345 case DWRITE_BREAK_CONDITION_MUST_BREAK
:
348 ERR("unknown break condition %d\n", existingbreak
);
351 return existingbreak
;
354 /* Actual breakpoint data gets updated with break condition required by inline object set for range 'cur'. */
355 static HRESULT
layout_update_breakpoints_range(struct dwrite_textlayout
*layout
, const struct layout_range
*cur
)
357 DWRITE_BREAK_CONDITION before
, after
;
361 hr
= IDWriteInlineObject_GetBreakConditions(cur
->object
, &before
, &after
);
365 if (!layout
->actual_breakpoints
) {
366 layout
->actual_breakpoints
= heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
367 if (!layout
->actual_breakpoints
)
368 return E_OUTOFMEMORY
;
370 memcpy(layout
->actual_breakpoints
, layout
->nominal_breakpoints
, sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
372 for (i
= cur
->range
.startPosition
; i
< cur
->range
.length
+ cur
->range
.startPosition
; i
++) {
373 UINT32 j
= i
+ cur
->range
.startPosition
;
376 layout
->actual_breakpoints
[j
].breakConditionBefore
= layout
->actual_breakpoints
[j
-1].breakConditionAfter
=
377 override_break_condition(layout
->actual_breakpoints
[j
-1].breakConditionAfter
, before
);
379 layout
->actual_breakpoints
[j
].breakConditionBefore
= before
;
381 layout
->actual_breakpoints
[j
].breakConditionAfter
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
384 layout
->actual_breakpoints
[j
].isWhitespace
= 0;
385 layout
->actual_breakpoints
[j
].isSoftHyphen
= 0;
387 if (i
== cur
->range
.length
- 1) {
388 layout
->actual_breakpoints
[j
].breakConditionBefore
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
389 if (j
< layout
->len
- 1)
390 layout
->actual_breakpoints
[j
].breakConditionAfter
= layout
->actual_breakpoints
[j
+1].breakConditionAfter
=
391 override_break_condition(layout
->actual_breakpoints
[j
+1].breakConditionAfter
, before
);
393 layout
->actual_breakpoints
[j
].breakConditionAfter
= before
;
400 static struct layout_range
*get_layout_range_by_pos(struct dwrite_textlayout
*layout
, UINT32 pos
);
402 static inline DWRITE_LINE_BREAKPOINT
get_effective_breakpoint(const struct dwrite_textlayout
*layout
, UINT32 pos
)
404 if (layout
->actual_breakpoints
)
405 return layout
->actual_breakpoints
[pos
];
406 return layout
->nominal_breakpoints
[pos
];
409 static inline void init_cluster_metrics(const struct dwrite_textlayout
*layout
, const struct regular_layout_run
*run
,
410 UINT16 start_glyph
, UINT16 stop_glyph
, UINT32 stop_position
, DWRITE_CLUSTER_METRICS
*metrics
)
412 UINT8 breakcondition
;
416 metrics
->width
= 0.0;
417 for (j
= start_glyph
; j
< stop_glyph
; j
++)
418 metrics
->width
+= run
->run
.glyphAdvances
[j
];
421 position
= stop_position
;
422 if (stop_glyph
== run
->run
.glyphCount
)
423 breakcondition
= get_effective_breakpoint(layout
, stop_position
).breakConditionAfter
;
425 breakcondition
= get_effective_breakpoint(layout
, stop_position
).breakConditionBefore
;
426 if (stop_position
) position
= stop_position
- 1;
429 metrics
->canWrapLineAfter
= breakcondition
== DWRITE_BREAK_CONDITION_CAN_BREAK
||
430 breakcondition
== DWRITE_BREAK_CONDITION_MUST_BREAK
;
431 if (metrics
->length
== 1) {
434 GetStringTypeW(CT_CTYPE1
, &layout
->str
[position
], 1, &type
);
435 metrics
->isWhitespace
= type
== C1_SPACE
;
436 metrics
->isNewline
= FALSE
/* FIXME */;
437 metrics
->isSoftHyphen
= layout
->str
[position
] == 0x00ad /* Unicode Soft Hyphen */;
440 metrics
->isWhitespace
= FALSE
;
441 metrics
->isNewline
= FALSE
;
442 metrics
->isSoftHyphen
= FALSE
;
444 metrics
->isRightToLeft
= run
->run
.bidiLevel
& 1;
445 metrics
->padding
= 0;
450 All clusters in a 'run' will be added to 'layout' data, starting at index pointed to by 'cluster'.
451 On return 'cluster' is updated to point to next metrics struct to be filled in on next call.
452 Note that there's no need to reallocate anything at this point as we allocate one cluster per
456 static void layout_set_cluster_metrics(struct dwrite_textlayout
*layout
, const struct layout_run
*r
, UINT32
*cluster
)
458 DWRITE_CLUSTER_METRICS
*metrics
= &layout
->clustermetrics
[*cluster
];
459 struct layout_cluster
*c
= &layout
->clusters
[*cluster
];
460 const struct regular_layout_run
*run
= &r
->u
.regular
;
463 for (i
= 0; i
< run
->descr
.stringLength
; i
++) {
464 BOOL end
= i
== run
->descr
.stringLength
- 1;
466 if (run
->descr
.clusterMap
[start
] != run
->descr
.clusterMap
[i
]) {
467 init_cluster_metrics(layout
, run
, run
->descr
.clusterMap
[start
], run
->descr
.clusterMap
[i
], i
, metrics
);
468 metrics
->length
= i
- start
;
479 init_cluster_metrics(layout
, run
, run
->descr
.clusterMap
[start
], run
->run
.glyphCount
, i
, metrics
);
480 metrics
->length
= i
- start
+ 1;
490 static HRESULT
layout_compute_runs(struct dwrite_textlayout
*layout
)
492 IDWriteTextAnalyzer
*analyzer
;
493 struct layout_range
*range
;
494 struct layout_run
*r
;
498 free_layout_runs(layout
);
500 /* Cluster data arrays are allocated once, assuming one text position per cluster. */
501 if (!layout
->clustermetrics
) {
502 layout
->clustermetrics
= heap_alloc(layout
->len
*sizeof(*layout
->clustermetrics
));
503 layout
->clusters
= heap_alloc(layout
->len
*sizeof(*layout
->clusters
));
504 if (!layout
->clustermetrics
|| !layout
->clusters
) {
505 heap_free(layout
->clustermetrics
);
506 heap_free(layout
->clusters
);
507 return E_OUTOFMEMORY
;
510 layout
->cluster_count
= 0;
512 hr
= get_textanalyzer(&analyzer
);
516 LIST_FOR_EACH_ENTRY(range
, &layout
->ranges
, struct layout_range
, entry
) {
517 /* inline objects override actual text in a range */
519 hr
= layout_update_breakpoints_range(layout
, range
);
523 r
= alloc_layout_run(LAYOUT_RUN_INLINE
);
525 return E_OUTOFMEMORY
;
527 r
->u
.object
.object
= range
->object
;
528 r
->u
.object
.length
= range
->range
.length
;
529 list_add_tail(&layout
->runs
, &r
->entry
);
533 /* initial splitting by script */
534 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
535 range
->range
.startPosition
, range
->range
.length
, &layout
->IDWriteTextAnalysisSink_iface
);
539 /* this splits it further */
540 hr
= IDWriteTextAnalyzer_AnalyzeBidi(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
541 range
->range
.startPosition
, range
->range
.length
, &layout
->IDWriteTextAnalysisSink_iface
);
547 LIST_FOR_EACH_ENTRY(r
, &layout
->runs
, struct layout_run
, entry
) {
548 DWRITE_SHAPING_GLYPH_PROPERTIES
*glyph_props
= NULL
;
549 DWRITE_SHAPING_TEXT_PROPERTIES
*text_props
= NULL
;
550 struct regular_layout_run
*run
= &r
->u
.regular
;
551 IDWriteFontFamily
*family
;
552 UINT32 index
, max_count
;
556 /* we need to do very little in case of inline objects */
557 if (r
->kind
== LAYOUT_RUN_INLINE
) {
558 DWRITE_CLUSTER_METRICS
*metrics
= &layout
->clustermetrics
[cluster
];
559 struct layout_cluster
*c
= &layout
->clusters
[cluster
];
560 DWRITE_INLINE_OBJECT_METRICS inlinemetrics
;
562 metrics
->width
= 0.0;
563 metrics
->length
= r
->u
.object
.length
;
564 metrics
->canWrapLineAfter
= FALSE
;
565 metrics
->isWhitespace
= FALSE
;
566 metrics
->isNewline
= FALSE
;
567 metrics
->isSoftHyphen
= FALSE
;
568 metrics
->isRightToLeft
= FALSE
;
569 metrics
->padding
= 0;
571 c
->position
= 0; /* there's always one cluster per inline object, so 0 is valid value */
574 /* TODO: is it fatal if GetMetrics() fails? */
575 hr
= IDWriteInlineObject_GetMetrics(r
->u
.object
.object
, &inlinemetrics
);
577 FIXME("failed to get inline object metrics, 0x%08x\n", hr
);
580 metrics
->width
= inlinemetrics
.width
;
582 /* FIXME: use resolved breakpoints in this case too */
587 range
= get_layout_range_by_pos(layout
, run
->descr
.textPosition
);
589 hr
= IDWriteFontCollection_FindFamilyName(range
->collection
, range
->fontfamily
, &index
, &exists
);
590 if (FAILED(hr
) || !exists
) {
591 WARN("%s: family %s not found in collection %p\n", debugstr_run(run
), debugstr_w(range
->fontfamily
), range
->collection
);
595 hr
= IDWriteFontCollection_GetFontFamily(range
->collection
, index
, &family
);
599 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, range
->weight
, range
->stretch
, range
->style
, &font
);
600 IDWriteFontFamily_Release(family
);
602 WARN("%s: failed to get a matching font\n", debugstr_run(run
));
606 hr
= IDWriteFont_CreateFontFace(font
, &run
->run
.fontFace
);
607 IDWriteFont_Release(font
);
611 run
->run
.fontEmSize
= range
->fontsize
;
612 run
->descr
.localeName
= range
->locale
;
613 run
->clustermap
= heap_alloc(run
->descr
.stringLength
*sizeof(UINT16
));
615 max_count
= 3*run
->descr
.stringLength
/2 + 16;
616 run
->glyphs
= heap_alloc(max_count
*sizeof(UINT16
));
617 if (!run
->clustermap
|| !run
->glyphs
)
620 text_props
= heap_alloc(run
->descr
.stringLength
*sizeof(DWRITE_SHAPING_TEXT_PROPERTIES
));
621 glyph_props
= heap_alloc(max_count
*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES
));
622 if (!text_props
|| !glyph_props
)
626 hr
= IDWriteTextAnalyzer_GetGlyphs(analyzer
, run
->descr
.string
, run
->descr
.stringLength
,
627 run
->run
.fontFace
, run
->run
.isSideways
, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
,
628 NULL
/* FIXME */, NULL
, NULL
, 0, max_count
, run
->clustermap
, text_props
, run
->glyphs
, glyph_props
,
629 &run
->run
.glyphCount
);
630 if (hr
== E_NOT_SUFFICIENT_BUFFER
) {
631 heap_free(run
->glyphs
);
632 heap_free(glyph_props
);
634 max_count
= run
->run
.glyphCount
;
636 run
->glyphs
= heap_alloc(max_count
*sizeof(UINT16
));
637 glyph_props
= heap_alloc(max_count
*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES
));
638 if (!run
->glyphs
|| !glyph_props
)
648 heap_free(text_props
);
649 heap_free(glyph_props
);
650 WARN("%s: shaping failed 0x%08x\n", debugstr_run(run
), hr
);
654 run
->run
.glyphIndices
= run
->glyphs
;
655 run
->descr
.clusterMap
= run
->clustermap
;
657 run
->advances
= heap_alloc(run
->run
.glyphCount
*sizeof(FLOAT
));
658 run
->offsets
= heap_alloc(run
->run
.glyphCount
*sizeof(DWRITE_GLYPH_OFFSET
));
659 if (!run
->advances
|| !run
->offsets
)
662 /* now set advances and offsets */
663 if (layout
->gdicompatible
)
664 hr
= IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer
, run
->descr
.string
, run
->descr
.clusterMap
,
665 text_props
, run
->descr
.stringLength
, run
->run
.glyphIndices
, glyph_props
, run
->run
.glyphCount
,
666 run
->run
.fontFace
, run
->run
.fontEmSize
, layout
->pixels_per_dip
, &layout
->transform
, layout
->use_gdi_natural
,
667 run
->run
.isSideways
, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
, NULL
, NULL
, 0,
668 run
->advances
, run
->offsets
);
670 hr
= IDWriteTextAnalyzer_GetGlyphPlacements(analyzer
, run
->descr
.string
, run
->descr
.clusterMap
, text_props
,
671 run
->descr
.stringLength
, run
->run
.glyphIndices
, glyph_props
, run
->run
.glyphCount
, run
->run
.fontFace
,
672 run
->run
.fontEmSize
, run
->run
.isSideways
, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
,
673 NULL
, NULL
, 0, run
->advances
, run
->offsets
);
675 heap_free(text_props
);
676 heap_free(glyph_props
);
678 WARN("%s: failed to get glyph placement info, 0x%08x\n", debugstr_run(run
), hr
);
680 run
->run
.glyphAdvances
= run
->advances
;
681 run
->run
.glyphOffsets
= run
->offsets
;
683 layout_set_cluster_metrics(layout
, r
, &cluster
);
688 heap_free(text_props
);
689 heap_free(glyph_props
);
690 heap_free(run
->clustermap
);
691 heap_free(run
->glyphs
);
692 heap_free(run
->advances
);
693 heap_free(run
->offsets
);
694 run
->advances
= NULL
;
696 run
->clustermap
= run
->glyphs
= NULL
;
702 layout
->cluster_count
= cluster
;
704 IDWriteTextAnalyzer_Release(analyzer
);
708 static HRESULT
layout_compute(struct dwrite_textlayout
*layout
)
712 if (!(layout
->recompute
& RECOMPUTE_NOMINAL_RUNS
))
715 /* nominal breakpoints are evaluated only once, because string never changes */
716 if (!layout
->nominal_breakpoints
) {
717 IDWriteTextAnalyzer
*analyzer
;
720 layout
->nominal_breakpoints
= heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
721 if (!layout
->nominal_breakpoints
)
722 return E_OUTOFMEMORY
;
724 hr
= get_textanalyzer(&analyzer
);
728 hr
= IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
729 0, layout
->len
, &layout
->IDWriteTextAnalysisSink_iface
);
730 IDWriteTextAnalyzer_Release(analyzer
);
732 if (layout
->actual_breakpoints
) {
733 heap_free(layout
->actual_breakpoints
);
734 layout
->actual_breakpoints
= NULL
;
737 hr
= layout_compute_runs(layout
);
739 if (TRACE_ON(dwrite
)) {
740 struct layout_run
*cur
;
742 LIST_FOR_EACH_ENTRY(cur
, &layout
->runs
, struct layout_run
, entry
) {
743 if (cur
->kind
== LAYOUT_RUN_INLINE
)
744 TRACE("run inline object %p, len %u\n", cur
->u
.object
.object
, cur
->u
.object
.length
);
746 TRACE("run [%u,%u], len %u, bidilevel %u\n", cur
->u
.regular
.descr
.textPosition
, cur
->u
.regular
.descr
.textPosition
+
747 cur
->u
.regular
.descr
.stringLength
-1, cur
->u
.regular
.descr
.stringLength
, cur
->u
.regular
.run
.bidiLevel
);
751 layout
->recompute
&= ~RECOMPUTE_NOMINAL_RUNS
;
755 static HRESULT
layout_add_effective_run(struct dwrite_textlayout
*layout
, const struct layout_run
*r
, UINT32 start
,
756 UINT32 length
, FLOAT origin_x
)
758 struct layout_effective_run
*run
;
761 run
= heap_alloc(sizeof(*run
));
763 return E_OUTOFMEMORY
;
765 run
->clustermap
= heap_alloc(sizeof(UINT16
)*length
);
766 if (!run
->clustermap
) {
768 return E_OUTOFMEMORY
;
773 run
->length
= length
;
774 run
->origin_x
= origin_x
;
775 run
->origin_y
= 0.0; /* FIXME: set after line is built */
777 /* trim from the left */
778 run
->glyphcount
= r
->u
.regular
.run
.glyphCount
- r
->u
.regular
.clustermap
[start
];
779 /* trim from the right */
780 if (length
< r
->u
.regular
.descr
.stringLength
)
781 run
->glyphcount
-= r
->u
.regular
.clustermap
[start
+ length
];
783 /* cluster map needs to be shifted */
784 for (i
= 0; i
< length
; i
++)
785 run
->clustermap
[i
] = r
->u
.regular
.clustermap
[start
] - start
;
787 list_add_tail(&layout
->eruns
, &run
->entry
);
791 static HRESULT
layout_set_line_metrics(struct dwrite_textlayout
*layout
, DWRITE_LINE_METRICS
*metrics
, UINT32
*line
)
793 if (!layout
->line_alloc
) {
794 layout
->line_alloc
= 5;
795 layout
->lines
= heap_alloc(layout
->line_alloc
*sizeof(*layout
->lines
));
797 return E_OUTOFMEMORY
;
800 if (layout
->line_count
== layout
->line_alloc
) {
801 DWRITE_LINE_METRICS
*l
= heap_realloc(layout
->lines
, layout
->line_alloc
*2*sizeof(*layout
->lines
));
803 return E_OUTOFMEMORY
;
805 layout
->line_alloc
*= 2;
808 layout
->lines
[*line
] = *metrics
;
813 static inline FLOAT
get_cluster_range_width(struct dwrite_textlayout
*layout
, UINT32 start
, UINT32 end
)
816 for (; start
< end
; start
++)
817 width
+= layout
->clustermetrics
[start
].width
;
821 static HRESULT
layout_compute_effective_runs(struct dwrite_textlayout
*layout
)
823 DWRITE_LINE_METRICS metrics
;
824 const struct layout_run
*run
;
825 FLOAT width
, origin_x
;
826 UINT32 i
, start
, line
;
830 if (!(layout
->recompute
& RECOMPUTE_EFFECTIVE_RUNS
))
833 hr
= layout_compute(layout
);
837 layout
->line_count
= 0;
840 run
= layout
->clusters
[0].run
;
841 can_wrap_after
= layout
->clustermetrics
[0].canWrapLineAfter
;
842 memset(&metrics
, 0, sizeof(metrics
));
844 for (i
= 0, start
= 0, width
= 0.0; i
< layout
->cluster_count
; i
++) {
845 if (run
!= layout
->clusters
[i
].run
) {
846 /* switched to next nominal run */
847 hr
= layout_add_effective_run(layout
, run
, start
, i
- start
, origin_x
);
850 origin_x
+= get_cluster_range_width(layout
, start
, i
);
854 /* check if we got new line */
855 if (((can_wrap_after
&& (width
+ layout
->clustermetrics
[i
].width
> layout
->maxwidth
)) ||
856 layout
->clustermetrics
[i
].isNewline
|| /* always wrap on new line */
857 i
== layout
->cluster_count
- 1)) /* end of the text */ {
859 UINT32 strlength
= metrics
.length
, index
= i
;
862 hr
= layout_add_effective_run(layout
, run
, start
, i
- start
, origin_x
);
865 /* we don't need to update origin for next run as we're going to wrap */
868 /* take a look at clusters we got for this line in reverse order */
870 DWRITE_CLUSTER_METRICS
*cluster
= &layout
->clustermetrics
[index
];
872 if (!cluster
->isNewline
&& !cluster
->isWhitespace
)
875 if (cluster
->isNewline
) {
876 metrics
.trailingWhitespaceLength
+= cluster
->length
;
877 metrics
.newlineLength
+= cluster
->length
;
880 if (cluster
->isWhitespace
)
881 metrics
.trailingWhitespaceLength
+= cluster
->length
;
883 strlength
-= cluster
->length
;
887 metrics
.height
= 0.0; /* FIXME */
888 metrics
.baseline
= 0.0; /* FIXME */
889 metrics
.isTrimmed
= width
> layout
->maxwidth
;
890 hr
= layout_set_line_metrics(layout
, &metrics
, &line
);
894 width
= layout
->clustermetrics
[i
].width
;
895 memset(&metrics
, 0, sizeof(metrics
));
900 metrics
.length
+= layout
->clustermetrics
[i
].length
;
901 width
+= layout
->clustermetrics
[i
].width
;
904 can_wrap_after
= layout
->clustermetrics
[i
].canWrapLineAfter
;
907 layout
->line_count
= line
;
908 layout
->recompute
&= ~RECOMPUTE_EFFECTIVE_RUNS
;
912 /* To be used in IDWriteTextLayout methods to validate and fix passed range */
913 static inline BOOL
validate_text_range(struct dwrite_textlayout
*layout
, DWRITE_TEXT_RANGE
*r
)
915 if (r
->startPosition
>= layout
->len
)
918 if (r
->startPosition
+ r
->length
> layout
->len
)
919 r
->length
= layout
->len
- r
->startPosition
;
924 static BOOL
is_same_layout_attrvalue(struct layout_range
const *range
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
927 case LAYOUT_RANGE_ATTR_WEIGHT
:
928 return range
->weight
== value
->u
.weight
;
929 case LAYOUT_RANGE_ATTR_STYLE
:
930 return range
->style
== value
->u
.style
;
931 case LAYOUT_RANGE_ATTR_STRETCH
:
932 return range
->stretch
== value
->u
.stretch
;
933 case LAYOUT_RANGE_ATTR_FONTSIZE
:
934 return range
->fontsize
== value
->u
.fontsize
;
935 case LAYOUT_RANGE_ATTR_INLINE
:
936 return range
->object
== value
->u
.object
;
937 case LAYOUT_RANGE_ATTR_EFFECT
:
938 return range
->effect
== value
->u
.effect
;
939 case LAYOUT_RANGE_ATTR_UNDERLINE
:
940 return range
->underline
== value
->u
.underline
;
941 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
942 return range
->strikethrough
== value
->u
.strikethrough
;
943 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
944 return range
->pair_kerning
== value
->u
.pair_kerning
;
945 case LAYOUT_RANGE_ATTR_FONTCOLL
:
946 return range
->collection
== value
->u
.collection
;
947 case LAYOUT_RANGE_ATTR_LOCALE
:
948 return strcmpW(range
->locale
, value
->u
.locale
) == 0;
949 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
950 return strcmpW(range
->fontfamily
, value
->u
.fontfamily
) == 0;
958 static inline BOOL
is_same_layout_attributes(struct layout_range
const *left
, struct layout_range
const *right
)
960 return left
->weight
== right
->weight
&&
961 left
->style
== right
->style
&&
962 left
->stretch
== right
->stretch
&&
963 left
->fontsize
== right
->fontsize
&&
964 left
->object
== right
->object
&&
965 left
->effect
== right
->effect
&&
966 left
->underline
== right
->underline
&&
967 left
->strikethrough
== right
->strikethrough
&&
968 left
->pair_kerning
== right
->pair_kerning
&&
969 left
->collection
== right
->collection
&&
970 !strcmpW(left
->locale
, right
->locale
) &&
971 !strcmpW(left
->fontfamily
, right
->fontfamily
);
974 static inline BOOL
is_same_text_range(const DWRITE_TEXT_RANGE
*left
, const DWRITE_TEXT_RANGE
*right
)
976 return left
->startPosition
== right
->startPosition
&& left
->length
== right
->length
;
979 /* Allocates range and inits it with default values from text format. */
980 static struct layout_range
*alloc_layout_range(struct dwrite_textlayout
*layout
, const DWRITE_TEXT_RANGE
*r
)
982 struct layout_range
*range
;
984 range
= heap_alloc(sizeof(*range
));
985 if (!range
) return NULL
;
988 range
->weight
= layout
->format
.weight
;
989 range
->style
= layout
->format
.style
;
990 range
->stretch
= layout
->format
.stretch
;
991 range
->fontsize
= layout
->format
.fontsize
;
992 range
->object
= NULL
;
993 range
->effect
= NULL
;
994 range
->underline
= FALSE
;
995 range
->strikethrough
= FALSE
;
996 range
->pair_kerning
= FALSE
;
998 range
->fontfamily
= heap_strdupW(layout
->format
.family_name
);
999 if (!range
->fontfamily
) {
1004 range
->collection
= layout
->format
.collection
;
1005 if (range
->collection
)
1006 IDWriteFontCollection_AddRef(range
->collection
);
1007 strcpyW(range
->locale
, layout
->format
.locale
);
1012 static struct layout_range
*alloc_layout_range_from(struct layout_range
*from
, const DWRITE_TEXT_RANGE
*r
)
1014 struct layout_range
*range
;
1016 range
= heap_alloc(sizeof(*range
));
1017 if (!range
) return NULL
;
1022 range
->fontfamily
= heap_strdupW(from
->fontfamily
);
1023 if (!range
->fontfamily
) {
1028 /* update refcounts */
1030 IDWriteInlineObject_AddRef(range
->object
);
1032 IUnknown_AddRef(range
->effect
);
1033 if (range
->collection
)
1034 IDWriteFontCollection_AddRef(range
->collection
);
1039 static void free_layout_range(struct layout_range
*range
)
1044 IDWriteInlineObject_Release(range
->object
);
1046 IUnknown_Release(range
->effect
);
1047 if (range
->collection
)
1048 IDWriteFontCollection_Release(range
->collection
);
1049 heap_free(range
->fontfamily
);
1053 static void free_layout_ranges_list(struct dwrite_textlayout
*layout
)
1055 struct layout_range
*cur
, *cur2
;
1056 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->ranges
, struct layout_range
, entry
) {
1057 list_remove(&cur
->entry
);
1058 free_layout_range(cur
);
1062 static struct layout_range
*find_outer_range(struct dwrite_textlayout
*layout
, const DWRITE_TEXT_RANGE
*range
)
1064 struct layout_range
*cur
;
1066 LIST_FOR_EACH_ENTRY(cur
, &layout
->ranges
, struct layout_range
, entry
) {
1068 if (cur
->range
.startPosition
> range
->startPosition
)
1071 if ((cur
->range
.startPosition
+ cur
->range
.length
< range
->startPosition
+ range
->length
) &&
1072 (range
->startPosition
< cur
->range
.startPosition
+ cur
->range
.length
))
1074 if (cur
->range
.startPosition
+ cur
->range
.length
>= range
->startPosition
+ range
->length
)
1081 static struct layout_range
*get_layout_range_by_pos(struct dwrite_textlayout
*layout
, UINT32 pos
)
1083 struct layout_range
*cur
;
1085 LIST_FOR_EACH_ENTRY(cur
, &layout
->ranges
, struct layout_range
, entry
) {
1086 DWRITE_TEXT_RANGE
*r
= &cur
->range
;
1087 if (r
->startPosition
<= pos
&& pos
< r
->startPosition
+ r
->length
)
1094 static inline BOOL
set_layout_range_iface_attr(IUnknown
**dest
, IUnknown
*value
)
1096 if (*dest
== value
) return FALSE
;
1099 IUnknown_Release(*dest
);
1102 IUnknown_AddRef(*dest
);
1107 static BOOL
set_layout_range_attrval(struct layout_range
*dest
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
1109 BOOL changed
= FALSE
;
1112 case LAYOUT_RANGE_ATTR_WEIGHT
:
1113 changed
= dest
->weight
!= value
->u
.weight
;
1114 dest
->weight
= value
->u
.weight
;
1116 case LAYOUT_RANGE_ATTR_STYLE
:
1117 changed
= dest
->style
!= value
->u
.style
;
1118 dest
->style
= value
->u
.style
;
1120 case LAYOUT_RANGE_ATTR_STRETCH
:
1121 changed
= dest
->stretch
!= value
->u
.stretch
;
1122 dest
->stretch
= value
->u
.stretch
;
1124 case LAYOUT_RANGE_ATTR_FONTSIZE
:
1125 changed
= dest
->fontsize
!= value
->u
.fontsize
;
1126 dest
->fontsize
= value
->u
.fontsize
;
1128 case LAYOUT_RANGE_ATTR_INLINE
:
1129 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->object
, (IUnknown
*)value
->u
.object
);
1131 case LAYOUT_RANGE_ATTR_EFFECT
:
1132 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->effect
, (IUnknown
*)value
->u
.effect
);
1134 case LAYOUT_RANGE_ATTR_UNDERLINE
:
1135 changed
= dest
->underline
!= value
->u
.underline
;
1136 dest
->underline
= value
->u
.underline
;
1138 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
1139 changed
= dest
->strikethrough
!= value
->u
.strikethrough
;
1140 dest
->strikethrough
= value
->u
.strikethrough
;
1142 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
1143 changed
= dest
->pair_kerning
!= value
->u
.pair_kerning
;
1144 dest
->pair_kerning
= value
->u
.pair_kerning
;
1146 case LAYOUT_RANGE_ATTR_FONTCOLL
:
1147 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->collection
, (IUnknown
*)value
->u
.collection
);
1149 case LAYOUT_RANGE_ATTR_LOCALE
:
1150 changed
= strcmpW(dest
->locale
, value
->u
.locale
) != 0;
1152 strcpyW(dest
->locale
, value
->u
.locale
);
1154 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1155 changed
= strcmpW(dest
->fontfamily
, value
->u
.fontfamily
) != 0;
1157 heap_free(dest
->fontfamily
);
1158 dest
->fontfamily
= heap_strdupW(value
->u
.fontfamily
);
1168 static inline BOOL
is_in_layout_range(const DWRITE_TEXT_RANGE
*outer
, const DWRITE_TEXT_RANGE
*inner
)
1170 return (inner
->startPosition
>= outer
->startPosition
) &&
1171 (inner
->startPosition
+ inner
->length
<= outer
->startPosition
+ outer
->length
);
1174 static inline HRESULT
return_range(const struct layout_range
*range
, DWRITE_TEXT_RANGE
*r
)
1176 if (r
) *r
= range
->range
;
1180 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
1181 static HRESULT
set_layout_range_attr(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
1183 struct layout_range
*outer
, *right
, *left
, *cur
;
1184 struct list
*ranges
= &layout
->ranges
;
1185 BOOL changed
= FALSE
;
1186 DWRITE_TEXT_RANGE r
;
1188 if (!validate_text_range(layout
, &value
->range
))
1191 /* If new range is completely within existing range, split existing range in two */
1192 if ((outer
= find_outer_range(layout
, &value
->range
))) {
1194 /* no need to add same range */
1195 if (is_same_layout_attrvalue(outer
, attr
, value
))
1198 /* for matching range bounds just replace data */
1199 if (is_same_text_range(&outer
->range
, &value
->range
)) {
1200 changed
= set_layout_range_attrval(outer
, attr
, value
);
1204 /* add new range to the left */
1205 if (value
->range
.startPosition
== outer
->range
.startPosition
) {
1206 left
= alloc_layout_range_from(outer
, &value
->range
);
1207 if (!left
) return E_OUTOFMEMORY
;
1209 changed
= set_layout_range_attrval(left
, attr
, value
);
1210 list_add_before(&outer
->entry
, &left
->entry
);
1211 outer
->range
.startPosition
+= value
->range
.length
;
1212 outer
->range
.length
-= value
->range
.length
;
1216 /* add new range to the right */
1217 if (value
->range
.startPosition
+ value
->range
.length
== outer
->range
.startPosition
+ outer
->range
.length
) {
1218 right
= alloc_layout_range_from(outer
, &value
->range
);
1219 if (!right
) return E_OUTOFMEMORY
;
1221 changed
= set_layout_range_attrval(right
, attr
, value
);
1222 list_add_after(&outer
->entry
, &right
->entry
);
1223 outer
->range
.length
-= value
->range
.length
;
1227 r
.startPosition
= value
->range
.startPosition
+ value
->range
.length
;
1228 r
.length
= outer
->range
.length
+ outer
->range
.startPosition
- r
.startPosition
;
1231 right
= alloc_layout_range_from(outer
, &r
);
1232 /* new range in the middle */
1233 cur
= alloc_layout_range_from(outer
, &value
->range
);
1234 if (!right
|| !cur
) {
1235 free_layout_range(right
);
1236 free_layout_range(cur
);
1237 return E_OUTOFMEMORY
;
1240 /* reuse container range as a left part */
1241 outer
->range
.length
= value
->range
.startPosition
- outer
->range
.startPosition
;
1244 set_layout_range_attrval(cur
, attr
, value
);
1246 list_add_after(&outer
->entry
, &cur
->entry
);
1247 list_add_after(&cur
->entry
, &right
->entry
);
1252 /* Now it's only possible that given range contains some existing ranges, fully or partially.
1253 Update all of them. */
1254 left
= get_layout_range_by_pos(layout
, value
->range
.startPosition
);
1255 if (left
->range
.startPosition
== value
->range
.startPosition
)
1256 changed
= set_layout_range_attrval(left
, attr
, value
);
1257 else /* need to split */ {
1258 r
.startPosition
= value
->range
.startPosition
;
1259 r
.length
= left
->range
.length
- value
->range
.startPosition
+ left
->range
.startPosition
;
1260 left
->range
.length
-= r
.length
;
1261 cur
= alloc_layout_range_from(left
, &r
);
1262 changed
= set_layout_range_attrval(cur
, attr
, value
);
1263 list_add_after(&left
->entry
, &cur
->entry
);
1265 cur
= LIST_ENTRY(list_next(ranges
, &left
->entry
), struct layout_range
, entry
);
1267 /* for all existing ranges covered by new one update value */
1268 while (is_in_layout_range(&value
->range
, &cur
->range
)) {
1269 changed
= set_layout_range_attrval(cur
, attr
, value
);
1270 cur
= LIST_ENTRY(list_next(ranges
, &cur
->entry
), struct layout_range
, entry
);
1273 /* it's possible rightmost range intersects */
1274 if (cur
&& (cur
->range
.startPosition
< value
->range
.startPosition
+ value
->range
.length
)) {
1275 r
.startPosition
= cur
->range
.startPosition
;
1276 r
.length
= value
->range
.startPosition
+ value
->range
.length
- cur
->range
.startPosition
;
1277 left
= alloc_layout_range_from(cur
, &r
);
1278 changed
= set_layout_range_attrval(left
, attr
, value
);
1279 cur
->range
.startPosition
+= left
->range
.length
;
1280 cur
->range
.length
-= left
->range
.length
;
1281 list_add_before(&cur
->entry
, &left
->entry
);
1286 struct list
*next
, *i
;
1288 layout
->recompute
= RECOMPUTE_EVERYTHING
;
1289 i
= list_head(ranges
);
1290 while ((next
= list_next(ranges
, i
))) {
1291 struct layout_range
*next_range
= LIST_ENTRY(next
, struct layout_range
, entry
);
1293 cur
= LIST_ENTRY(i
, struct layout_range
, entry
);
1294 if (is_same_layout_attributes(cur
, next_range
)) {
1295 /* remove similar range */
1296 cur
->range
.length
+= next_range
->range
.length
;
1298 free_layout_range(next_range
);
1301 i
= list_next(ranges
, i
);
1308 static inline const WCHAR
*get_string_attribute_ptr(struct layout_range
*range
, enum layout_range_attr_kind kind
)
1313 case LAYOUT_RANGE_ATTR_LOCALE
:
1314 str
= range
->locale
;
1316 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1317 str
= range
->fontfamily
;
1326 static HRESULT
get_string_attribute_length(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind kind
, UINT32 position
,
1327 UINT32
*length
, DWRITE_TEXT_RANGE
*r
)
1329 struct layout_range
*range
;
1332 range
= get_layout_range_by_pos(layout
, position
);
1338 str
= get_string_attribute_ptr(range
, kind
);
1339 *length
= strlenW(str
);
1340 return return_range(range
, r
);
1343 static HRESULT
get_string_attribute_value(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind kind
, UINT32 position
,
1344 WCHAR
*ret
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1346 struct layout_range
*range
;
1350 return E_INVALIDARG
;
1353 range
= get_layout_range_by_pos(layout
, position
);
1355 return E_INVALIDARG
;
1357 str
= get_string_attribute_ptr(range
, kind
);
1358 if (length
< strlenW(str
) + 1)
1359 return E_NOT_SUFFICIENT_BUFFER
;
1362 return return_range(range
, r
);
1365 static HRESULT WINAPI
dwritetextlayout_QueryInterface(IDWriteTextLayout2
*iface
, REFIID riid
, void **obj
)
1367 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1369 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1373 if (IsEqualIID(riid
, &IID_IDWriteTextLayout2
) ||
1374 IsEqualIID(riid
, &IID_IDWriteTextLayout1
) ||
1375 IsEqualIID(riid
, &IID_IDWriteTextLayout
) ||
1376 IsEqualIID(riid
, &IID_IUnknown
))
1380 else if (IsEqualIID(riid
, &IID_IDWriteTextFormat1
) ||
1381 IsEqualIID(riid
, &IID_IDWriteTextFormat
))
1382 *obj
= &This
->IDWriteTextFormat1_iface
;
1385 IDWriteTextLayout2_AddRef(iface
);
1389 return E_NOINTERFACE
;
1392 static ULONG WINAPI
dwritetextlayout_AddRef(IDWriteTextLayout2
*iface
)
1394 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1395 ULONG ref
= InterlockedIncrement(&This
->ref
);
1396 TRACE("(%p)->(%d)\n", This
, ref
);
1400 static ULONG WINAPI
dwritetextlayout_Release(IDWriteTextLayout2
*iface
)
1402 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1403 ULONG ref
= InterlockedDecrement(&This
->ref
);
1405 TRACE("(%p)->(%d)\n", This
, ref
);
1408 free_layout_ranges_list(This
);
1409 free_layout_eruns(This
);
1410 free_layout_runs(This
);
1411 release_format_data(&This
->format
);
1412 heap_free(This
->nominal_breakpoints
);
1413 heap_free(This
->actual_breakpoints
);
1414 heap_free(This
->clustermetrics
);
1415 heap_free(This
->clusters
);
1416 heap_free(This
->lines
);
1417 heap_free(This
->str
);
1424 static HRESULT WINAPI
dwritetextlayout_SetTextAlignment(IDWriteTextLayout2
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
1426 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1427 TRACE("(%p)->(%d)\n", This
, alignment
);
1428 return IDWriteTextFormat1_SetTextAlignment(&This
->IDWriteTextFormat1_iface
, alignment
);
1431 static HRESULT WINAPI
dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout2
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
1433 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1434 TRACE("(%p)->(%d)\n", This
, alignment
);
1435 return IDWriteTextFormat1_SetParagraphAlignment(&This
->IDWriteTextFormat1_iface
, alignment
);
1438 static HRESULT WINAPI
dwritetextlayout_SetWordWrapping(IDWriteTextLayout2
*iface
, DWRITE_WORD_WRAPPING wrapping
)
1440 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1441 TRACE("(%p)->(%d)\n", This
, wrapping
);
1442 return IDWriteTextFormat1_SetWordWrapping(&This
->IDWriteTextFormat1_iface
, wrapping
);
1445 static HRESULT WINAPI
dwritetextlayout_SetReadingDirection(IDWriteTextLayout2
*iface
, DWRITE_READING_DIRECTION direction
)
1447 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1448 TRACE("(%p)->(%d)\n", This
, direction
);
1449 return IDWriteTextFormat1_SetReadingDirection(&This
->IDWriteTextFormat1_iface
, direction
);
1452 static HRESULT WINAPI
dwritetextlayout_SetFlowDirection(IDWriteTextLayout2
*iface
, DWRITE_FLOW_DIRECTION direction
)
1454 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1455 TRACE("(%p)->(%d)\n", This
, direction
);
1456 return IDWriteTextFormat1_SetFlowDirection(&This
->IDWriteTextFormat1_iface
, direction
);
1459 static HRESULT WINAPI
dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout2
*iface
, FLOAT tabstop
)
1461 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1462 TRACE("(%p)->(%.2f)\n", This
, tabstop
);
1463 return IDWriteTextFormat1_SetIncrementalTabStop(&This
->IDWriteTextFormat1_iface
, tabstop
);
1466 static HRESULT WINAPI
dwritetextlayout_SetTrimming(IDWriteTextLayout2
*iface
, DWRITE_TRIMMING
const *trimming
,
1467 IDWriteInlineObject
*trimming_sign
)
1469 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1470 TRACE("(%p)->(%p %p)\n", This
, trimming
, trimming_sign
);
1471 return IDWriteTextFormat1_SetTrimming(&This
->IDWriteTextFormat1_iface
, trimming
, trimming_sign
);
1474 static HRESULT WINAPI
dwritetextlayout_SetLineSpacing(IDWriteTextLayout2
*iface
, DWRITE_LINE_SPACING_METHOD spacing
,
1475 FLOAT line_spacing
, FLOAT baseline
)
1477 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1478 TRACE("(%p)->(%d %.2f %.2f)\n", This
, spacing
, line_spacing
, baseline
);
1479 return IDWriteTextFormat1_SetLineSpacing(&This
->IDWriteTextFormat1_iface
, spacing
, line_spacing
, baseline
);
1482 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextlayout_GetTextAlignment(IDWriteTextLayout2
*iface
)
1484 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1485 TRACE("(%p)\n", This
);
1486 return IDWriteTextFormat1_GetTextAlignment(&This
->IDWriteTextFormat1_iface
);
1489 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout2
*iface
)
1491 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1492 TRACE("(%p)\n", This
);
1493 return IDWriteTextFormat1_GetParagraphAlignment(&This
->IDWriteTextFormat1_iface
);
1496 static DWRITE_WORD_WRAPPING WINAPI
dwritetextlayout_GetWordWrapping(IDWriteTextLayout2
*iface
)
1498 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1499 TRACE("(%p)\n", This
);
1500 return IDWriteTextFormat1_GetWordWrapping(&This
->IDWriteTextFormat1_iface
);
1503 static DWRITE_READING_DIRECTION WINAPI
dwritetextlayout_GetReadingDirection(IDWriteTextLayout2
*iface
)
1505 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1506 TRACE("(%p)\n", This
);
1507 return IDWriteTextFormat1_GetReadingDirection(&This
->IDWriteTextFormat1_iface
);
1510 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextlayout_GetFlowDirection(IDWriteTextLayout2
*iface
)
1512 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1513 TRACE("(%p)\n", This
);
1514 return IDWriteTextFormat1_GetFlowDirection(&This
->IDWriteTextFormat1_iface
);
1517 static FLOAT WINAPI
dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout2
*iface
)
1519 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1520 TRACE("(%p)\n", This
);
1521 return IDWriteTextFormat1_GetIncrementalTabStop(&This
->IDWriteTextFormat1_iface
);
1524 static HRESULT WINAPI
dwritetextlayout_GetTrimming(IDWriteTextLayout2
*iface
, DWRITE_TRIMMING
*options
,
1525 IDWriteInlineObject
**trimming_sign
)
1527 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1528 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
1529 return IDWriteTextFormat1_GetTrimming(&This
->IDWriteTextFormat1_iface
, options
, trimming_sign
);
1532 static HRESULT WINAPI
dwritetextlayout_GetLineSpacing(IDWriteTextLayout2
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
1533 FLOAT
*spacing
, FLOAT
*baseline
)
1535 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1536 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
1537 return IDWriteTextFormat1_GetLineSpacing(&This
->IDWriteTextFormat1_iface
, method
, spacing
, baseline
);
1540 static HRESULT WINAPI
dwritetextlayout_GetFontCollection(IDWriteTextLayout2
*iface
, IDWriteFontCollection
**collection
)
1542 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1543 TRACE("(%p)->(%p)\n", This
, collection
);
1544 return IDWriteTextFormat1_GetFontCollection(&This
->IDWriteTextFormat1_iface
, collection
);
1547 static UINT32 WINAPI
dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout2
*iface
)
1549 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1550 TRACE("(%p)\n", This
);
1551 return IDWriteTextFormat1_GetFontFamilyNameLength(&This
->IDWriteTextFormat1_iface
);
1554 static HRESULT WINAPI
dwritetextlayout_GetFontFamilyName(IDWriteTextLayout2
*iface
, WCHAR
*name
, UINT32 size
)
1556 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1557 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
1558 return IDWriteTextFormat1_GetFontFamilyName(&This
->IDWriteTextFormat1_iface
, name
, size
);
1561 static DWRITE_FONT_WEIGHT WINAPI
dwritetextlayout_GetFontWeight(IDWriteTextLayout2
*iface
)
1563 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1564 TRACE("(%p)\n", This
);
1565 return IDWriteTextFormat1_GetFontWeight(&This
->IDWriteTextFormat1_iface
);
1568 static DWRITE_FONT_STYLE WINAPI
dwritetextlayout_GetFontStyle(IDWriteTextLayout2
*iface
)
1570 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1571 TRACE("(%p)\n", This
);
1572 return IDWriteTextFormat1_GetFontStyle(&This
->IDWriteTextFormat1_iface
);
1575 static DWRITE_FONT_STRETCH WINAPI
dwritetextlayout_GetFontStretch(IDWriteTextLayout2
*iface
)
1577 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1578 TRACE("(%p)\n", This
);
1579 return IDWriteTextFormat1_GetFontStretch(&This
->IDWriteTextFormat1_iface
);
1582 static FLOAT WINAPI
dwritetextlayout_GetFontSize(IDWriteTextLayout2
*iface
)
1584 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1585 TRACE("(%p)\n", This
);
1586 return IDWriteTextFormat1_GetFontSize(&This
->IDWriteTextFormat1_iface
);
1589 static UINT32 WINAPI
dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout2
*iface
)
1591 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1592 TRACE("(%p)\n", This
);
1593 return IDWriteTextFormat1_GetLocaleNameLength(&This
->IDWriteTextFormat1_iface
);
1596 static HRESULT WINAPI
dwritetextlayout_GetLocaleName(IDWriteTextLayout2
*iface
, WCHAR
*name
, UINT32 size
)
1598 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1599 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
1600 return IDWriteTextFormat1_GetLocaleName(&This
->IDWriteTextFormat1_iface
, name
, size
);
1603 static HRESULT WINAPI
dwritetextlayout_SetMaxWidth(IDWriteTextLayout2
*iface
, FLOAT maxWidth
)
1605 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1606 TRACE("(%p)->(%.1f)\n", This
, maxWidth
);
1609 return E_INVALIDARG
;
1611 This
->maxwidth
= maxWidth
;
1615 static HRESULT WINAPI
dwritetextlayout_SetMaxHeight(IDWriteTextLayout2
*iface
, FLOAT maxHeight
)
1617 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1618 TRACE("(%p)->(%.1f)\n", This
, maxHeight
);
1620 if (maxHeight
< 0.0)
1621 return E_INVALIDARG
;
1623 This
->maxheight
= maxHeight
;
1627 static HRESULT WINAPI
dwritetextlayout_SetFontCollection(IDWriteTextLayout2
*iface
, IDWriteFontCollection
* collection
, DWRITE_TEXT_RANGE range
)
1629 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1630 struct layout_range_attr_value value
;
1632 TRACE("(%p)->(%p %s)\n", This
, collection
, debugstr_range(&range
));
1634 value
.range
= range
;
1635 value
.u
.collection
= collection
;
1636 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTCOLL
, &value
);
1639 static HRESULT WINAPI
dwritetextlayout_SetFontFamilyName(IDWriteTextLayout2
*iface
, WCHAR
const *name
, DWRITE_TEXT_RANGE range
)
1641 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1642 struct layout_range_attr_value value
;
1644 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(name
), debugstr_range(&range
));
1647 return E_INVALIDARG
;
1649 value
.range
= range
;
1650 value
.u
.fontfamily
= name
;
1651 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, &value
);
1654 static HRESULT WINAPI
dwritetextlayout_SetFontWeight(IDWriteTextLayout2
*iface
, DWRITE_FONT_WEIGHT weight
, DWRITE_TEXT_RANGE range
)
1656 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1657 struct layout_range_attr_value value
;
1659 TRACE("(%p)->(%d %s)\n", This
, weight
, debugstr_range(&range
));
1661 value
.range
= range
;
1662 value
.u
.weight
= weight
;
1663 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_WEIGHT
, &value
);
1666 static HRESULT WINAPI
dwritetextlayout_SetFontStyle(IDWriteTextLayout2
*iface
, DWRITE_FONT_STYLE style
, DWRITE_TEXT_RANGE range
)
1668 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1669 struct layout_range_attr_value value
;
1671 TRACE("(%p)->(%d %s)\n", This
, style
, debugstr_range(&range
));
1673 value
.range
= range
;
1674 value
.u
.style
= style
;
1675 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STYLE
, &value
);
1678 static HRESULT WINAPI
dwritetextlayout_SetFontStretch(IDWriteTextLayout2
*iface
, DWRITE_FONT_STRETCH stretch
, DWRITE_TEXT_RANGE range
)
1680 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1681 struct layout_range_attr_value value
;
1683 TRACE("(%p)->(%d %s)\n", This
, stretch
, debugstr_range(&range
));
1685 value
.range
= range
;
1686 value
.u
.stretch
= stretch
;
1687 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STRETCH
, &value
);
1690 static HRESULT WINAPI
dwritetextlayout_SetFontSize(IDWriteTextLayout2
*iface
, FLOAT size
, DWRITE_TEXT_RANGE range
)
1692 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1693 struct layout_range_attr_value value
;
1695 TRACE("(%p)->(%.2f %s)\n", This
, size
, debugstr_range(&range
));
1697 value
.range
= range
;
1698 value
.u
.fontsize
= size
;
1699 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTSIZE
, &value
);
1702 static HRESULT WINAPI
dwritetextlayout_SetUnderline(IDWriteTextLayout2
*iface
, BOOL underline
, DWRITE_TEXT_RANGE range
)
1704 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1705 struct layout_range_attr_value value
;
1707 TRACE("(%p)->(%d %s)\n", This
, underline
, debugstr_range(&range
));
1709 value
.range
= range
;
1710 value
.u
.underline
= underline
;
1711 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_UNDERLINE
, &value
);
1714 static HRESULT WINAPI
dwritetextlayout_SetStrikethrough(IDWriteTextLayout2
*iface
, BOOL strikethrough
, DWRITE_TEXT_RANGE range
)
1716 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1717 struct layout_range_attr_value value
;
1719 TRACE("(%p)->(%d %s)\n", This
, strikethrough
, debugstr_range(&range
));
1721 value
.range
= range
;
1722 value
.u
.strikethrough
= strikethrough
;
1723 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STRIKETHROUGH
, &value
);
1726 static HRESULT WINAPI
dwritetextlayout_SetDrawingEffect(IDWriteTextLayout2
*iface
, IUnknown
* effect
, DWRITE_TEXT_RANGE range
)
1728 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1729 struct layout_range_attr_value value
;
1731 TRACE("(%p)->(%p %s)\n", This
, effect
, debugstr_range(&range
));
1733 value
.range
= range
;
1734 value
.u
.effect
= effect
;
1735 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_EFFECT
, &value
);
1738 static HRESULT WINAPI
dwritetextlayout_SetInlineObject(IDWriteTextLayout2
*iface
, IDWriteInlineObject
*object
, DWRITE_TEXT_RANGE range
)
1740 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1741 struct layout_range_attr_value value
;
1743 TRACE("(%p)->(%p %s)\n", This
, object
, debugstr_range(&range
));
1745 value
.range
= range
;
1746 value
.u
.object
= object
;
1747 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_INLINE
, &value
);
1750 static HRESULT WINAPI
dwritetextlayout_SetTypography(IDWriteTextLayout2
*iface
, IDWriteTypography
* typography
, DWRITE_TEXT_RANGE range
)
1752 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1753 FIXME("(%p)->(%p %s): stub\n", This
, typography
, debugstr_range(&range
));
1757 static HRESULT WINAPI
dwritetextlayout_SetLocaleName(IDWriteTextLayout2
*iface
, WCHAR
const* locale
, DWRITE_TEXT_RANGE range
)
1759 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1760 struct layout_range_attr_value value
;
1762 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(locale
), debugstr_range(&range
));
1764 if (!locale
|| strlenW(locale
) > LOCALE_NAME_MAX_LENGTH
-1)
1765 return E_INVALIDARG
;
1767 value
.range
= range
;
1768 value
.u
.locale
= locale
;
1769 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_LOCALE
, &value
);
1772 static FLOAT WINAPI
dwritetextlayout_GetMaxWidth(IDWriteTextLayout2
*iface
)
1774 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1775 TRACE("(%p)\n", This
);
1776 return This
->maxwidth
;
1779 static FLOAT WINAPI
dwritetextlayout_GetMaxHeight(IDWriteTextLayout2
*iface
)
1781 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1782 TRACE("(%p)\n", This
);
1783 return This
->maxheight
;
1786 static HRESULT WINAPI
dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout2
*iface
, UINT32 position
,
1787 IDWriteFontCollection
** collection
, DWRITE_TEXT_RANGE
*r
)
1789 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1790 struct layout_range
*range
;
1792 TRACE("(%p)->(%u %p %p)\n", This
, position
, collection
, r
);
1794 range
= get_layout_range_by_pos(This
, position
);
1795 *collection
= range
? range
->collection
: NULL
;
1797 IDWriteFontCollection_AddRef(*collection
);
1799 return return_range(range
, r
);
1802 static HRESULT WINAPI
dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout2
*iface
,
1803 UINT32 position
, UINT32
*length
, DWRITE_TEXT_RANGE
*r
)
1805 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1806 TRACE("(%p)->(%d %p %p)\n", This
, position
, length
, r
);
1807 return get_string_attribute_length(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, position
, length
, r
);
1810 static HRESULT WINAPI
dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout2
*iface
,
1811 UINT32 position
, WCHAR
*name
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1813 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1814 TRACE("(%p)->(%u %p %u %p)\n", This
, position
, name
, length
, r
);
1815 return get_string_attribute_value(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, position
, name
, length
, r
);
1818 static HRESULT WINAPI
dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout2
*iface
,
1819 UINT32 position
, DWRITE_FONT_WEIGHT
*weight
, DWRITE_TEXT_RANGE
*r
)
1821 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1822 struct layout_range
*range
;
1824 TRACE("(%p)->(%u %p %p)\n", This
, position
, weight
, r
);
1826 if (position
>= This
->len
)
1829 range
= get_layout_range_by_pos(This
, position
);
1830 *weight
= range
->weight
;
1832 return return_range(range
, r
);
1835 static HRESULT WINAPI
dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout2
*iface
,
1836 UINT32 position
, DWRITE_FONT_STYLE
*style
, DWRITE_TEXT_RANGE
*r
)
1838 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1839 struct layout_range
*range
;
1841 TRACE("(%p)->(%u %p %p)\n", This
, position
, style
, r
);
1843 if (position
>= This
->len
)
1846 range
= get_layout_range_by_pos(This
, position
);
1847 *style
= range
->style
;
1849 return return_range(range
, r
);
1852 static HRESULT WINAPI
dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout2
*iface
,
1853 UINT32 position
, DWRITE_FONT_STRETCH
*stretch
, DWRITE_TEXT_RANGE
*r
)
1855 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1856 struct layout_range
*range
;
1858 TRACE("(%p)->(%u %p %p)\n", This
, position
, stretch
, r
);
1860 if (position
>= This
->len
)
1863 range
= get_layout_range_by_pos(This
, position
);
1864 *stretch
= range
->stretch
;
1866 return return_range(range
, r
);
1869 static HRESULT WINAPI
dwritetextlayout_layout_GetFontSize(IDWriteTextLayout2
*iface
,
1870 UINT32 position
, FLOAT
*size
, DWRITE_TEXT_RANGE
*r
)
1872 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1873 struct layout_range
*range
;
1875 TRACE("(%p)->(%u %p %p)\n", This
, position
, size
, r
);
1877 if (position
>= This
->len
)
1880 range
= get_layout_range_by_pos(This
, position
);
1881 *size
= range
->fontsize
;
1883 return return_range(range
, r
);
1886 static HRESULT WINAPI
dwritetextlayout_GetUnderline(IDWriteTextLayout2
*iface
,
1887 UINT32 position
, BOOL
*underline
, DWRITE_TEXT_RANGE
*r
)
1889 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1890 struct layout_range
*range
;
1892 TRACE("(%p)->(%u %p %p)\n", This
, position
, underline
, r
);
1894 if (position
>= This
->len
)
1897 range
= get_layout_range_by_pos(This
, position
);
1898 *underline
= range
->underline
;
1900 return return_range(range
, r
);
1903 static HRESULT WINAPI
dwritetextlayout_GetStrikethrough(IDWriteTextLayout2
*iface
,
1904 UINT32 position
, BOOL
*strikethrough
, DWRITE_TEXT_RANGE
*r
)
1906 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1907 struct layout_range
*range
;
1909 TRACE("(%p)->(%u %p %p)\n", This
, position
, strikethrough
, r
);
1911 if (position
>= This
->len
)
1914 range
= get_layout_range_by_pos(This
, position
);
1915 *strikethrough
= range
->strikethrough
;
1917 return return_range(range
, r
);
1920 static HRESULT WINAPI
dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2
*iface
,
1921 UINT32 position
, IUnknown
**effect
, DWRITE_TEXT_RANGE
*r
)
1923 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1924 struct layout_range
*range
;
1926 TRACE("(%p)->(%u %p %p)\n", This
, position
, effect
, r
);
1928 if (position
>= This
->len
)
1931 range
= get_layout_range_by_pos(This
, position
);
1932 *effect
= range
->effect
;
1934 IUnknown_AddRef(*effect
);
1936 return return_range(range
, r
);
1939 static HRESULT WINAPI
dwritetextlayout_GetInlineObject(IDWriteTextLayout2
*iface
,
1940 UINT32 position
, IDWriteInlineObject
**object
, DWRITE_TEXT_RANGE
*r
)
1942 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1943 struct layout_range
*range
;
1945 TRACE("(%p)->(%u %p %p)\n", This
, position
, object
, r
);
1947 range
= get_layout_range_by_pos(This
, position
);
1948 *object
= range
? range
->object
: NULL
;
1950 IDWriteInlineObject_AddRef(*object
);
1952 return return_range(range
, r
);
1955 static HRESULT WINAPI
dwritetextlayout_GetTypography(IDWriteTextLayout2
*iface
,
1956 UINT32 position
, IDWriteTypography
** typography
, DWRITE_TEXT_RANGE
*range
)
1958 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1959 FIXME("(%p)->(%u %p %p): stub\n", This
, position
, typography
, range
);
1963 static HRESULT WINAPI
dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2
*iface
,
1964 UINT32 position
, UINT32
* length
, DWRITE_TEXT_RANGE
*r
)
1966 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1967 TRACE("(%p)->(%u %p %p)\n", This
, position
, length
, r
);
1968 return get_string_attribute_length(This
, LAYOUT_RANGE_ATTR_LOCALE
, position
, length
, r
);
1971 static HRESULT WINAPI
dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout2
*iface
,
1972 UINT32 position
, WCHAR
* locale
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1974 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1975 TRACE("(%p)->(%u %p %u %p)\n", This
, position
, locale
, length
, r
);
1976 return get_string_attribute_value(This
, LAYOUT_RANGE_ATTR_LOCALE
, position
, locale
, length
, r
);
1979 static HRESULT WINAPI
dwritetextlayout_Draw(IDWriteTextLayout2
*iface
,
1980 void *context
, IDWriteTextRenderer
* renderer
, FLOAT origin_x
, FLOAT origin_y
)
1982 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1983 struct layout_effective_run
*run
;
1986 TRACE("(%p)->(%p %p %.2f %.2f)\n", This
, context
, renderer
, origin_x
, origin_y
);
1988 hr
= layout_compute_effective_runs(This
);
1992 /* 1. Regular runs */
1993 LIST_FOR_EACH_ENTRY(run
, &This
->eruns
, struct layout_effective_run
, entry
) {
1994 const struct regular_layout_run
*regular
= &run
->run
->u
.regular
;
1995 UINT32 start_glyph
= regular
->clustermap
[run
->start
];
1996 DWRITE_GLYPH_RUN_DESCRIPTION descr
;
1997 DWRITE_GLYPH_RUN glyph_run
;
1999 /* Everything but cluster map will be reused from nominal run, as we only need
2000 to adjust some pointers. Cluster map however is rebuilt when effective run is added,
2001 it can't be reused because it has to start with 0 index for each reported run. */
2002 glyph_run
= regular
->run
;
2003 glyph_run
.glyphCount
= run
->glyphcount
;
2005 /* fixup glyph data arrays */
2006 glyph_run
.glyphIndices
+= start_glyph
;
2007 glyph_run
.glyphAdvances
+= start_glyph
;
2008 glyph_run
.glyphOffsets
+= start_glyph
;
2011 descr
= regular
->descr
;
2012 descr
.stringLength
= run
->length
;
2013 descr
.string
+= run
->start
;
2014 descr
.clusterMap
= run
->clustermap
;
2015 descr
.textPosition
+= run
->start
;
2017 /* return value is ignored */
2018 IDWriteTextRenderer_DrawGlyphRun(renderer
,
2020 run
->origin_x
+ origin_x
,
2021 run
->origin_y
+ origin_y
,
2022 DWRITE_MEASURING_MODE_NATURAL
,
2028 /* TODO: 2. Inline objects */
2029 /* TODO: 3. Underlines */
2030 /* TODO: 4. Strikethrough */
2035 static HRESULT WINAPI
dwritetextlayout_GetLineMetrics(IDWriteTextLayout2
*iface
,
2036 DWRITE_LINE_METRICS
*metrics
, UINT32 max_count
, UINT32
*count
)
2038 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2041 TRACE("(%p)->(%p %u %p)\n", This
, metrics
, max_count
, count
);
2043 hr
= layout_compute_effective_runs(This
);
2048 memcpy(metrics
, This
->lines
, sizeof(DWRITE_LINE_METRICS
)*min(max_count
, This
->line_count
));
2050 *count
= This
->line_count
;
2051 return max_count
>= This
->line_count
? S_OK
: E_NOT_SUFFICIENT_BUFFER
;
2054 static HRESULT WINAPI
dwritetextlayout_GetMetrics(IDWriteTextLayout2
*iface
, DWRITE_TEXT_METRICS
*metrics
)
2056 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2057 DWRITE_TEXT_METRICS1 metrics1
;
2060 TRACE("(%p)->(%p)\n", This
, metrics
);
2062 hr
= IDWriteTextLayout2_GetMetrics(iface
, &metrics1
);
2064 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
2069 static HRESULT WINAPI
dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout2
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
2071 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2072 FIXME("(%p)->(%p): stub\n", This
, overhangs
);
2076 static HRESULT WINAPI
dwritetextlayout_GetClusterMetrics(IDWriteTextLayout2
*iface
,
2077 DWRITE_CLUSTER_METRICS
*metrics
, UINT32 max_count
, UINT32
*count
)
2079 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2082 TRACE("(%p)->(%p %u %p)\n", This
, metrics
, max_count
, count
);
2084 hr
= layout_compute(This
);
2089 memcpy(metrics
, This
->clustermetrics
, sizeof(DWRITE_CLUSTER_METRICS
)*min(max_count
, This
->cluster_count
));
2091 *count
= This
->cluster_count
;
2092 return max_count
>= This
->cluster_count
? S_OK
: E_NOT_SUFFICIENT_BUFFER
;
2095 /* Only to be used with DetermineMinWidth() to find the longest cluster sequence that we don't want to try
2096 too hard to break. */
2097 static inline BOOL
is_terminal_cluster(struct dwrite_textlayout
*layout
, UINT32 index
)
2099 if (layout
->clustermetrics
[index
].isWhitespace
|| layout
->clustermetrics
[index
].isNewline
||
2100 (index
== layout
->cluster_count
- 1))
2102 /* check next one */
2103 return (index
< layout
->cluster_count
- 1) && layout
->clustermetrics
[index
+1].isWhitespace
;
2106 static HRESULT WINAPI
dwritetextlayout_DetermineMinWidth(IDWriteTextLayout2
*iface
, FLOAT
* min_width
)
2108 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2113 TRACE("(%p)->(%p)\n", This
, min_width
);
2116 return E_INVALIDARG
;
2118 if (!(This
->recompute
& RECOMPUTE_MINIMAL_WIDTH
))
2122 hr
= layout_compute(This
);
2126 for (i
= 0; i
< This
->cluster_count
;) {
2127 if (is_terminal_cluster(This
, i
)) {
2128 width
= This
->clustermetrics
[i
].width
;
2133 while (!is_terminal_cluster(This
, i
)) {
2134 width
+= This
->clustermetrics
[i
].width
;
2137 /* count last one too */
2138 width
+= This
->clustermetrics
[i
].width
;
2141 if (width
> This
->minwidth
)
2142 This
->minwidth
= width
;
2144 This
->recompute
&= ~RECOMPUTE_MINIMAL_WIDTH
;
2147 *min_width
= This
->minwidth
;
2151 static HRESULT WINAPI
dwritetextlayout_HitTestPoint(IDWriteTextLayout2
*iface
,
2152 FLOAT pointX
, FLOAT pointY
, BOOL
* is_trailinghit
, BOOL
* is_inside
, DWRITE_HIT_TEST_METRICS
*metrics
)
2154 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2155 FIXME("(%p)->(%f %f %p %p %p): stub\n", This
, pointX
, pointY
, is_trailinghit
, is_inside
, metrics
);
2159 static HRESULT WINAPI
dwritetextlayout_HitTestTextPosition(IDWriteTextLayout2
*iface
,
2160 UINT32 textPosition
, BOOL is_trailinghit
, FLOAT
* pointX
, FLOAT
* pointY
, DWRITE_HIT_TEST_METRICS
*metrics
)
2162 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2163 FIXME("(%p)->(%u %d %p %p %p): stub\n", This
, textPosition
, is_trailinghit
, pointX
, pointY
, metrics
);
2167 static HRESULT WINAPI
dwritetextlayout_HitTestTextRange(IDWriteTextLayout2
*iface
,
2168 UINT32 textPosition
, UINT32 textLength
, FLOAT originX
, FLOAT originY
,
2169 DWRITE_HIT_TEST_METRICS
*metrics
, UINT32 max_metricscount
, UINT32
* actual_metricscount
)
2171 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2172 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This
, textPosition
, textLength
, originX
, originY
, metrics
,
2173 max_metricscount
, actual_metricscount
);
2177 static HRESULT WINAPI
dwritetextlayout1_SetPairKerning(IDWriteTextLayout2
*iface
, BOOL is_pairkerning_enabled
,
2178 DWRITE_TEXT_RANGE range
)
2180 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2181 struct layout_range_attr_value value
;
2183 TRACE("(%p)->(%d %s)\n", This
, is_pairkerning_enabled
, debugstr_range(&range
));
2185 value
.range
= range
;
2186 value
.u
.pair_kerning
= !!is_pairkerning_enabled
;
2187 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_PAIR_KERNING
, &value
);
2190 static HRESULT WINAPI
dwritetextlayout1_GetPairKerning(IDWriteTextLayout2
*iface
, UINT32 position
, BOOL
*is_pairkerning_enabled
,
2191 DWRITE_TEXT_RANGE
*r
)
2193 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2194 struct layout_range
*range
;
2196 TRACE("(%p)->(%u %p %p)\n", This
, position
, is_pairkerning_enabled
, r
);
2198 if (position
>= This
->len
)
2201 range
= get_layout_range_by_pos(This
, position
);
2202 *is_pairkerning_enabled
= range
->pair_kerning
;
2204 return return_range(range
, r
);
2207 static HRESULT WINAPI
dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2
*iface
, FLOAT leading_spacing
, FLOAT trailing_spacing
,
2208 FLOAT minimum_advance_width
, DWRITE_TEXT_RANGE range
)
2210 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2211 FIXME("(%p)->(%f %f %f %s): stub\n", This
, leading_spacing
, trailing_spacing
, minimum_advance_width
, debugstr_range(&range
));
2215 static HRESULT WINAPI
dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2
*iface
, UINT32 position
, FLOAT
* leading_spacing
,
2216 FLOAT
* trailing_spacing
, FLOAT
* minimum_advance_width
, DWRITE_TEXT_RANGE
*range
)
2218 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2219 FIXME("(%p)->(%u %p %p %p %p): stub\n", This
, position
, leading_spacing
, trailing_spacing
, minimum_advance_width
, range
);
2223 static HRESULT WINAPI
dwritetextlayout2_GetMetrics(IDWriteTextLayout2
*iface
, DWRITE_TEXT_METRICS1
*metrics
)
2225 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2226 FIXME("(%p)->(%p): stub\n", This
, metrics
);
2230 static HRESULT WINAPI
dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout2
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
2232 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2234 TRACE("(%p)->(%d)\n", This
, orientation
);
2236 if ((UINT32
)orientation
> DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
)
2237 return E_INVALIDARG
;
2239 This
->format
.vertical_orientation
= orientation
;
2243 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextlayout2_GetVerticalGlyphOrientation(IDWriteTextLayout2
*iface
)
2245 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2246 TRACE("(%p)\n", This
);
2247 return This
->format
.vertical_orientation
;
2250 static HRESULT WINAPI
dwritetextlayout2_SetLastLineWrapping(IDWriteTextLayout2
*iface
, BOOL lastline_wrapping_enabled
)
2252 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2253 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
2257 static BOOL WINAPI
dwritetextlayout2_GetLastLineWrapping(IDWriteTextLayout2
*iface
)
2259 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2260 FIXME("(%p): stub\n", This
);
2264 static HRESULT WINAPI
dwritetextlayout2_SetOpticalAlignment(IDWriteTextLayout2
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
2266 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2267 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2271 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextlayout2_GetOpticalAlignment(IDWriteTextLayout2
*iface
)
2273 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2274 FIXME("(%p): stub\n", This
);
2275 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
2278 static HRESULT WINAPI
dwritetextlayout2_SetFontFallback(IDWriteTextLayout2
*iface
, IDWriteFontFallback
*fallback
)
2280 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2281 TRACE("(%p)->(%p)\n", This
, fallback
);
2282 return set_fontfallback_for_format(&This
->format
, fallback
);
2285 static HRESULT WINAPI
dwritetextlayout2_GetFontFallback(IDWriteTextLayout2
*iface
, IDWriteFontFallback
**fallback
)
2287 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2288 TRACE("(%p)->(%p)\n", This
, fallback
);
2289 return get_fontfallback_from_format(&This
->format
, fallback
);
2292 static const IDWriteTextLayout2Vtbl dwritetextlayoutvtbl
= {
2293 dwritetextlayout_QueryInterface
,
2294 dwritetextlayout_AddRef
,
2295 dwritetextlayout_Release
,
2296 dwritetextlayout_SetTextAlignment
,
2297 dwritetextlayout_SetParagraphAlignment
,
2298 dwritetextlayout_SetWordWrapping
,
2299 dwritetextlayout_SetReadingDirection
,
2300 dwritetextlayout_SetFlowDirection
,
2301 dwritetextlayout_SetIncrementalTabStop
,
2302 dwritetextlayout_SetTrimming
,
2303 dwritetextlayout_SetLineSpacing
,
2304 dwritetextlayout_GetTextAlignment
,
2305 dwritetextlayout_GetParagraphAlignment
,
2306 dwritetextlayout_GetWordWrapping
,
2307 dwritetextlayout_GetReadingDirection
,
2308 dwritetextlayout_GetFlowDirection
,
2309 dwritetextlayout_GetIncrementalTabStop
,
2310 dwritetextlayout_GetTrimming
,
2311 dwritetextlayout_GetLineSpacing
,
2312 dwritetextlayout_GetFontCollection
,
2313 dwritetextlayout_GetFontFamilyNameLength
,
2314 dwritetextlayout_GetFontFamilyName
,
2315 dwritetextlayout_GetFontWeight
,
2316 dwritetextlayout_GetFontStyle
,
2317 dwritetextlayout_GetFontStretch
,
2318 dwritetextlayout_GetFontSize
,
2319 dwritetextlayout_GetLocaleNameLength
,
2320 dwritetextlayout_GetLocaleName
,
2321 dwritetextlayout_SetMaxWidth
,
2322 dwritetextlayout_SetMaxHeight
,
2323 dwritetextlayout_SetFontCollection
,
2324 dwritetextlayout_SetFontFamilyName
,
2325 dwritetextlayout_SetFontWeight
,
2326 dwritetextlayout_SetFontStyle
,
2327 dwritetextlayout_SetFontStretch
,
2328 dwritetextlayout_SetFontSize
,
2329 dwritetextlayout_SetUnderline
,
2330 dwritetextlayout_SetStrikethrough
,
2331 dwritetextlayout_SetDrawingEffect
,
2332 dwritetextlayout_SetInlineObject
,
2333 dwritetextlayout_SetTypography
,
2334 dwritetextlayout_SetLocaleName
,
2335 dwritetextlayout_GetMaxWidth
,
2336 dwritetextlayout_GetMaxHeight
,
2337 dwritetextlayout_layout_GetFontCollection
,
2338 dwritetextlayout_layout_GetFontFamilyNameLength
,
2339 dwritetextlayout_layout_GetFontFamilyName
,
2340 dwritetextlayout_layout_GetFontWeight
,
2341 dwritetextlayout_layout_GetFontStyle
,
2342 dwritetextlayout_layout_GetFontStretch
,
2343 dwritetextlayout_layout_GetFontSize
,
2344 dwritetextlayout_GetUnderline
,
2345 dwritetextlayout_GetStrikethrough
,
2346 dwritetextlayout_GetDrawingEffect
,
2347 dwritetextlayout_GetInlineObject
,
2348 dwritetextlayout_GetTypography
,
2349 dwritetextlayout_layout_GetLocaleNameLength
,
2350 dwritetextlayout_layout_GetLocaleName
,
2351 dwritetextlayout_Draw
,
2352 dwritetextlayout_GetLineMetrics
,
2353 dwritetextlayout_GetMetrics
,
2354 dwritetextlayout_GetOverhangMetrics
,
2355 dwritetextlayout_GetClusterMetrics
,
2356 dwritetextlayout_DetermineMinWidth
,
2357 dwritetextlayout_HitTestPoint
,
2358 dwritetextlayout_HitTestTextPosition
,
2359 dwritetextlayout_HitTestTextRange
,
2360 dwritetextlayout1_SetPairKerning
,
2361 dwritetextlayout1_GetPairKerning
,
2362 dwritetextlayout1_SetCharacterSpacing
,
2363 dwritetextlayout1_GetCharacterSpacing
,
2364 dwritetextlayout2_GetMetrics
,
2365 dwritetextlayout2_SetVerticalGlyphOrientation
,
2366 dwritetextlayout2_GetVerticalGlyphOrientation
,
2367 dwritetextlayout2_SetLastLineWrapping
,
2368 dwritetextlayout2_GetLastLineWrapping
,
2369 dwritetextlayout2_SetOpticalAlignment
,
2370 dwritetextlayout2_GetOpticalAlignment
,
2371 dwritetextlayout2_SetFontFallback
,
2372 dwritetextlayout2_GetFontFallback
2375 static HRESULT WINAPI
dwritetextformat1_layout_QueryInterface(IDWriteTextFormat1
*iface
, REFIID riid
, void **obj
)
2377 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2378 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2379 return IDWriteTextLayout2_QueryInterface(&This
->IDWriteTextLayout2_iface
, riid
, obj
);
2382 static ULONG WINAPI
dwritetextformat1_layout_AddRef(IDWriteTextFormat1
*iface
)
2384 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2385 return IDWriteTextLayout2_AddRef(&This
->IDWriteTextLayout2_iface
);
2388 static ULONG WINAPI
dwritetextformat1_layout_Release(IDWriteTextFormat1
*iface
)
2390 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2391 return IDWriteTextLayout2_Release(&This
->IDWriteTextLayout2_iface
);
2394 static HRESULT WINAPI
dwritetextformat1_layout_SetTextAlignment(IDWriteTextFormat1
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
2396 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2397 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2401 static HRESULT WINAPI
dwritetextformat1_layout_SetParagraphAlignment(IDWriteTextFormat1
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
2403 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2404 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2408 static HRESULT WINAPI
dwritetextformat1_layout_SetWordWrapping(IDWriteTextFormat1
*iface
, DWRITE_WORD_WRAPPING wrapping
)
2410 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2411 FIXME("(%p)->(%d): stub\n", This
, wrapping
);
2415 static HRESULT WINAPI
dwritetextformat1_layout_SetReadingDirection(IDWriteTextFormat1
*iface
, DWRITE_READING_DIRECTION direction
)
2417 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2418 FIXME("(%p)->(%d): stub\n", This
, direction
);
2422 static HRESULT WINAPI
dwritetextformat1_layout_SetFlowDirection(IDWriteTextFormat1
*iface
, DWRITE_FLOW_DIRECTION direction
)
2424 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2425 FIXME("(%p)->(%d): stub\n", This
, direction
);
2429 static HRESULT WINAPI
dwritetextformat1_layout_SetIncrementalTabStop(IDWriteTextFormat1
*iface
, FLOAT tabstop
)
2431 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2432 FIXME("(%p)->(%f): stub\n", This
, tabstop
);
2436 static HRESULT WINAPI
dwritetextformat1_layout_SetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
const *trimming
,
2437 IDWriteInlineObject
*trimming_sign
)
2439 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2440 FIXME("(%p)->(%p %p): stub\n", This
, trimming
, trimming_sign
);
2444 static HRESULT WINAPI
dwritetextformat1_layout_SetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD spacing
,
2445 FLOAT line_spacing
, FLOAT baseline
)
2447 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2448 FIXME("(%p)->(%d %f %f): stub\n", This
, spacing
, line_spacing
, baseline
);
2452 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextformat1_layout_GetTextAlignment(IDWriteTextFormat1
*iface
)
2454 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2455 TRACE("(%p)\n", This
);
2456 return This
->format
.textalignment
;
2459 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextformat1_layout_GetParagraphAlignment(IDWriteTextFormat1
*iface
)
2461 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2462 TRACE("(%p)\n", This
);
2463 return This
->format
.paralign
;
2466 static DWRITE_WORD_WRAPPING WINAPI
dwritetextformat1_layout_GetWordWrapping(IDWriteTextFormat1
*iface
)
2468 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2469 FIXME("(%p): stub\n", This
);
2470 return This
->format
.wrapping
;
2473 static DWRITE_READING_DIRECTION WINAPI
dwritetextformat1_layout_GetReadingDirection(IDWriteTextFormat1
*iface
)
2475 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2476 TRACE("(%p)\n", This
);
2477 return This
->format
.readingdir
;
2480 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextformat1_layout_GetFlowDirection(IDWriteTextFormat1
*iface
)
2482 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2483 TRACE("(%p)\n", This
);
2484 return This
->format
.flow
;
2487 static FLOAT WINAPI
dwritetextformat1_layout_GetIncrementalTabStop(IDWriteTextFormat1
*iface
)
2489 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2490 FIXME("(%p): stub\n", This
);
2494 static HRESULT WINAPI
dwritetextformat1_layout_GetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
*options
,
2495 IDWriteInlineObject
**trimming_sign
)
2497 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2499 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
2501 *options
= This
->format
.trimming
;
2502 *trimming_sign
= This
->format
.trimmingsign
;
2504 IDWriteInlineObject_AddRef(*trimming_sign
);
2508 static HRESULT WINAPI
dwritetextformat1_layout_GetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
2509 FLOAT
*spacing
, FLOAT
*baseline
)
2511 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2513 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
2515 *method
= This
->format
.spacingmethod
;
2516 *spacing
= This
->format
.spacing
;
2517 *baseline
= This
->format
.baseline
;
2521 static HRESULT WINAPI
dwritetextformat1_layout_GetFontCollection(IDWriteTextFormat1
*iface
, IDWriteFontCollection
**collection
)
2523 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2525 TRACE("(%p)->(%p)\n", This
, collection
);
2527 *collection
= This
->format
.collection
;
2529 IDWriteFontCollection_AddRef(*collection
);
2533 static UINT32 WINAPI
dwritetextformat1_layout_GetFontFamilyNameLength(IDWriteTextFormat1
*iface
)
2535 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2536 TRACE("(%p)\n", This
);
2537 return This
->format
.family_len
;
2540 static HRESULT WINAPI
dwritetextformat1_layout_GetFontFamilyName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
2542 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2544 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
2546 if (size
<= This
->format
.family_len
) return E_NOT_SUFFICIENT_BUFFER
;
2547 strcpyW(name
, This
->format
.family_name
);
2551 static DWRITE_FONT_WEIGHT WINAPI
dwritetextformat1_layout_GetFontWeight(IDWriteTextFormat1
*iface
)
2553 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2554 TRACE("(%p)\n", This
);
2555 return This
->format
.weight
;
2558 static DWRITE_FONT_STYLE WINAPI
dwritetextformat1_layout_GetFontStyle(IDWriteTextFormat1
*iface
)
2560 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2561 TRACE("(%p)\n", This
);
2562 return This
->format
.style
;
2565 static DWRITE_FONT_STRETCH WINAPI
dwritetextformat1_layout_GetFontStretch(IDWriteTextFormat1
*iface
)
2567 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2568 TRACE("(%p)\n", This
);
2569 return This
->format
.stretch
;
2572 static FLOAT WINAPI
dwritetextformat1_layout_GetFontSize(IDWriteTextFormat1
*iface
)
2574 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2575 TRACE("(%p)\n", This
);
2576 return This
->format
.fontsize
;
2579 static UINT32 WINAPI
dwritetextformat1_layout_GetLocaleNameLength(IDWriteTextFormat1
*iface
)
2581 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2582 TRACE("(%p)\n", This
);
2583 return This
->format
.locale_len
;
2586 static HRESULT WINAPI
dwritetextformat1_layout_GetLocaleName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
2588 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2590 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
2592 if (size
<= This
->format
.locale_len
) return E_NOT_SUFFICIENT_BUFFER
;
2593 strcpyW(name
, This
->format
.locale
);
2597 static HRESULT WINAPI
dwritetextformat1_layout_SetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
2599 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2600 FIXME("(%p)->(%d): stub\n", This
, orientation
);
2604 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextformat1_layout_GetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
)
2606 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2607 FIXME("(%p): stub\n", This
);
2608 return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
2611 static HRESULT WINAPI
dwritetextformat1_layout_SetLastLineWrapping(IDWriteTextFormat1
*iface
, BOOL lastline_wrapping_enabled
)
2613 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2614 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
2618 static BOOL WINAPI
dwritetextformat1_layout_GetLastLineWrapping(IDWriteTextFormat1
*iface
)
2620 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2621 FIXME("(%p): stub\n", This
);
2625 static HRESULT WINAPI
dwritetextformat1_layout_SetOpticalAlignment(IDWriteTextFormat1
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
2627 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2628 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2632 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextformat1_layout_GetOpticalAlignment(IDWriteTextFormat1
*iface
)
2634 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2635 FIXME("(%p): stub\n", This
);
2636 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
2639 static HRESULT WINAPI
dwritetextformat1_layout_SetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
*fallback
)
2641 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2642 TRACE("(%p)->(%p)\n", This
, fallback
);
2643 return IDWriteTextLayout2_SetFontFallback(&This
->IDWriteTextLayout2_iface
, fallback
);
2646 static HRESULT WINAPI
dwritetextformat1_layout_GetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
**fallback
)
2648 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2649 TRACE("(%p)->(%p)\n", This
, fallback
);
2650 return IDWriteTextLayout2_GetFontFallback(&This
->IDWriteTextLayout2_iface
, fallback
);
2653 static const IDWriteTextFormat1Vtbl dwritetextformat1_layout_vtbl
= {
2654 dwritetextformat1_layout_QueryInterface
,
2655 dwritetextformat1_layout_AddRef
,
2656 dwritetextformat1_layout_Release
,
2657 dwritetextformat1_layout_SetTextAlignment
,
2658 dwritetextformat1_layout_SetParagraphAlignment
,
2659 dwritetextformat1_layout_SetWordWrapping
,
2660 dwritetextformat1_layout_SetReadingDirection
,
2661 dwritetextformat1_layout_SetFlowDirection
,
2662 dwritetextformat1_layout_SetIncrementalTabStop
,
2663 dwritetextformat1_layout_SetTrimming
,
2664 dwritetextformat1_layout_SetLineSpacing
,
2665 dwritetextformat1_layout_GetTextAlignment
,
2666 dwritetextformat1_layout_GetParagraphAlignment
,
2667 dwritetextformat1_layout_GetWordWrapping
,
2668 dwritetextformat1_layout_GetReadingDirection
,
2669 dwritetextformat1_layout_GetFlowDirection
,
2670 dwritetextformat1_layout_GetIncrementalTabStop
,
2671 dwritetextformat1_layout_GetTrimming
,
2672 dwritetextformat1_layout_GetLineSpacing
,
2673 dwritetextformat1_layout_GetFontCollection
,
2674 dwritetextformat1_layout_GetFontFamilyNameLength
,
2675 dwritetextformat1_layout_GetFontFamilyName
,
2676 dwritetextformat1_layout_GetFontWeight
,
2677 dwritetextformat1_layout_GetFontStyle
,
2678 dwritetextformat1_layout_GetFontStretch
,
2679 dwritetextformat1_layout_GetFontSize
,
2680 dwritetextformat1_layout_GetLocaleNameLength
,
2681 dwritetextformat1_layout_GetLocaleName
,
2682 dwritetextformat1_layout_SetVerticalGlyphOrientation
,
2683 dwritetextformat1_layout_GetVerticalGlyphOrientation
,
2684 dwritetextformat1_layout_SetLastLineWrapping
,
2685 dwritetextformat1_layout_GetLastLineWrapping
,
2686 dwritetextformat1_layout_SetOpticalAlignment
,
2687 dwritetextformat1_layout_GetOpticalAlignment
,
2688 dwritetextformat1_layout_SetFontFallback
,
2689 dwritetextformat1_layout_GetFontFallback
2692 static HRESULT WINAPI
dwritetextlayout_sink_QueryInterface(IDWriteTextAnalysisSink
*iface
,
2693 REFIID riid
, void **obj
)
2695 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
)) {
2697 IDWriteTextAnalysisSink_AddRef(iface
);
2702 return E_NOINTERFACE
;
2705 static ULONG WINAPI
dwritetextlayout_sink_AddRef(IDWriteTextAnalysisSink
*iface
)
2710 static ULONG WINAPI
dwritetextlayout_sink_Release(IDWriteTextAnalysisSink
*iface
)
2715 static HRESULT WINAPI
dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
2716 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
2718 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
2719 struct layout_run
*run
;
2721 TRACE("%u %u script=%d\n", position
, length
, sa
->script
);
2723 run
= alloc_layout_run(LAYOUT_RUN_REGULAR
);
2725 return E_OUTOFMEMORY
;
2727 run
->u
.regular
.descr
.string
= &layout
->str
[position
];
2728 run
->u
.regular
.descr
.stringLength
= length
;
2729 run
->u
.regular
.descr
.textPosition
= position
;
2730 run
->u
.regular
.sa
= *sa
;
2731 list_add_tail(&layout
->runs
, &run
->entry
);
2735 static HRESULT WINAPI
dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
2736 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
2738 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
2740 if (position
+ length
> layout
->len
)
2743 memcpy(&layout
->nominal_breakpoints
[position
], breakpoints
, length
*sizeof(DWRITE_LINE_BREAKPOINT
));
2747 static HRESULT WINAPI
dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
, UINT32 position
,
2748 UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
2750 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
2751 struct layout_run
*cur_run
;
2753 LIST_FOR_EACH_ENTRY(cur_run
, &layout
->runs
, struct layout_run
, entry
) {
2754 struct regular_layout_run
*cur
= &cur_run
->u
.regular
;
2755 struct layout_run
*run
, *run2
;
2757 if (cur_run
->kind
== LAYOUT_RUN_INLINE
)
2760 /* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */
2761 if (position
< cur
->descr
.textPosition
|| position
> cur
->descr
.textPosition
+ cur
->descr
.stringLength
)
2764 /* full hit - just set run level */
2765 if (cur
->descr
.textPosition
== position
&& cur
->descr
.stringLength
== length
) {
2766 cur
->run
.bidiLevel
= resolvedLevel
;
2770 /* current run is fully covered, move to next one */
2771 if (cur
->descr
.textPosition
== position
&& cur
->descr
.stringLength
< length
) {
2772 cur
->run
.bidiLevel
= resolvedLevel
;
2773 position
+= cur
->descr
.stringLength
;
2774 length
-= cur
->descr
.stringLength
;
2778 /* now starting point is in a run, so it splits it */
2779 run
= alloc_layout_run(LAYOUT_RUN_REGULAR
);
2781 return E_OUTOFMEMORY
;
2784 run
->u
.regular
.descr
.textPosition
= position
;
2785 run
->u
.regular
.descr
.stringLength
= cur
->descr
.stringLength
- position
+ cur
->descr
.textPosition
;
2786 run
->u
.regular
.descr
.string
= &layout
->str
[position
];
2787 run
->u
.regular
.run
.bidiLevel
= resolvedLevel
;
2788 cur
->descr
.stringLength
-= position
- cur
->descr
.textPosition
;
2790 list_add_after(&cur_run
->entry
, &run
->entry
);
2792 if (position
+ length
== run
->u
.regular
.descr
.textPosition
+ run
->u
.regular
.descr
.stringLength
)
2795 /* split second time */
2796 run2
= alloc_layout_run(LAYOUT_RUN_REGULAR
);
2798 return E_OUTOFMEMORY
;
2801 run2
->u
.regular
.descr
.textPosition
= run
->u
.regular
.descr
.textPosition
+ run
->u
.regular
.descr
.stringLength
;
2802 run2
->u
.regular
.descr
.stringLength
= cur
->descr
.textPosition
+ cur
->descr
.stringLength
- position
- length
;
2803 run2
->u
.regular
.descr
.string
= &layout
->str
[run2
->u
.regular
.descr
.textPosition
];
2804 run
->u
.regular
.descr
.stringLength
-= run2
->u
.regular
.descr
.stringLength
;
2806 list_add_after(&run
->entry
, &run2
->entry
);
2813 static HRESULT WINAPI
dwritetextlayout_sink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
2814 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
2819 static const IDWriteTextAnalysisSinkVtbl dwritetextlayoutsinkvtbl
= {
2820 dwritetextlayout_sink_QueryInterface
,
2821 dwritetextlayout_sink_AddRef
,
2822 dwritetextlayout_sink_Release
,
2823 dwritetextlayout_sink_SetScriptAnalysis
,
2824 dwritetextlayout_sink_SetLineBreakpoints
,
2825 dwritetextlayout_sink_SetBidiLevel
,
2826 dwritetextlayout_sink_SetNumberSubstitution
2829 static HRESULT WINAPI
dwritetextlayout_source_QueryInterface(IDWriteTextAnalysisSource
*iface
,
2830 REFIID riid
, void **obj
)
2832 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSource
) ||
2833 IsEqualIID(riid
, &IID_IUnknown
))
2836 IDWriteTextAnalysisSource_AddRef(iface
);
2841 return E_NOINTERFACE
;
2844 static ULONG WINAPI
dwritetextlayout_source_AddRef(IDWriteTextAnalysisSource
*iface
)
2849 static ULONG WINAPI
dwritetextlayout_source_Release(IDWriteTextAnalysisSource
*iface
)
2854 static HRESULT WINAPI
dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
2855 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
2857 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSource(iface
);
2859 TRACE("(%p)->(%u %p %p)\n", layout
, position
, text
, text_len
);
2861 if (position
< layout
->len
) {
2862 *text
= &layout
->str
[position
];
2863 *text_len
= layout
->len
- position
;
2873 static HRESULT WINAPI
dwritetextlayout_source_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
2874 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
2876 FIXME("%u %p %p: stub\n", position
, text
, text_len
);
2880 static DWRITE_READING_DIRECTION WINAPI
dwritetextlayout_source_GetParagraphReadingDirection(IDWriteTextAnalysisSource
*iface
)
2882 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSource(iface
);
2883 return IDWriteTextLayout2_GetReadingDirection(&layout
->IDWriteTextLayout2_iface
);
2886 static HRESULT WINAPI
dwritetextlayout_source_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
2887 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
2889 FIXME("%u %p %p: stub\n", position
, text_len
, locale
);
2893 static HRESULT WINAPI
dwritetextlayout_source_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
2894 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
2896 FIXME("%u %p %p: stub\n", position
, text_len
, substitution
);
2900 static const IDWriteTextAnalysisSourceVtbl dwritetextlayoutsourcevtbl
= {
2901 dwritetextlayout_source_QueryInterface
,
2902 dwritetextlayout_source_AddRef
,
2903 dwritetextlayout_source_Release
,
2904 dwritetextlayout_source_GetTextAtPosition
,
2905 dwritetextlayout_source_GetTextBeforePosition
,
2906 dwritetextlayout_source_GetParagraphReadingDirection
,
2907 dwritetextlayout_source_GetLocaleName
,
2908 dwritetextlayout_source_GetNumberSubstitution
2911 static HRESULT
layout_format_from_textformat(struct dwrite_textlayout
*layout
, IDWriteTextFormat
*format
)
2913 IDWriteTextFormat1
*format1
;
2917 layout
->format
.weight
= IDWriteTextFormat_GetFontWeight(format
);
2918 layout
->format
.style
= IDWriteTextFormat_GetFontStyle(format
);
2919 layout
->format
.stretch
= IDWriteTextFormat_GetFontStretch(format
);
2920 layout
->format
.fontsize
= IDWriteTextFormat_GetFontSize(format
);
2921 layout
->format
.textalignment
= IDWriteTextFormat_GetTextAlignment(format
);
2922 layout
->format
.paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
2923 layout
->format
.wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
2924 layout
->format
.readingdir
= IDWriteTextFormat_GetReadingDirection(format
);
2925 layout
->format
.flow
= IDWriteTextFormat_GetFlowDirection(format
);
2926 layout
->format
.fallback
= NULL
;
2927 hr
= IDWriteTextFormat_GetLineSpacing(format
, &layout
->format
.spacingmethod
,
2928 &layout
->format
.spacing
, &layout
->format
.baseline
);
2932 hr
= IDWriteTextFormat_GetTrimming(format
, &layout
->format
.trimming
, &layout
->format
.trimmingsign
);
2936 /* locale name and length */
2937 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
2938 layout
->format
.locale
= heap_alloc((len
+1)*sizeof(WCHAR
));
2939 if (!layout
->format
.locale
)
2940 return E_OUTOFMEMORY
;
2942 hr
= IDWriteTextFormat_GetLocaleName(format
, layout
->format
.locale
, len
+1);
2945 layout
->format
.locale_len
= len
;
2947 /* font family name and length */
2948 len
= IDWriteTextFormat_GetFontFamilyNameLength(format
);
2949 layout
->format
.family_name
= heap_alloc((len
+1)*sizeof(WCHAR
));
2950 if (!layout
->format
.family_name
)
2951 return E_OUTOFMEMORY
;
2953 hr
= IDWriteTextFormat_GetFontFamilyName(format
, layout
->format
.family_name
, len
+1);
2956 layout
->format
.family_len
= len
;
2958 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
2960 layout
->format
.vertical_orientation
= IDWriteTextFormat1_GetVerticalGlyphOrientation(format1
);
2961 IDWriteTextFormat1_GetFontFallback(format1
, &layout
->format
.fallback
);
2962 IDWriteTextFormat1_Release(format1
);
2965 layout
->format
.vertical_orientation
= DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
2967 return IDWriteTextFormat_GetFontCollection(format
, &layout
->format
.collection
);
2970 static HRESULT
init_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
, struct dwrite_textlayout
*layout
)
2972 DWRITE_TEXT_RANGE r
= { 0, len
};
2973 struct layout_range
*range
;
2976 layout
->IDWriteTextLayout2_iface
.lpVtbl
= &dwritetextlayoutvtbl
;
2977 layout
->IDWriteTextFormat1_iface
.lpVtbl
= &dwritetextformat1_layout_vtbl
;
2978 layout
->IDWriteTextAnalysisSink_iface
.lpVtbl
= &dwritetextlayoutsinkvtbl
;
2979 layout
->IDWriteTextAnalysisSource_iface
.lpVtbl
= &dwritetextlayoutsourcevtbl
;
2982 layout
->maxwidth
= maxwidth
;
2983 layout
->maxheight
= maxheight
;
2984 layout
->recompute
= RECOMPUTE_EVERYTHING
;
2985 layout
->nominal_breakpoints
= NULL
;
2986 layout
->actual_breakpoints
= NULL
;
2987 layout
->cluster_count
= 0;
2988 layout
->clustermetrics
= NULL
;
2989 layout
->clusters
= NULL
;
2990 layout
->lines
= NULL
;
2991 layout
->line_count
= 0;
2992 layout
->line_alloc
= 0;
2993 layout
->minwidth
= 0.0;
2994 list_init(&layout
->eruns
);
2995 list_init(&layout
->runs
);
2996 list_init(&layout
->ranges
);
2997 memset(&layout
->format
, 0, sizeof(layout
->format
));
2999 layout
->gdicompatible
= FALSE
;
3000 layout
->pixels_per_dip
= 0.0;
3001 layout
->use_gdi_natural
= FALSE
;
3002 memset(&layout
->transform
, 0, sizeof(layout
->transform
));
3004 layout
->str
= heap_strdupnW(str
, len
);
3005 if (len
&& !layout
->str
) {
3010 hr
= layout_format_from_textformat(layout
, format
);
3014 range
= alloc_layout_range(layout
, &r
);
3020 list_add_head(&layout
->ranges
, &range
->entry
);
3024 IDWriteTextLayout2_Release(&layout
->IDWriteTextLayout2_iface
);
3028 HRESULT
create_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
, IDWriteTextLayout
**ret
)
3030 struct dwrite_textlayout
*layout
;
3035 layout
= heap_alloc(sizeof(struct dwrite_textlayout
));
3036 if (!layout
) return E_OUTOFMEMORY
;
3038 hr
= init_textlayout(str
, len
, format
, maxwidth
, maxheight
, layout
);
3040 *ret
= (IDWriteTextLayout
*)&layout
->IDWriteTextLayout2_iface
;
3045 HRESULT
create_gdicompat_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
,
3046 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
, IDWriteTextLayout
**ret
)
3048 struct dwrite_textlayout
*layout
;
3053 layout
= heap_alloc(sizeof(struct dwrite_textlayout
));
3054 if (!layout
) return E_OUTOFMEMORY
;
3056 hr
= init_textlayout(str
, len
, format
, maxwidth
, maxheight
, layout
);
3058 /* set gdi-specific properties */
3059 layout
->gdicompatible
= TRUE
;
3060 layout
->pixels_per_dip
= pixels_per_dip
;
3061 layout
->use_gdi_natural
= use_gdi_natural
;
3062 layout
->transform
= transform
? *transform
: identity
;
3064 *ret
= (IDWriteTextLayout
*)&layout
->IDWriteTextLayout2_iface
;
3070 static HRESULT WINAPI
dwritetrimmingsign_QueryInterface(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
3072 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3074 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3076 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteInlineObject
)) {
3078 IDWriteInlineObject_AddRef(iface
);
3083 return E_NOINTERFACE
;
3087 static ULONG WINAPI
dwritetrimmingsign_AddRef(IDWriteInlineObject
*iface
)
3089 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3090 ULONG ref
= InterlockedIncrement(&This
->ref
);
3091 TRACE("(%p)->(%d)\n", This
, ref
);
3095 static ULONG WINAPI
dwritetrimmingsign_Release(IDWriteInlineObject
*iface
)
3097 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3098 ULONG ref
= InterlockedDecrement(&This
->ref
);
3100 TRACE("(%p)->(%d)\n", This
, ref
);
3108 static HRESULT WINAPI
dwritetrimmingsign_Draw(IDWriteInlineObject
*iface
, void *context
, IDWriteTextRenderer
*renderer
,
3109 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*drawing_effect
)
3111 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3112 FIXME("(%p)->(%p %p %f %f %d %d %p): stub\n", This
, context
, renderer
, originX
, originY
, is_sideways
, is_rtl
, drawing_effect
);
3116 static HRESULT WINAPI
dwritetrimmingsign_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
3118 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3119 FIXME("(%p)->(%p): stub\n", This
, metrics
);
3120 memset(metrics
, 0, sizeof(*metrics
));
3124 static HRESULT WINAPI
dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
3126 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3127 FIXME("(%p)->(%p): stub\n", This
, overhangs
);
3131 static HRESULT WINAPI
dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
3132 DWRITE_BREAK_CONDITION
*after
)
3134 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3136 TRACE("(%p)->(%p %p)\n", This
, before
, after
);
3138 *before
= *after
= DWRITE_BREAK_CONDITION_NEUTRAL
;
3142 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl
= {
3143 dwritetrimmingsign_QueryInterface
,
3144 dwritetrimmingsign_AddRef
,
3145 dwritetrimmingsign_Release
,
3146 dwritetrimmingsign_Draw
,
3147 dwritetrimmingsign_GetMetrics
,
3148 dwritetrimmingsign_GetOverhangMetrics
,
3149 dwritetrimmingsign_GetBreakConditions
3152 HRESULT
create_trimmingsign(IDWriteInlineObject
**sign
)
3154 struct dwrite_trimmingsign
*This
;
3158 This
= heap_alloc(sizeof(struct dwrite_trimmingsign
));
3159 if (!This
) return E_OUTOFMEMORY
;
3161 This
->IDWriteInlineObject_iface
.lpVtbl
= &dwritetrimmingsignvtbl
;
3164 *sign
= &This
->IDWriteInlineObject_iface
;
3169 static HRESULT WINAPI
dwritetextformat_QueryInterface(IDWriteTextFormat1
*iface
, REFIID riid
, void **obj
)
3171 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3173 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3175 if (IsEqualIID(riid
, &IID_IDWriteTextFormat1
) ||
3176 IsEqualIID(riid
, &IID_IDWriteTextFormat
) ||
3177 IsEqualIID(riid
, &IID_IUnknown
))
3180 IDWriteTextFormat1_AddRef(iface
);
3186 return E_NOINTERFACE
;
3189 static ULONG WINAPI
dwritetextformat_AddRef(IDWriteTextFormat1
*iface
)
3191 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3192 ULONG ref
= InterlockedIncrement(&This
->ref
);
3193 TRACE("(%p)->(%d)\n", This
, ref
);
3197 static ULONG WINAPI
dwritetextformat_Release(IDWriteTextFormat1
*iface
)
3199 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3200 ULONG ref
= InterlockedDecrement(&This
->ref
);
3202 TRACE("(%p)->(%d)\n", This
, ref
);
3206 release_format_data(&This
->format
);
3213 static HRESULT WINAPI
dwritetextformat_SetTextAlignment(IDWriteTextFormat1
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
3215 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3216 TRACE("(%p)->(%d)\n", This
, alignment
);
3217 This
->format
.textalignment
= alignment
;
3221 static HRESULT WINAPI
dwritetextformat_SetParagraphAlignment(IDWriteTextFormat1
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
3223 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3224 TRACE("(%p)->(%d)\n", This
, alignment
);
3225 This
->format
.paralign
= alignment
;
3229 static HRESULT WINAPI
dwritetextformat_SetWordWrapping(IDWriteTextFormat1
*iface
, DWRITE_WORD_WRAPPING wrapping
)
3231 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3232 TRACE("(%p)->(%d)\n", This
, wrapping
);
3233 This
->format
.wrapping
= wrapping
;
3237 static HRESULT WINAPI
dwritetextformat_SetReadingDirection(IDWriteTextFormat1
*iface
, DWRITE_READING_DIRECTION direction
)
3239 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3240 TRACE("(%p)->(%d)\n", This
, direction
);
3241 This
->format
.readingdir
= direction
;
3245 static HRESULT WINAPI
dwritetextformat_SetFlowDirection(IDWriteTextFormat1
*iface
, DWRITE_FLOW_DIRECTION direction
)
3247 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3248 TRACE("(%p)->(%d)\n", This
, direction
);
3249 This
->format
.flow
= direction
;
3253 static HRESULT WINAPI
dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat1
*iface
, FLOAT tabstop
)
3255 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3256 FIXME("(%p)->(%f): stub\n", This
, tabstop
);
3260 static HRESULT WINAPI
dwritetextformat_SetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
const *trimming
,
3261 IDWriteInlineObject
*trimming_sign
)
3263 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3264 TRACE("(%p)->(%p %p)\n", This
, trimming
, trimming_sign
);
3266 This
->format
.trimming
= *trimming
;
3267 if (This
->format
.trimmingsign
)
3268 IDWriteInlineObject_Release(This
->format
.trimmingsign
);
3269 This
->format
.trimmingsign
= trimming_sign
;
3270 if (This
->format
.trimmingsign
)
3271 IDWriteInlineObject_AddRef(This
->format
.trimmingsign
);
3275 static HRESULT WINAPI
dwritetextformat_SetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD method
,
3276 FLOAT spacing
, FLOAT baseline
)
3278 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3279 TRACE("(%p)->(%d %f %f)\n", This
, method
, spacing
, baseline
);
3280 This
->format
.spacingmethod
= method
;
3281 This
->format
.spacing
= spacing
;
3282 This
->format
.baseline
= baseline
;
3286 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextformat_GetTextAlignment(IDWriteTextFormat1
*iface
)
3288 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3289 TRACE("(%p)\n", This
);
3290 return This
->format
.textalignment
;
3293 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextformat_GetParagraphAlignment(IDWriteTextFormat1
*iface
)
3295 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3296 TRACE("(%p)\n", This
);
3297 return This
->format
.paralign
;
3300 static DWRITE_WORD_WRAPPING WINAPI
dwritetextformat_GetWordWrapping(IDWriteTextFormat1
*iface
)
3302 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3303 TRACE("(%p)\n", This
);
3304 return This
->format
.wrapping
;
3307 static DWRITE_READING_DIRECTION WINAPI
dwritetextformat_GetReadingDirection(IDWriteTextFormat1
*iface
)
3309 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3310 TRACE("(%p)\n", This
);
3311 return This
->format
.readingdir
;
3314 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextformat_GetFlowDirection(IDWriteTextFormat1
*iface
)
3316 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3317 TRACE("(%p)\n", This
);
3318 return This
->format
.flow
;
3321 static FLOAT WINAPI
dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat1
*iface
)
3323 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3324 FIXME("(%p): stub\n", This
);
3328 static HRESULT WINAPI
dwritetextformat_GetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
*options
,
3329 IDWriteInlineObject
**trimming_sign
)
3331 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3332 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
3334 *options
= This
->format
.trimming
;
3335 if ((*trimming_sign
= This
->format
.trimmingsign
))
3336 IDWriteInlineObject_AddRef(*trimming_sign
);
3341 static HRESULT WINAPI
dwritetextformat_GetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
3342 FLOAT
*spacing
, FLOAT
*baseline
)
3344 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3345 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
3347 *method
= This
->format
.spacingmethod
;
3348 *spacing
= This
->format
.spacing
;
3349 *baseline
= This
->format
.baseline
;
3353 static HRESULT WINAPI
dwritetextformat_GetFontCollection(IDWriteTextFormat1
*iface
, IDWriteFontCollection
**collection
)
3355 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3357 TRACE("(%p)->(%p)\n", This
, collection
);
3359 *collection
= This
->format
.collection
;
3360 IDWriteFontCollection_AddRef(*collection
);
3365 static UINT32 WINAPI
dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat1
*iface
)
3367 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3368 TRACE("(%p)\n", This
);
3369 return This
->format
.family_len
;
3372 static HRESULT WINAPI
dwritetextformat_GetFontFamilyName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
3374 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3376 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
3378 if (size
<= This
->format
.family_len
) return E_NOT_SUFFICIENT_BUFFER
;
3379 strcpyW(name
, This
->format
.family_name
);
3383 static DWRITE_FONT_WEIGHT WINAPI
dwritetextformat_GetFontWeight(IDWriteTextFormat1
*iface
)
3385 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3386 TRACE("(%p)\n", This
);
3387 return This
->format
.weight
;
3390 static DWRITE_FONT_STYLE WINAPI
dwritetextformat_GetFontStyle(IDWriteTextFormat1
*iface
)
3392 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3393 TRACE("(%p)\n", This
);
3394 return This
->format
.style
;
3397 static DWRITE_FONT_STRETCH WINAPI
dwritetextformat_GetFontStretch(IDWriteTextFormat1
*iface
)
3399 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3400 TRACE("(%p)\n", This
);
3401 return This
->format
.stretch
;
3404 static FLOAT WINAPI
dwritetextformat_GetFontSize(IDWriteTextFormat1
*iface
)
3406 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3407 TRACE("(%p)\n", This
);
3408 return This
->format
.fontsize
;
3411 static UINT32 WINAPI
dwritetextformat_GetLocaleNameLength(IDWriteTextFormat1
*iface
)
3413 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3414 TRACE("(%p)\n", This
);
3415 return This
->format
.locale_len
;
3418 static HRESULT WINAPI
dwritetextformat_GetLocaleName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
3420 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3422 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
3424 if (size
<= This
->format
.locale_len
) return E_NOT_SUFFICIENT_BUFFER
;
3425 strcpyW(name
, This
->format
.locale
);
3429 static HRESULT WINAPI
dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
3431 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3433 TRACE("(%p)->(%d)\n", This
, orientation
);
3435 if ((UINT32
)orientation
> DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
)
3436 return E_INVALIDARG
;
3438 This
->format
.vertical_orientation
= orientation
;
3442 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
)
3444 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3445 TRACE("(%p)\n", This
);
3446 return This
->format
.vertical_orientation
;
3449 static HRESULT WINAPI
dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat1
*iface
, BOOL lastline_wrapping_enabled
)
3451 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3452 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
3456 static BOOL WINAPI
dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat1
*iface
)
3458 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3459 FIXME("(%p): stub\n", This
);
3463 static HRESULT WINAPI
dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat1
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
3465 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3466 FIXME("(%p)->(%d): stub\n", This
, alignment
);
3470 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat1
*iface
)
3472 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3473 FIXME("(%p): stub\n", This
);
3474 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
3477 static HRESULT WINAPI
dwritetextformat1_SetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
*fallback
)
3479 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3480 TRACE("(%p)->(%p)\n", This
, fallback
);
3481 return set_fontfallback_for_format(&This
->format
, fallback
);
3484 static HRESULT WINAPI
dwritetextformat1_GetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
**fallback
)
3486 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3487 TRACE("(%p)->(%p)\n", This
, fallback
);
3488 return get_fontfallback_from_format(&This
->format
, fallback
);
3491 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl
= {
3492 dwritetextformat_QueryInterface
,
3493 dwritetextformat_AddRef
,
3494 dwritetextformat_Release
,
3495 dwritetextformat_SetTextAlignment
,
3496 dwritetextformat_SetParagraphAlignment
,
3497 dwritetextformat_SetWordWrapping
,
3498 dwritetextformat_SetReadingDirection
,
3499 dwritetextformat_SetFlowDirection
,
3500 dwritetextformat_SetIncrementalTabStop
,
3501 dwritetextformat_SetTrimming
,
3502 dwritetextformat_SetLineSpacing
,
3503 dwritetextformat_GetTextAlignment
,
3504 dwritetextformat_GetParagraphAlignment
,
3505 dwritetextformat_GetWordWrapping
,
3506 dwritetextformat_GetReadingDirection
,
3507 dwritetextformat_GetFlowDirection
,
3508 dwritetextformat_GetIncrementalTabStop
,
3509 dwritetextformat_GetTrimming
,
3510 dwritetextformat_GetLineSpacing
,
3511 dwritetextformat_GetFontCollection
,
3512 dwritetextformat_GetFontFamilyNameLength
,
3513 dwritetextformat_GetFontFamilyName
,
3514 dwritetextformat_GetFontWeight
,
3515 dwritetextformat_GetFontStyle
,
3516 dwritetextformat_GetFontStretch
,
3517 dwritetextformat_GetFontSize
,
3518 dwritetextformat_GetLocaleNameLength
,
3519 dwritetextformat_GetLocaleName
,
3520 dwritetextformat1_SetVerticalGlyphOrientation
,
3521 dwritetextformat1_GetVerticalGlyphOrientation
,
3522 dwritetextformat1_SetLastLineWrapping
,
3523 dwritetextformat1_GetLastLineWrapping
,
3524 dwritetextformat1_SetOpticalAlignment
,
3525 dwritetextformat1_GetOpticalAlignment
,
3526 dwritetextformat1_SetFontFallback
,
3527 dwritetextformat1_GetFontFallback
3530 HRESULT
create_textformat(const WCHAR
*family_name
, IDWriteFontCollection
*collection
, DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STYLE style
,
3531 DWRITE_FONT_STRETCH stretch
, FLOAT size
, const WCHAR
*locale
, IDWriteTextFormat
**format
)
3533 struct dwrite_textformat
*This
;
3537 This
= heap_alloc(sizeof(struct dwrite_textformat
));
3538 if (!This
) return E_OUTOFMEMORY
;
3540 This
->IDWriteTextFormat1_iface
.lpVtbl
= &dwritetextformatvtbl
;
3542 This
->format
.family_name
= heap_strdupW(family_name
);
3543 This
->format
.family_len
= strlenW(family_name
);
3544 This
->format
.locale
= heap_strdupW(locale
);
3545 This
->format
.locale_len
= strlenW(locale
);
3546 This
->format
.weight
= weight
;
3547 This
->format
.style
= style
;
3548 This
->format
.fontsize
= size
;
3549 This
->format
.stretch
= stretch
;
3550 This
->format
.textalignment
= DWRITE_TEXT_ALIGNMENT_LEADING
;
3551 This
->format
.paralign
= DWRITE_PARAGRAPH_ALIGNMENT_NEAR
;
3552 This
->format
.wrapping
= DWRITE_WORD_WRAPPING_WRAP
;
3553 This
->format
.readingdir
= DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
;
3554 This
->format
.flow
= DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
;
3555 This
->format
.spacingmethod
= DWRITE_LINE_SPACING_METHOD_DEFAULT
;
3556 This
->format
.vertical_orientation
= DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
3557 This
->format
.spacing
= 0.0;
3558 This
->format
.baseline
= 0.0;
3559 This
->format
.trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_NONE
;
3560 This
->format
.trimming
.delimiter
= 0;
3561 This
->format
.trimming
.delimiterCount
= 0;
3562 This
->format
.trimmingsign
= NULL
;
3563 This
->format
.collection
= collection
;
3564 This
->format
.fallback
= NULL
;
3565 IDWriteFontCollection_AddRef(collection
);
3567 *format
= (IDWriteTextFormat
*)&This
->IDWriteTextFormat1_iface
;
3572 static HRESULT WINAPI
dwritetypography_QueryInterface(IDWriteTypography
*iface
, REFIID riid
, void **obj
)
3574 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
3576 TRACE("(%p)->(%s %p)\n", typography
, debugstr_guid(riid
), obj
);
3578 if (IsEqualIID(riid
, &IID_IDWriteTypography
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3580 IDWriteTypography_AddRef(iface
);
3586 return E_NOINTERFACE
;
3589 static ULONG WINAPI
dwritetypography_AddRef(IDWriteTypography
*iface
)
3591 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
3592 ULONG ref
= InterlockedIncrement(&typography
->ref
);
3593 TRACE("(%p)->(%d)\n", typography
, ref
);
3597 static ULONG WINAPI
dwritetypography_Release(IDWriteTypography
*iface
)
3599 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
3600 ULONG ref
= InterlockedDecrement(&typography
->ref
);
3602 TRACE("(%p)->(%d)\n", typography
, ref
);
3605 heap_free(typography
->features
);
3606 heap_free(typography
);
3612 static HRESULT WINAPI
dwritetypography_AddFontFeature(IDWriteTypography
*iface
, DWRITE_FONT_FEATURE feature
)
3614 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
3616 TRACE("(%p)->(%x %u)\n", typography
, feature
.nameTag
, feature
.parameter
);
3618 if (typography
->count
== typography
->allocated
) {
3619 DWRITE_FONT_FEATURE
*ptr
= heap_realloc(typography
->features
, 2*typography
->allocated
*sizeof(DWRITE_FONT_FEATURE
));
3621 return E_OUTOFMEMORY
;
3623 typography
->features
= ptr
;
3624 typography
->allocated
*= 2;
3627 typography
->features
[typography
->count
++] = feature
;
3631 static UINT32 WINAPI
dwritetypography_GetFontFeatureCount(IDWriteTypography
*iface
)
3633 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
3634 TRACE("(%p)\n", typography
);
3635 return typography
->count
;
3638 static HRESULT WINAPI
dwritetypography_GetFontFeature(IDWriteTypography
*iface
, UINT32 index
, DWRITE_FONT_FEATURE
*feature
)
3640 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
3642 TRACE("(%p)->(%u %p)\n", typography
, index
, feature
);
3644 if (index
>= typography
->count
)
3645 return E_INVALIDARG
;
3647 *feature
= typography
->features
[index
];
3651 static const IDWriteTypographyVtbl dwritetypographyvtbl
= {
3652 dwritetypography_QueryInterface
,
3653 dwritetypography_AddRef
,
3654 dwritetypography_Release
,
3655 dwritetypography_AddFontFeature
,
3656 dwritetypography_GetFontFeatureCount
,
3657 dwritetypography_GetFontFeature
3660 HRESULT
create_typography(IDWriteTypography
**ret
)
3662 struct dwrite_typography
*typography
;
3666 typography
= heap_alloc(sizeof(*typography
));
3668 return E_OUTOFMEMORY
;
3670 typography
->IDWriteTypography_iface
.lpVtbl
= &dwritetypographyvtbl
;
3671 typography
->ref
= 1;
3672 typography
->allocated
= 2;
3673 typography
->count
= 0;
3675 typography
->features
= heap_alloc(typography
->allocated
*sizeof(DWRITE_FONT_FEATURE
));
3676 if (!typography
->features
) {
3677 heap_free(typography
);
3678 return E_OUTOFMEMORY
;
3681 *ret
= &typography
->IDWriteTypography_iface
;