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
,
76 LAYOUT_RANGE_ATTR_SPACING
79 struct layout_range_attr_value
{
80 DWRITE_TEXT_RANGE range
;
82 DWRITE_FONT_WEIGHT weight
;
83 DWRITE_FONT_STYLE style
;
84 DWRITE_FONT_STRETCH stretch
;
86 IDWriteInlineObject
*object
;
91 IDWriteFontCollection
*collection
;
93 const WCHAR
*fontfamily
;
94 FLOAT spacing
[3]; /* in arguments order - leading, trailing, advance */
98 enum layout_range_kind
{
100 LAYOUT_RANGE_STRIKETHROUGH
,
105 struct layout_range_header
{
107 enum layout_range_kind kind
;
108 DWRITE_TEXT_RANGE range
;
111 struct layout_range
{
112 struct layout_range_header h
;
113 DWRITE_FONT_WEIGHT weight
;
114 DWRITE_FONT_STYLE style
;
116 DWRITE_FONT_STRETCH stretch
;
117 IDWriteInlineObject
*object
;
120 IDWriteFontCollection
*collection
;
121 WCHAR locale
[LOCALE_NAME_MAX_LENGTH
];
125 struct layout_range_bool
{
126 struct layout_range_header h
;
130 struct layout_range_effect
{
131 struct layout_range_header h
;
135 struct layout_range_spacing
{
136 struct layout_range_header h
;
142 enum layout_run_kind
{
147 struct inline_object_run
{
148 IDWriteInlineObject
*object
;
152 struct regular_layout_run
{
153 DWRITE_GLYPH_RUN_DESCRIPTION descr
;
154 DWRITE_GLYPH_RUN run
;
155 DWRITE_SCRIPT_ANALYSIS sa
;
159 DWRITE_GLYPH_OFFSET
*offsets
;
160 /* this is actual glyph count after shaping, it's not necessary the same as reported to Draw() */
166 enum layout_run_kind kind
;
168 struct inline_object_run object
;
169 struct regular_layout_run regular
;
175 struct layout_effective_run
{
177 const struct layout_run
*run
; /* nominal run this one is based on */
178 UINT32 start
; /* relative text position, 0 means first text position of a nominal run */
179 UINT32 length
; /* length in codepoints that this run covers */
180 UINT32 glyphcount
; /* total glyph count in this run */
181 FLOAT origin_x
; /* baseline X position */
182 FLOAT origin_y
; /* baseline Y position */
183 UINT16
*clustermap
; /* effective clustermap, allocated separately, is not reused from nominal map */
187 struct layout_effective_inline
{
189 IDWriteInlineObject
*object
;
198 struct layout_strikethrough
{
200 const struct layout_effective_run
*run
;
201 DWRITE_STRIKETHROUGH s
;
204 struct layout_cluster
{
205 const struct layout_run
*run
; /* link to nominal run this cluster belongs to */
206 UINT32 position
; /* relative to run, first cluster has 0 position */
209 enum layout_recompute_mask
{
210 RECOMPUTE_NOMINAL_RUNS
= 1 << 0,
211 RECOMPUTE_MINIMAL_WIDTH
= 1 << 1,
212 RECOMPUTE_EFFECTIVE_RUNS
= 1 << 2,
213 RECOMPUTE_EVERYTHING
= 0xffff
216 struct dwrite_textlayout
{
217 IDWriteTextLayout2 IDWriteTextLayout2_iface
;
218 IDWriteTextFormat1 IDWriteTextFormat1_iface
;
219 IDWriteTextAnalysisSink IDWriteTextAnalysisSink_iface
;
220 IDWriteTextAnalysisSource IDWriteTextAnalysisSource_iface
;
225 struct dwrite_textformat_data format
;
228 struct list strike_ranges
;
233 /* lists ready to use by Draw() */
235 struct list inlineobjects
;
236 struct list strikethrough
;
239 DWRITE_LINE_BREAKPOINT
*nominal_breakpoints
;
240 DWRITE_LINE_BREAKPOINT
*actual_breakpoints
;
242 struct layout_cluster
*clusters
;
243 DWRITE_CLUSTER_METRICS
*clustermetrics
;
244 UINT32 cluster_count
;
247 DWRITE_LINE_METRICS
*lines
;
251 /* gdi-compatible layout specifics */
253 FLOAT pixels_per_dip
;
254 BOOL use_gdi_natural
;
255 DWRITE_MATRIX transform
;
258 struct dwrite_textformat
{
259 IDWriteTextFormat1 IDWriteTextFormat1_iface
;
261 struct dwrite_textformat_data format
;
264 struct dwrite_trimmingsign
{
265 IDWriteInlineObject IDWriteInlineObject_iface
;
268 IDWriteTextLayout
*layout
;
271 struct dwrite_typography
{
272 IDWriteTypography IDWriteTypography_iface
;
275 DWRITE_FONT_FEATURE
*features
;
280 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl
;
282 static void release_format_data(struct dwrite_textformat_data
*data
)
284 if (data
->collection
) IDWriteFontCollection_Release(data
->collection
);
285 if (data
->fallback
) IDWriteFontFallback_Release(data
->fallback
);
286 if (data
->trimmingsign
) IDWriteInlineObject_Release(data
->trimmingsign
);
287 heap_free(data
->family_name
);
288 heap_free(data
->locale
);
291 static inline struct dwrite_textlayout
*impl_from_IDWriteTextLayout2(IDWriteTextLayout2
*iface
)
293 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextLayout2_iface
);
296 static inline struct dwrite_textlayout
*impl_layout_form_IDWriteTextFormat1(IDWriteTextFormat1
*iface
)
298 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextFormat1_iface
);
301 static inline struct dwrite_textlayout
*impl_from_IDWriteTextAnalysisSink(IDWriteTextAnalysisSink
*iface
)
303 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextAnalysisSink_iface
);
306 static inline struct dwrite_textlayout
*impl_from_IDWriteTextAnalysisSource(IDWriteTextAnalysisSource
*iface
)
308 return CONTAINING_RECORD(iface
, struct dwrite_textlayout
, IDWriteTextAnalysisSource_iface
);
311 static inline struct dwrite_textformat
*impl_from_IDWriteTextFormat1(IDWriteTextFormat1
*iface
)
313 return CONTAINING_RECORD(iface
, struct dwrite_textformat
, IDWriteTextFormat1_iface
);
316 static inline struct dwrite_trimmingsign
*impl_from_IDWriteInlineObject(IDWriteInlineObject
*iface
)
318 return CONTAINING_RECORD(iface
, struct dwrite_trimmingsign
, IDWriteInlineObject_iface
);
321 static inline struct dwrite_typography
*impl_from_IDWriteTypography(IDWriteTypography
*iface
)
323 return CONTAINING_RECORD(iface
, struct dwrite_typography
, IDWriteTypography_iface
);
326 static inline const char *debugstr_run(const struct regular_layout_run
*run
)
328 return wine_dbg_sprintf("[%u,%u)", run
->descr
.textPosition
, run
->descr
.textPosition
+
329 run
->descr
.stringLength
);
332 static HRESULT
get_fontfallback_from_format(const struct dwrite_textformat_data
*format
, IDWriteFontFallback
**fallback
)
334 *fallback
= format
->fallback
;
336 IDWriteFontFallback_AddRef(*fallback
);
340 static HRESULT
set_fontfallback_for_format(struct dwrite_textformat_data
*format
, IDWriteFontFallback
*fallback
)
342 if (format
->fallback
)
343 IDWriteFontFallback_Release(format
->fallback
);
344 format
->fallback
= fallback
;
346 IDWriteFontFallback_AddRef(fallback
);
350 static struct layout_run
*alloc_layout_run(enum layout_run_kind kind
)
352 struct layout_run
*ret
;
354 ret
= heap_alloc(sizeof(*ret
));
355 if (!ret
) return NULL
;
357 memset(ret
, 0, sizeof(*ret
));
359 if (kind
== LAYOUT_RUN_REGULAR
) {
360 ret
->u
.regular
.sa
.script
= Script_Unknown
;
361 ret
->u
.regular
.sa
.shapes
= DWRITE_SCRIPT_SHAPES_DEFAULT
;
367 static void free_layout_runs(struct dwrite_textlayout
*layout
)
369 struct layout_run
*cur
, *cur2
;
370 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->runs
, struct layout_run
, entry
) {
371 list_remove(&cur
->entry
);
372 if (cur
->kind
== LAYOUT_RUN_REGULAR
) {
373 if (cur
->u
.regular
.run
.fontFace
)
374 IDWriteFontFace_Release(cur
->u
.regular
.run
.fontFace
);
375 heap_free(cur
->u
.regular
.glyphs
);
376 heap_free(cur
->u
.regular
.clustermap
);
377 heap_free(cur
->u
.regular
.advances
);
378 heap_free(cur
->u
.regular
.offsets
);
384 static void free_layout_eruns(struct dwrite_textlayout
*layout
)
386 struct layout_effective_inline
*in
, *in2
;
387 struct layout_effective_run
*cur
, *cur2
;
388 struct layout_strikethrough
*s
, *s2
;
390 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->eruns
, struct layout_effective_run
, entry
) {
391 list_remove(&cur
->entry
);
392 heap_free(cur
->clustermap
);
396 LIST_FOR_EACH_ENTRY_SAFE(in
, in2
, &layout
->inlineobjects
, struct layout_effective_inline
, entry
) {
397 list_remove(&in
->entry
);
401 LIST_FOR_EACH_ENTRY_SAFE(s
, s2
, &layout
->strikethrough
, struct layout_strikethrough
, entry
) {
402 list_remove(&s
->entry
);
407 /* Used to resolve break condition by forcing stronger condition over weaker. */
408 static inline DWRITE_BREAK_CONDITION
override_break_condition(DWRITE_BREAK_CONDITION existingbreak
, DWRITE_BREAK_CONDITION newbreak
)
410 switch (existingbreak
) {
411 case DWRITE_BREAK_CONDITION_NEUTRAL
:
413 case DWRITE_BREAK_CONDITION_CAN_BREAK
:
414 return newbreak
== DWRITE_BREAK_CONDITION_NEUTRAL
? existingbreak
: newbreak
;
415 /* let's keep stronger conditions as is */
416 case DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
:
417 case DWRITE_BREAK_CONDITION_MUST_BREAK
:
420 ERR("unknown break condition %d\n", existingbreak
);
423 return existingbreak
;
426 /* Actual breakpoint data gets updated with break condition required by inline object set for range 'cur'. */
427 static HRESULT
layout_update_breakpoints_range(struct dwrite_textlayout
*layout
, const struct layout_range
*cur
)
429 DWRITE_BREAK_CONDITION before
, after
;
433 /* ignore returned conditions if failed */
434 hr
= IDWriteInlineObject_GetBreakConditions(cur
->object
, &before
, &after
);
436 after
= before
= DWRITE_BREAK_CONDITION_NEUTRAL
;
438 if (!layout
->actual_breakpoints
) {
439 layout
->actual_breakpoints
= heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
440 if (!layout
->actual_breakpoints
)
441 return E_OUTOFMEMORY
;
442 memcpy(layout
->actual_breakpoints
, layout
->nominal_breakpoints
, sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
445 for (i
= cur
->h
.range
.startPosition
; i
< cur
->h
.range
.length
+ cur
->h
.range
.startPosition
; i
++) {
446 /* for first codepoint check if there's anything before it and update accordingly */
447 if (i
== cur
->h
.range
.startPosition
) {
449 layout
->actual_breakpoints
[i
].breakConditionBefore
= layout
->actual_breakpoints
[i
-1].breakConditionAfter
=
450 override_break_condition(layout
->actual_breakpoints
[i
-1].breakConditionAfter
, before
);
452 layout
->actual_breakpoints
[i
].breakConditionBefore
= before
;
453 layout
->actual_breakpoints
[i
].breakConditionAfter
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
455 /* similar check for last codepoint */
456 else if (i
== cur
->h
.range
.startPosition
+ cur
->h
.range
.length
- 1) {
457 if (i
== layout
->len
- 1)
458 layout
->actual_breakpoints
[i
].breakConditionAfter
= after
;
460 layout
->actual_breakpoints
[i
].breakConditionAfter
= layout
->actual_breakpoints
[i
+1].breakConditionBefore
=
461 override_break_condition(layout
->actual_breakpoints
[i
+1].breakConditionBefore
, after
);
462 layout
->actual_breakpoints
[i
].breakConditionBefore
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
464 /* for all positions within a range disable breaks */
466 layout
->actual_breakpoints
[i
].breakConditionBefore
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
467 layout
->actual_breakpoints
[i
].breakConditionAfter
= DWRITE_BREAK_CONDITION_MAY_NOT_BREAK
;
470 layout
->actual_breakpoints
[i
].isWhitespace
= FALSE
;
471 layout
->actual_breakpoints
[i
].isSoftHyphen
= FALSE
;
477 static struct layout_range
*get_layout_range_by_pos(struct dwrite_textlayout
*layout
, UINT32 pos
);
479 static inline DWRITE_LINE_BREAKPOINT
get_effective_breakpoint(const struct dwrite_textlayout
*layout
, UINT32 pos
)
481 if (layout
->actual_breakpoints
)
482 return layout
->actual_breakpoints
[pos
];
483 return layout
->nominal_breakpoints
[pos
];
486 static inline void init_cluster_metrics(const struct dwrite_textlayout
*layout
, const struct regular_layout_run
*run
,
487 UINT16 start_glyph
, UINT16 stop_glyph
, UINT32 stop_position
, UINT16 length
, DWRITE_CLUSTER_METRICS
*metrics
)
489 UINT8 breakcondition
;
493 /* For clusters made of control chars we report zero glyphs, and we need zero cluster
494 width as well; advances are already computed at this point and are not necessary zero. */
495 metrics
->width
= 0.0;
496 if (run
->run
.glyphCount
) {
497 for (j
= start_glyph
; j
< stop_glyph
; j
++)
498 metrics
->width
+= run
->run
.glyphAdvances
[j
];
500 metrics
->length
= length
;
502 position
= stop_position
;
503 if (stop_glyph
== run
->glyphcount
)
504 breakcondition
= get_effective_breakpoint(layout
, stop_position
).breakConditionAfter
;
506 breakcondition
= get_effective_breakpoint(layout
, stop_position
).breakConditionBefore
;
507 if (stop_position
) position
= stop_position
- 1;
510 metrics
->canWrapLineAfter
= breakcondition
== DWRITE_BREAK_CONDITION_CAN_BREAK
||
511 breakcondition
== DWRITE_BREAK_CONDITION_MUST_BREAK
;
512 if (metrics
->length
== 1) {
515 GetStringTypeW(CT_CTYPE1
, &layout
->str
[position
], 1, &type
);
516 metrics
->isWhitespace
= !!(type
& C1_SPACE
);
517 metrics
->isNewline
= FALSE
/* FIXME */;
518 metrics
->isSoftHyphen
= layout
->str
[position
] == 0x00ad /* Unicode Soft Hyphen */;
521 metrics
->isWhitespace
= FALSE
;
522 metrics
->isNewline
= FALSE
;
523 metrics
->isSoftHyphen
= FALSE
;
525 metrics
->isRightToLeft
= run
->run
.bidiLevel
& 1;
526 metrics
->padding
= 0;
531 All clusters in a 'run' will be added to 'layout' data, starting at index pointed to by 'cluster'.
532 On return 'cluster' is updated to point to next metrics struct to be filled in on next call.
533 Note that there's no need to reallocate anything at this point as we allocate one cluster per
537 static void layout_set_cluster_metrics(struct dwrite_textlayout
*layout
, const struct layout_run
*r
, UINT32
*cluster
)
539 DWRITE_CLUSTER_METRICS
*metrics
= &layout
->clustermetrics
[*cluster
];
540 struct layout_cluster
*c
= &layout
->clusters
[*cluster
];
541 const struct regular_layout_run
*run
= &r
->u
.regular
;
544 for (i
= 0; i
< run
->descr
.stringLength
; i
++) {
545 BOOL end
= i
== run
->descr
.stringLength
- 1;
547 if (run
->descr
.clusterMap
[start
] != run
->descr
.clusterMap
[i
]) {
548 init_cluster_metrics(layout
, run
, run
->descr
.clusterMap
[start
], run
->descr
.clusterMap
[i
], i
,
560 init_cluster_metrics(layout
, run
, run
->descr
.clusterMap
[start
], run
->glyphcount
, i
,
561 i
- start
+ 1, metrics
);
571 /* This helper should be used to get effective range length, in other words it returns number of text
572 positions from range starting point to the end of the range, limited by layout text length */
573 static inline UINT32
get_clipped_range_length(const struct dwrite_textlayout
*layout
, const struct layout_range
*range
)
575 if (range
->h
.range
.startPosition
+ range
->h
.range
.length
<= layout
->len
)
576 return range
->h
.range
.length
;
577 return layout
->len
- range
->h
.range
.startPosition
;
580 static inline FLOAT
get_scaled_font_metric(UINT32 metric
, FLOAT emSize
, const DWRITE_FONT_METRICS
*metrics
)
582 return (FLOAT
)metric
* emSize
/ (FLOAT
)metrics
->designUnitsPerEm
;
585 static HRESULT
layout_compute_runs(struct dwrite_textlayout
*layout
)
587 IDWriteTextAnalyzer
*analyzer
;
588 struct layout_range
*range
;
589 struct layout_run
*r
;
593 free_layout_eruns(layout
);
594 free_layout_runs(layout
);
596 /* Cluster data arrays are allocated once, assuming one text position per cluster. */
597 if (!layout
->clustermetrics
) {
598 layout
->clustermetrics
= heap_alloc(layout
->len
*sizeof(*layout
->clustermetrics
));
599 layout
->clusters
= heap_alloc(layout
->len
*sizeof(*layout
->clusters
));
600 if (!layout
->clustermetrics
|| !layout
->clusters
) {
601 heap_free(layout
->clustermetrics
);
602 heap_free(layout
->clusters
);
603 return E_OUTOFMEMORY
;
606 layout
->cluster_count
= 0;
608 hr
= get_textanalyzer(&analyzer
);
612 LIST_FOR_EACH_ENTRY(range
, &layout
->ranges
, struct layout_range
, h
.entry
) {
613 /* we don't care about ranges that don't contain any text */
614 if (range
->h
.range
.startPosition
>= layout
->len
)
617 /* inline objects override actual text in a range */
619 hr
= layout_update_breakpoints_range(layout
, range
);
623 r
= alloc_layout_run(LAYOUT_RUN_INLINE
);
625 return E_OUTOFMEMORY
;
627 r
->u
.object
.object
= range
->object
;
628 r
->u
.object
.length
= get_clipped_range_length(layout
, range
);
629 list_add_tail(&layout
->runs
, &r
->entry
);
633 /* initial splitting by script */
634 hr
= IDWriteTextAnalyzer_AnalyzeScript(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
635 range
->h
.range
.startPosition
, get_clipped_range_length(layout
, range
), &layout
->IDWriteTextAnalysisSink_iface
);
639 /* this splits it further */
640 hr
= IDWriteTextAnalyzer_AnalyzeBidi(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
641 range
->h
.range
.startPosition
, get_clipped_range_length(layout
, range
), &layout
->IDWriteTextAnalysisSink_iface
);
647 LIST_FOR_EACH_ENTRY(r
, &layout
->runs
, struct layout_run
, entry
) {
648 DWRITE_SHAPING_GLYPH_PROPERTIES
*glyph_props
= NULL
;
649 DWRITE_SHAPING_TEXT_PROPERTIES
*text_props
= NULL
;
650 struct regular_layout_run
*run
= &r
->u
.regular
;
651 DWRITE_FONT_METRICS fontmetrics
= { 0 };
652 IDWriteFontFamily
*family
;
653 UINT32 index
, max_count
;
657 /* we need to do very little in case of inline objects */
658 if (r
->kind
== LAYOUT_RUN_INLINE
) {
659 DWRITE_CLUSTER_METRICS
*metrics
= &layout
->clustermetrics
[cluster
];
660 struct layout_cluster
*c
= &layout
->clusters
[cluster
];
661 DWRITE_INLINE_OBJECT_METRICS inlinemetrics
;
663 metrics
->width
= 0.0;
664 metrics
->length
= r
->u
.object
.length
;
665 metrics
->canWrapLineAfter
= FALSE
;
666 metrics
->isWhitespace
= FALSE
;
667 metrics
->isNewline
= FALSE
;
668 metrics
->isSoftHyphen
= FALSE
;
669 metrics
->isRightToLeft
= FALSE
;
670 metrics
->padding
= 0;
672 c
->position
= 0; /* there's always one cluster per inline object, so 0 is valid value */
675 /* it's not fatal if GetMetrics() fails, all returned metrics are ignored */
676 hr
= IDWriteInlineObject_GetMetrics(r
->u
.object
.object
, &inlinemetrics
);
678 memset(&inlinemetrics
, 0, sizeof(inlinemetrics
));
681 metrics
->width
= inlinemetrics
.width
;
682 r
->baseline
= inlinemetrics
.baseline
;
683 r
->height
= inlinemetrics
.height
;
685 /* FIXME: use resolved breakpoints in this case too */
690 range
= get_layout_range_by_pos(layout
, run
->descr
.textPosition
);
692 hr
= IDWriteFontCollection_FindFamilyName(range
->collection
, range
->fontfamily
, &index
, &exists
);
693 if (FAILED(hr
) || !exists
) {
694 WARN("%s: family %s not found in collection %p\n", debugstr_run(run
), debugstr_w(range
->fontfamily
), range
->collection
);
698 hr
= IDWriteFontCollection_GetFontFamily(range
->collection
, index
, &family
);
702 hr
= IDWriteFontFamily_GetFirstMatchingFont(family
, range
->weight
, range
->stretch
, range
->style
, &font
);
703 IDWriteFontFamily_Release(family
);
705 WARN("%s: failed to get a matching font\n", debugstr_run(run
));
709 hr
= IDWriteFont_CreateFontFace(font
, &run
->run
.fontFace
);
710 IDWriteFont_Release(font
);
714 run
->run
.fontEmSize
= range
->fontsize
;
715 run
->descr
.localeName
= range
->locale
;
716 run
->clustermap
= heap_alloc(run
->descr
.stringLength
*sizeof(UINT16
));
718 max_count
= 3*run
->descr
.stringLength
/2 + 16;
719 run
->glyphs
= heap_alloc(max_count
*sizeof(UINT16
));
720 if (!run
->clustermap
|| !run
->glyphs
)
723 text_props
= heap_alloc(run
->descr
.stringLength
*sizeof(DWRITE_SHAPING_TEXT_PROPERTIES
));
724 glyph_props
= heap_alloc(max_count
*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES
));
725 if (!text_props
|| !glyph_props
)
729 hr
= IDWriteTextAnalyzer_GetGlyphs(analyzer
, run
->descr
.string
, run
->descr
.stringLength
,
730 run
->run
.fontFace
, run
->run
.isSideways
, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
,
731 NULL
/* FIXME */, NULL
, NULL
, 0, max_count
, run
->clustermap
, text_props
, run
->glyphs
, glyph_props
,
733 if (hr
== E_NOT_SUFFICIENT_BUFFER
) {
734 heap_free(run
->glyphs
);
735 heap_free(glyph_props
);
737 max_count
= run
->glyphcount
;
739 run
->glyphs
= heap_alloc(max_count
*sizeof(UINT16
));
740 glyph_props
= heap_alloc(max_count
*sizeof(DWRITE_SHAPING_GLYPH_PROPERTIES
));
741 if (!run
->glyphs
|| !glyph_props
)
751 heap_free(text_props
);
752 heap_free(glyph_props
);
753 WARN("%s: shaping failed 0x%08x\n", debugstr_run(run
), hr
);
757 run
->run
.glyphIndices
= run
->glyphs
;
758 run
->descr
.clusterMap
= run
->clustermap
;
760 run
->advances
= heap_alloc(run
->glyphcount
*sizeof(FLOAT
));
761 run
->offsets
= heap_alloc(run
->glyphcount
*sizeof(DWRITE_GLYPH_OFFSET
));
762 if (!run
->advances
|| !run
->offsets
)
765 /* now set advances and offsets */
766 if (layout
->gdicompatible
)
767 hr
= IDWriteTextAnalyzer_GetGdiCompatibleGlyphPlacements(analyzer
, run
->descr
.string
, run
->descr
.clusterMap
,
768 text_props
, run
->descr
.stringLength
, run
->run
.glyphIndices
, glyph_props
, run
->glyphcount
,
769 run
->run
.fontFace
, run
->run
.fontEmSize
, layout
->pixels_per_dip
, &layout
->transform
, layout
->use_gdi_natural
,
770 run
->run
.isSideways
, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
, NULL
, NULL
, 0,
771 run
->advances
, run
->offsets
);
773 hr
= IDWriteTextAnalyzer_GetGlyphPlacements(analyzer
, run
->descr
.string
, run
->descr
.clusterMap
, text_props
,
774 run
->descr
.stringLength
, run
->run
.glyphIndices
, glyph_props
, run
->glyphcount
, run
->run
.fontFace
,
775 run
->run
.fontEmSize
, run
->run
.isSideways
, run
->run
.bidiLevel
& 1, &run
->sa
, run
->descr
.localeName
,
776 NULL
, NULL
, 0, run
->advances
, run
->offsets
);
778 heap_free(text_props
);
779 heap_free(glyph_props
);
781 WARN("%s: failed to get glyph placement info, 0x%08x\n", debugstr_run(run
), hr
);
783 run
->run
.glyphAdvances
= run
->advances
;
784 run
->run
.glyphOffsets
= run
->offsets
;
786 /* Special treatment of control script, shaping code adds normal glyphs for it,
787 with non-zero advances, and layout code exposes those as zero width clusters,
788 so we have to do it manually. */
789 if (run
->sa
.script
== Script_Common
)
790 run
->run
.glyphCount
= 0;
792 run
->run
.glyphCount
= run
->glyphcount
;
794 /* baseline derived from font metrics */
795 if (layout
->gdicompatible
) {
796 /* FIXME: check return value when it's actually implemented */
797 IDWriteFontFace_GetGdiCompatibleMetrics(run
->run
.fontFace
,
799 layout
->pixels_per_dip
,
804 IDWriteFontFace_GetMetrics(run
->run
.fontFace
, &fontmetrics
);
806 r
->baseline
= get_scaled_font_metric(fontmetrics
.ascent
, run
->run
.fontEmSize
, &fontmetrics
);
807 r
->height
= get_scaled_font_metric(fontmetrics
.ascent
+ fontmetrics
.descent
, run
->run
.fontEmSize
, &fontmetrics
);
809 layout_set_cluster_metrics(layout
, r
, &cluster
);
814 heap_free(text_props
);
815 heap_free(glyph_props
);
816 heap_free(run
->clustermap
);
817 heap_free(run
->glyphs
);
818 heap_free(run
->advances
);
819 heap_free(run
->offsets
);
820 run
->advances
= NULL
;
822 run
->clustermap
= run
->glyphs
= NULL
;
828 layout
->cluster_count
= cluster
;
830 IDWriteTextAnalyzer_Release(analyzer
);
834 static HRESULT
layout_compute(struct dwrite_textlayout
*layout
)
838 if (!(layout
->recompute
& RECOMPUTE_NOMINAL_RUNS
))
841 /* nominal breakpoints are evaluated only once, because string never changes */
842 if (!layout
->nominal_breakpoints
) {
843 IDWriteTextAnalyzer
*analyzer
;
846 layout
->nominal_breakpoints
= heap_alloc(sizeof(DWRITE_LINE_BREAKPOINT
)*layout
->len
);
847 if (!layout
->nominal_breakpoints
)
848 return E_OUTOFMEMORY
;
850 hr
= get_textanalyzer(&analyzer
);
854 hr
= IDWriteTextAnalyzer_AnalyzeLineBreakpoints(analyzer
, &layout
->IDWriteTextAnalysisSource_iface
,
855 0, layout
->len
, &layout
->IDWriteTextAnalysisSink_iface
);
856 IDWriteTextAnalyzer_Release(analyzer
);
858 if (layout
->actual_breakpoints
) {
859 heap_free(layout
->actual_breakpoints
);
860 layout
->actual_breakpoints
= NULL
;
863 hr
= layout_compute_runs(layout
);
865 if (TRACE_ON(dwrite
)) {
866 struct layout_run
*cur
;
868 LIST_FOR_EACH_ENTRY(cur
, &layout
->runs
, struct layout_run
, entry
) {
869 if (cur
->kind
== LAYOUT_RUN_INLINE
)
870 TRACE("run inline object %p, len %u\n", cur
->u
.object
.object
, cur
->u
.object
.length
);
872 TRACE("run [%u,%u], len %u, bidilevel %u\n", cur
->u
.regular
.descr
.textPosition
, cur
->u
.regular
.descr
.textPosition
+
873 cur
->u
.regular
.descr
.stringLength
-1, cur
->u
.regular
.descr
.stringLength
, cur
->u
.regular
.run
.bidiLevel
);
877 layout
->recompute
&= ~RECOMPUTE_NOMINAL_RUNS
;
881 static inline FLOAT
get_cluster_range_width(struct dwrite_textlayout
*layout
, UINT32 start
, UINT32 end
)
884 for (; start
< end
; start
++)
885 width
+= layout
->clustermetrics
[start
].width
;
889 static struct layout_range_header
*get_layout_range_header_by_pos(struct list
*ranges
, UINT32 pos
)
891 struct layout_range_header
*cur
;
893 LIST_FOR_EACH_ENTRY(cur
, ranges
, struct layout_range_header
, entry
) {
894 DWRITE_TEXT_RANGE
*r
= &cur
->range
;
895 if (r
->startPosition
<= pos
&& pos
< r
->startPosition
+ r
->length
)
902 static inline IUnknown
*layout_get_effect_from_pos(struct dwrite_textlayout
*layout
, UINT32 pos
)
904 struct layout_range_header
*h
= get_layout_range_header_by_pos(&layout
->effects
, pos
);
905 return ((struct layout_range_effect
*)h
)->effect
;
908 /* Effective run is built from consecutive clusters of a single nominal run, 'first_cluster' is 0 based cluster index,
909 'cluster_count' indicates how many clusters to add, including first one. */
910 static HRESULT
layout_add_effective_run(struct dwrite_textlayout
*layout
, const struct layout_run
*r
, UINT32 first_cluster
,
911 UINT32 cluster_count
, UINT32 line
, FLOAT origin_x
, BOOL strikethrough
)
913 UINT32 i
, start
, length
, last_cluster
;
914 struct layout_effective_run
*run
;
916 if (r
->kind
== LAYOUT_RUN_INLINE
) {
917 struct layout_effective_inline
*inlineobject
;
919 inlineobject
= heap_alloc(sizeof(*inlineobject
));
921 return E_OUTOFMEMORY
;
923 inlineobject
->object
= r
->u
.object
.object
;
924 inlineobject
->origin_x
= origin_x
;
925 inlineobject
->origin_y
= 0.0; /* FIXME */
926 /* It's not clear how these two are set, possibly directionality
927 is derived from surrounding text (replaced text could have
928 different ranges which differ in reading direction). */
929 inlineobject
->is_sideways
= FALSE
;
930 inlineobject
->is_rtl
= FALSE
;
931 inlineobject
->line
= line
;
933 /* effect assigned from start position and on is used for inline objects */
934 inlineobject
->effect
= layout_get_effect_from_pos(layout
, layout
->clusters
[first_cluster
].position
);
936 list_add_tail(&layout
->inlineobjects
, &inlineobject
->entry
);
940 run
= heap_alloc(sizeof(*run
));
942 return E_OUTOFMEMORY
;
944 /* No need to iterate for that, use simple fact that:
945 <last cluster position> = first cluster position> + <sum of cluster lengths not including last one> */
946 last_cluster
= first_cluster
+ cluster_count
- 1;
947 length
= layout
->clusters
[last_cluster
].position
- layout
->clusters
[first_cluster
].position
+
948 layout
->clustermetrics
[last_cluster
].length
;
950 run
->clustermap
= heap_alloc(sizeof(UINT16
)*length
);
951 if (!run
->clustermap
) {
953 return E_OUTOFMEMORY
;
957 run
->start
= start
= layout
->clusters
[first_cluster
].position
;
958 run
->length
= length
;
959 run
->origin_x
= origin_x
;
960 run
->origin_y
= 0.0; /* set after line is built */
963 if (r
->u
.regular
.run
.glyphCount
) {
964 /* trim from the left */
965 run
->glyphcount
= r
->u
.regular
.run
.glyphCount
- r
->u
.regular
.clustermap
[start
];
966 /* trim from the right */
967 if (start
+ length
< r
->u
.regular
.descr
.stringLength
- 1)
968 run
->glyphcount
-= r
->u
.regular
.run
.glyphCount
- r
->u
.regular
.clustermap
[start
+ length
];
973 /* cluster map needs to be shifted */
974 for (i
= 0; i
< length
; i
++)
975 run
->clustermap
[i
] = r
->u
.regular
.clustermap
[start
+ i
] - r
->u
.regular
.clustermap
[start
];
977 list_add_tail(&layout
->eruns
, &run
->entry
);
979 /* Strikethrough style is guaranteed to be consistent within effective run,
980 it's width equals to run width, thikness and offset are derived from
981 font metrics, rest of the values are from layout or run itself */
983 DWRITE_FONT_METRICS metrics
= { 0 };
984 struct layout_strikethrough
*s
;
986 s
= heap_alloc(sizeof(*s
));
988 return E_OUTOFMEMORY
;
990 if (layout
->gdicompatible
) {
991 HRESULT hr
= IDWriteFontFace_GetGdiCompatibleMetrics(
992 r
->u
.regular
.run
.fontFace
,
993 r
->u
.regular
.run
.fontEmSize
,
994 layout
->pixels_per_dip
,
998 WARN("failed to get font metrics, 0x%08x\n", hr
);
1001 IDWriteFontFace_GetMetrics(r
->u
.regular
.run
.fontFace
, &metrics
);
1003 s
->s
.width
= get_cluster_range_width(layout
, first_cluster
, first_cluster
+ cluster_count
);
1004 s
->s
.thickness
= metrics
.strikethroughThickness
;
1005 s
->s
.offset
= metrics
.strikethroughPosition
;
1006 s
->s
.readingDirection
= layout
->format
.readingdir
;
1007 s
->s
.flowDirection
= layout
->format
.flow
;
1008 s
->s
.localeName
= r
->u
.regular
.descr
.localeName
;
1009 s
->s
.measuringMode
= DWRITE_MEASURING_MODE_NATURAL
; /* FIXME */
1012 list_add_tail(&layout
->strikethrough
, &s
->entry
);
1018 static HRESULT
layout_set_line_metrics(struct dwrite_textlayout
*layout
, DWRITE_LINE_METRICS
*metrics
, UINT32
*line
)
1020 if (!layout
->line_alloc
) {
1021 layout
->line_alloc
= 5;
1022 layout
->lines
= heap_alloc(layout
->line_alloc
*sizeof(*layout
->lines
));
1024 return E_OUTOFMEMORY
;
1027 if (layout
->line_count
== layout
->line_alloc
) {
1028 DWRITE_LINE_METRICS
*l
= heap_realloc(layout
->lines
, layout
->line_alloc
*2*sizeof(*layout
->lines
));
1030 return E_OUTOFMEMORY
;
1032 layout
->line_alloc
*= 2;
1035 layout
->lines
[*line
] = *metrics
;
1040 static inline BOOL
layout_get_strikethrough_from_pos(struct dwrite_textlayout
*layout
, UINT32 pos
)
1042 struct layout_range_header
*h
= get_layout_range_header_by_pos(&layout
->strike_ranges
, pos
);
1043 return ((struct layout_range_bool
*)h
)->value
;
1046 static inline struct layout_effective_run
*layout_get_next_erun(struct dwrite_textlayout
*layout
,
1047 const struct layout_effective_run
*cur
)
1052 e
= list_head(&layout
->eruns
);
1054 e
= list_next(&layout
->eruns
, &cur
->entry
);
1057 return LIST_ENTRY(e
, struct layout_effective_run
, entry
);
1060 static inline struct layout_effective_inline
*layout_get_next_inline_run(struct dwrite_textlayout
*layout
,
1061 const struct layout_effective_inline
*cur
)
1066 e
= list_head(&layout
->inlineobjects
);
1068 e
= list_next(&layout
->inlineobjects
, &cur
->entry
);
1071 return LIST_ENTRY(e
, struct layout_effective_inline
, entry
);
1074 static HRESULT
layout_compute_effective_runs(struct dwrite_textlayout
*layout
)
1076 struct layout_effective_inline
*inrun
;
1077 struct layout_effective_run
*erun
;
1078 const struct layout_run
*run
;
1079 DWRITE_LINE_METRICS metrics
;
1080 FLOAT width
, origin_x
, origin_y
;
1081 UINT32 i
, start
, line
, textpos
;
1085 if (!(layout
->recompute
& RECOMPUTE_EFFECTIVE_RUNS
))
1088 hr
= layout_compute(layout
);
1092 layout
->line_count
= 0;
1095 run
= layout
->clusters
[0].run
;
1096 memset(&metrics
, 0, sizeof(metrics
));
1097 s
[0] = s
[1] = layout_get_strikethrough_from_pos(layout
, 0);
1099 for (i
= 0, start
= 0, textpos
= 0, width
= 0.0; i
< layout
->cluster_count
; i
++) {
1102 s
[1] = layout_get_strikethrough_from_pos(layout
, textpos
);
1104 /* switched to next nominal run, at this point all previous pending clusters are already
1105 checked for layout line overflow, so new effective run will fit in current line */
1106 if (run
!= layout
->clusters
[i
].run
|| s
[0] != s
[1]) {
1107 hr
= layout_add_effective_run(layout
, run
, start
, i
- start
, line
, origin_x
, s
[0]);
1110 origin_x
+= get_cluster_range_width(layout
, start
, i
);
1111 run
= layout
->clusters
[i
].run
;
1115 overflow
= layout
->clustermetrics
[i
].canWrapLineAfter
&&
1116 (width
+ layout
->clustermetrics
[i
].width
> layout
->maxwidth
);
1117 /* check if we got new */
1119 layout
->clustermetrics
[i
].isNewline
|| /* always wrap on new line */
1120 i
== layout
->cluster_count
- 1) /* end of the text */ {
1122 UINT32 strlength
, last_cluster
= i
, index
;
1126 metrics
.length
+= layout
->clustermetrics
[i
].length
;
1130 last_cluster
= i
? i
- 1 : i
;
1133 hr
= layout_add_effective_run(layout
, run
, start
, i
- start
+ 1, line
, origin_x
, s
[0]);
1136 /* we don't need to update origin for next run as we're going to wrap */
1139 /* take a look at clusters we got for this line in reverse order to set
1140 trailing properties for current line */
1141 strlength
= metrics
.length
;
1142 index
= last_cluster
;
1144 DWRITE_CLUSTER_METRICS
*cluster
= &layout
->clustermetrics
[index
];
1146 if (!cluster
->isNewline
&& !cluster
->isWhitespace
)
1149 if (cluster
->isNewline
) {
1150 metrics
.trailingWhitespaceLength
+= cluster
->length
;
1151 metrics
.newlineLength
+= cluster
->length
;
1154 if (cluster
->isWhitespace
)
1155 metrics
.trailingWhitespaceLength
+= cluster
->length
;
1157 strlength
-= cluster
->length
;
1161 /* look for max baseline and descent for this line */
1162 strlength
= metrics
.length
;
1163 index
= last_cluster
;
1164 metrics
.baseline
= 0.0;
1167 DWRITE_CLUSTER_METRICS
*cluster
= &layout
->clustermetrics
[index
];
1168 const struct layout_run
*cur
= layout
->clusters
[index
].run
;
1169 FLOAT cur_descent
= cur
->height
- cur
->baseline
;
1171 if (cur
->baseline
> metrics
.baseline
)
1172 metrics
.baseline
= cur
->baseline
;
1174 if (cur_descent
> descent
)
1175 descent
= cur_descent
;
1177 strlength
-= cluster
->length
;
1180 metrics
.height
= descent
+ metrics
.baseline
;
1182 metrics
.isTrimmed
= width
> layout
->maxwidth
;
1183 hr
= layout_set_line_metrics(layout
, &metrics
, &line
);
1187 width
= layout
->clustermetrics
[i
].width
;
1188 memset(&metrics
, 0, sizeof(metrics
));
1193 metrics
.length
+= layout
->clustermetrics
[i
].length
;
1194 width
+= layout
->clustermetrics
[i
].width
;
1198 textpos
+= layout
->clustermetrics
[i
].length
;
1201 layout
->line_count
= line
;
1203 /* Now all line info is here, update effective runs positions in flow direction */
1204 erun
= layout_get_next_erun(layout
, NULL
);
1205 inrun
= layout_get_next_inline_run(layout
, NULL
);
1208 for (line
= 0; line
< layout
->line_count
; line
++) {
1210 origin_y
+= layout
->lines
[line
].baseline
;
1212 /* For all runs on this line */
1213 while (erun
&& erun
->line
== line
) {
1214 erun
->origin_y
= origin_y
;
1215 erun
= layout_get_next_erun(layout
, erun
);
1220 /* Same for inline runs */
1221 while (inrun
&& inrun
->line
== line
) {
1222 inrun
->origin_y
= origin_y
;
1223 inrun
= layout_get_next_inline_run(layout
, inrun
);
1229 layout
->recompute
&= ~RECOMPUTE_EFFECTIVE_RUNS
;
1233 static BOOL
is_same_layout_attrvalue(struct layout_range_header
const *h
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
1235 struct layout_range_spacing
const *range_spacing
= (struct layout_range_spacing
*)h
;
1236 struct layout_range_effect
const *range_effect
= (struct layout_range_effect
*)h
;
1237 struct layout_range_bool
const *range_bool
= (struct layout_range_bool
*)h
;
1238 struct layout_range
const *range
= (struct layout_range
*)h
;
1241 case LAYOUT_RANGE_ATTR_WEIGHT
:
1242 return range
->weight
== value
->u
.weight
;
1243 case LAYOUT_RANGE_ATTR_STYLE
:
1244 return range
->style
== value
->u
.style
;
1245 case LAYOUT_RANGE_ATTR_STRETCH
:
1246 return range
->stretch
== value
->u
.stretch
;
1247 case LAYOUT_RANGE_ATTR_FONTSIZE
:
1248 return range
->fontsize
== value
->u
.fontsize
;
1249 case LAYOUT_RANGE_ATTR_INLINE
:
1250 return range
->object
== value
->u
.object
;
1251 case LAYOUT_RANGE_ATTR_EFFECT
:
1252 return range_effect
->effect
== value
->u
.effect
;
1253 case LAYOUT_RANGE_ATTR_UNDERLINE
:
1254 return range
->underline
== value
->u
.underline
;
1255 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
1256 return range_bool
->value
== value
->u
.strikethrough
;
1257 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
1258 return range
->pair_kerning
== value
->u
.pair_kerning
;
1259 case LAYOUT_RANGE_ATTR_FONTCOLL
:
1260 return range
->collection
== value
->u
.collection
;
1261 case LAYOUT_RANGE_ATTR_LOCALE
:
1262 return strcmpW(range
->locale
, value
->u
.locale
) == 0;
1263 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1264 return strcmpW(range
->fontfamily
, value
->u
.fontfamily
) == 0;
1265 case LAYOUT_RANGE_ATTR_SPACING
:
1266 return range_spacing
->leading
== value
->u
.spacing
[0] &&
1267 range_spacing
->trailing
== value
->u
.spacing
[1] &&
1268 range_spacing
->min_advance
== value
->u
.spacing
[2];
1276 static inline BOOL
is_same_layout_attributes(struct layout_range_header
const *hleft
, struct layout_range_header
const *hright
)
1278 switch (hleft
->kind
)
1280 case LAYOUT_RANGE_REGULAR
:
1282 struct layout_range
const *left
= (struct layout_range
const*)hleft
;
1283 struct layout_range
const *right
= (struct layout_range
const*)hright
;
1284 return left
->weight
== right
->weight
&&
1285 left
->style
== right
->style
&&
1286 left
->stretch
== right
->stretch
&&
1287 left
->fontsize
== right
->fontsize
&&
1288 left
->object
== right
->object
&&
1289 left
->underline
== right
->underline
&&
1290 left
->pair_kerning
== right
->pair_kerning
&&
1291 left
->collection
== right
->collection
&&
1292 !strcmpW(left
->locale
, right
->locale
) &&
1293 !strcmpW(left
->fontfamily
, right
->fontfamily
);
1295 case LAYOUT_RANGE_STRIKETHROUGH
:
1297 struct layout_range_bool
const *left
= (struct layout_range_bool
const*)hleft
;
1298 struct layout_range_bool
const *right
= (struct layout_range_bool
const*)hright
;
1299 return left
->value
== right
->value
;
1301 case LAYOUT_RANGE_EFFECT
:
1303 struct layout_range_effect
const *left
= (struct layout_range_effect
const*)hleft
;
1304 struct layout_range_effect
const *right
= (struct layout_range_effect
const*)hright
;
1305 return left
->effect
== right
->effect
;
1307 case LAYOUT_RANGE_SPACING
:
1309 struct layout_range_spacing
const *left
= (struct layout_range_spacing
const*)hleft
;
1310 struct layout_range_spacing
const *right
= (struct layout_range_spacing
const*)hright
;
1311 return left
->leading
== right
->leading
&&
1312 left
->trailing
== right
->trailing
&&
1313 left
->min_advance
== right
->min_advance
;
1316 FIXME("unknown range kind %d\n", hleft
->kind
);
1321 static inline BOOL
is_same_text_range(const DWRITE_TEXT_RANGE
*left
, const DWRITE_TEXT_RANGE
*right
)
1323 return left
->startPosition
== right
->startPosition
&& left
->length
== right
->length
;
1326 /* Allocates range and inits it with default values from text format. */
1327 static struct layout_range_header
*alloc_layout_range(struct dwrite_textlayout
*layout
, const DWRITE_TEXT_RANGE
*r
,
1328 enum layout_range_kind kind
)
1330 struct layout_range_header
*h
;
1334 case LAYOUT_RANGE_REGULAR
:
1336 struct layout_range
*range
;
1338 range
= heap_alloc(sizeof(*range
));
1339 if (!range
) return NULL
;
1341 range
->weight
= layout
->format
.weight
;
1342 range
->style
= layout
->format
.style
;
1343 range
->stretch
= layout
->format
.stretch
;
1344 range
->fontsize
= layout
->format
.fontsize
;
1345 range
->object
= NULL
;
1346 range
->underline
= FALSE
;
1347 range
->pair_kerning
= FALSE
;
1349 range
->fontfamily
= heap_strdupW(layout
->format
.family_name
);
1350 if (!range
->fontfamily
) {
1355 range
->collection
= layout
->format
.collection
;
1356 if (range
->collection
)
1357 IDWriteFontCollection_AddRef(range
->collection
);
1358 strcpyW(range
->locale
, layout
->format
.locale
);
1363 case LAYOUT_RANGE_STRIKETHROUGH
:
1365 struct layout_range_bool
*range
;
1367 range
= heap_alloc(sizeof(*range
));
1368 if (!range
) return NULL
;
1370 range
->value
= FALSE
;
1374 case LAYOUT_RANGE_EFFECT
:
1376 struct layout_range_effect
*range
;
1378 range
= heap_alloc(sizeof(*range
));
1379 if (!range
) return NULL
;
1381 range
->effect
= NULL
;
1385 case LAYOUT_RANGE_SPACING
:
1387 struct layout_range_spacing
*range
;
1389 range
= heap_alloc(sizeof(*range
));
1390 if (!range
) return NULL
;
1392 range
->leading
= 0.0;
1393 range
->trailing
= 0.0;
1394 range
->min_advance
= 0.0;
1399 FIXME("unknown range kind %d\n", kind
);
1408 static struct layout_range_header
*alloc_layout_range_from(struct layout_range_header
*h
, const DWRITE_TEXT_RANGE
*r
)
1410 struct layout_range_header
*ret
;
1414 case LAYOUT_RANGE_REGULAR
:
1416 struct layout_range
*from
= (struct layout_range
*)h
;
1418 struct layout_range
*range
= heap_alloc(sizeof(*range
));
1419 if (!range
) return NULL
;
1422 range
->fontfamily
= heap_strdupW(from
->fontfamily
);
1423 if (!range
->fontfamily
) {
1428 /* update refcounts */
1430 IDWriteInlineObject_AddRef(range
->object
);
1431 if (range
->collection
)
1432 IDWriteFontCollection_AddRef(range
->collection
);
1436 case LAYOUT_RANGE_STRIKETHROUGH
:
1438 struct layout_range_bool
*strike
= heap_alloc(sizeof(*strike
));
1439 if (!strike
) return NULL
;
1441 *strike
= *(struct layout_range_bool
*)h
;
1445 case LAYOUT_RANGE_EFFECT
:
1447 struct layout_range_effect
*effect
= heap_alloc(sizeof(*effect
));
1448 if (!effect
) return NULL
;
1450 *effect
= *(struct layout_range_effect
*)h
;
1452 IUnknown_AddRef(effect
->effect
);
1456 case LAYOUT_RANGE_SPACING
:
1458 struct layout_range_spacing
*spacing
= heap_alloc(sizeof(*spacing
));
1459 if (!spacing
) return NULL
;
1461 *spacing
= *(struct layout_range_spacing
*)h
;
1466 FIXME("unknown range kind %d\n", h
->kind
);
1474 static void free_layout_range(struct layout_range_header
*h
)
1481 case LAYOUT_RANGE_REGULAR
:
1483 struct layout_range
*range
= (struct layout_range
*)h
;
1486 IDWriteInlineObject_Release(range
->object
);
1487 if (range
->collection
)
1488 IDWriteFontCollection_Release(range
->collection
);
1489 heap_free(range
->fontfamily
);
1492 case LAYOUT_RANGE_EFFECT
:
1494 struct layout_range_effect
*effect
= (struct layout_range_effect
*)h
;
1496 IUnknown_Release(effect
->effect
);
1506 static void free_layout_ranges_list(struct dwrite_textlayout
*layout
)
1508 struct layout_range_header
*cur
, *cur2
;
1510 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->ranges
, struct layout_range_header
, entry
) {
1511 list_remove(&cur
->entry
);
1512 free_layout_range(cur
);
1515 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->strike_ranges
, struct layout_range_header
, entry
) {
1516 list_remove(&cur
->entry
);
1517 free_layout_range(cur
);
1520 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->effects
, struct layout_range_header
, entry
) {
1521 list_remove(&cur
->entry
);
1522 free_layout_range(cur
);
1525 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, &layout
->spacing
, struct layout_range_header
, entry
) {
1526 list_remove(&cur
->entry
);
1527 free_layout_range(cur
);
1531 static struct layout_range_header
*find_outer_range(struct list
*ranges
, const DWRITE_TEXT_RANGE
*range
)
1533 struct layout_range_header
*cur
;
1535 LIST_FOR_EACH_ENTRY(cur
, ranges
, struct layout_range_header
, entry
) {
1537 if (cur
->range
.startPosition
> range
->startPosition
)
1540 if ((cur
->range
.startPosition
+ cur
->range
.length
< range
->startPosition
+ range
->length
) &&
1541 (range
->startPosition
< cur
->range
.startPosition
+ cur
->range
.length
))
1543 if (cur
->range
.startPosition
+ cur
->range
.length
>= range
->startPosition
+ range
->length
)
1550 static struct layout_range
*get_layout_range_by_pos(struct dwrite_textlayout
*layout
, UINT32 pos
)
1552 struct layout_range
*cur
;
1554 LIST_FOR_EACH_ENTRY(cur
, &layout
->ranges
, struct layout_range
, h
.entry
) {
1555 DWRITE_TEXT_RANGE
*r
= &cur
->h
.range
;
1556 if (r
->startPosition
<= pos
&& pos
< r
->startPosition
+ r
->length
)
1563 static inline BOOL
set_layout_range_iface_attr(IUnknown
**dest
, IUnknown
*value
)
1565 if (*dest
== value
) return FALSE
;
1568 IUnknown_Release(*dest
);
1571 IUnknown_AddRef(*dest
);
1576 static BOOL
set_layout_range_attrval(struct layout_range_header
*h
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
1578 struct layout_range_spacing
*dest_spacing
= (struct layout_range_spacing
*)h
;
1579 struct layout_range_effect
*dest_effect
= (struct layout_range_effect
*)h
;
1580 struct layout_range_bool
*dest_bool
= (struct layout_range_bool
*)h
;
1581 struct layout_range
*dest
= (struct layout_range
*)h
;
1583 BOOL changed
= FALSE
;
1586 case LAYOUT_RANGE_ATTR_WEIGHT
:
1587 changed
= dest
->weight
!= value
->u
.weight
;
1588 dest
->weight
= value
->u
.weight
;
1590 case LAYOUT_RANGE_ATTR_STYLE
:
1591 changed
= dest
->style
!= value
->u
.style
;
1592 dest
->style
= value
->u
.style
;
1594 case LAYOUT_RANGE_ATTR_STRETCH
:
1595 changed
= dest
->stretch
!= value
->u
.stretch
;
1596 dest
->stretch
= value
->u
.stretch
;
1598 case LAYOUT_RANGE_ATTR_FONTSIZE
:
1599 changed
= dest
->fontsize
!= value
->u
.fontsize
;
1600 dest
->fontsize
= value
->u
.fontsize
;
1602 case LAYOUT_RANGE_ATTR_INLINE
:
1603 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->object
, (IUnknown
*)value
->u
.object
);
1605 case LAYOUT_RANGE_ATTR_EFFECT
:
1606 changed
= set_layout_range_iface_attr((IUnknown
**)&dest_effect
->effect
, (IUnknown
*)value
->u
.effect
);
1608 case LAYOUT_RANGE_ATTR_UNDERLINE
:
1609 changed
= dest
->underline
!= value
->u
.underline
;
1610 dest
->underline
= value
->u
.underline
;
1612 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
1613 changed
= dest_bool
->value
!= value
->u
.strikethrough
;
1614 dest_bool
->value
= value
->u
.strikethrough
;
1616 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
1617 changed
= dest
->pair_kerning
!= value
->u
.pair_kerning
;
1618 dest
->pair_kerning
= value
->u
.pair_kerning
;
1620 case LAYOUT_RANGE_ATTR_FONTCOLL
:
1621 changed
= set_layout_range_iface_attr((IUnknown
**)&dest
->collection
, (IUnknown
*)value
->u
.collection
);
1623 case LAYOUT_RANGE_ATTR_LOCALE
:
1624 changed
= strcmpW(dest
->locale
, value
->u
.locale
) != 0;
1626 strcpyW(dest
->locale
, value
->u
.locale
);
1628 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1629 changed
= strcmpW(dest
->fontfamily
, value
->u
.fontfamily
) != 0;
1631 heap_free(dest
->fontfamily
);
1632 dest
->fontfamily
= heap_strdupW(value
->u
.fontfamily
);
1635 case LAYOUT_RANGE_ATTR_SPACING
:
1636 changed
= dest_spacing
->leading
!= value
->u
.spacing
[0] ||
1637 dest_spacing
->trailing
!= value
->u
.spacing
[1] ||
1638 dest_spacing
->min_advance
!= value
->u
.spacing
[2];
1639 dest_spacing
->leading
= value
->u
.spacing
[0];
1640 dest_spacing
->trailing
= value
->u
.spacing
[1];
1641 dest_spacing
->min_advance
= value
->u
.spacing
[2];
1650 static inline BOOL
is_in_layout_range(const DWRITE_TEXT_RANGE
*outer
, const DWRITE_TEXT_RANGE
*inner
)
1652 return (inner
->startPosition
>= outer
->startPosition
) &&
1653 (inner
->startPosition
+ inner
->length
<= outer
->startPosition
+ outer
->length
);
1656 static inline HRESULT
return_range(const struct layout_range_header
*h
, DWRITE_TEXT_RANGE
*r
)
1658 if (r
) *r
= h
->range
;
1662 /* Set attribute value for given range, does all needed splitting/merging of existing ranges. */
1663 static HRESULT
set_layout_range_attr(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind attr
, struct layout_range_attr_value
*value
)
1665 struct layout_range_header
*cur
, *right
, *left
, *outer
;
1666 BOOL changed
= FALSE
;
1667 struct list
*ranges
;
1668 DWRITE_TEXT_RANGE r
;
1670 /* ignore zero length ranges */
1671 if (value
->range
.length
== 0)
1674 /* select from ranges lists */
1677 case LAYOUT_RANGE_ATTR_WEIGHT
:
1678 case LAYOUT_RANGE_ATTR_STYLE
:
1679 case LAYOUT_RANGE_ATTR_STRETCH
:
1680 case LAYOUT_RANGE_ATTR_FONTSIZE
:
1681 case LAYOUT_RANGE_ATTR_INLINE
:
1682 case LAYOUT_RANGE_ATTR_UNDERLINE
:
1683 case LAYOUT_RANGE_ATTR_PAIR_KERNING
:
1684 case LAYOUT_RANGE_ATTR_FONTCOLL
:
1685 case LAYOUT_RANGE_ATTR_LOCALE
:
1686 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1687 ranges
= &layout
->ranges
;
1689 case LAYOUT_RANGE_ATTR_STRIKETHROUGH
:
1690 ranges
= &layout
->strike_ranges
;
1692 case LAYOUT_RANGE_ATTR_EFFECT
:
1693 ranges
= &layout
->effects
;
1695 case LAYOUT_RANGE_ATTR_SPACING
:
1696 ranges
= &layout
->spacing
;
1699 FIXME("unknown attr kind %d\n", attr
);
1703 /* If new range is completely within existing range, split existing range in two */
1704 if ((outer
= find_outer_range(ranges
, &value
->range
))) {
1706 /* no need to add same range */
1707 if (is_same_layout_attrvalue(outer
, attr
, value
))
1710 /* for matching range bounds just replace data */
1711 if (is_same_text_range(&outer
->range
, &value
->range
)) {
1712 changed
= set_layout_range_attrval(outer
, attr
, value
);
1716 /* add new range to the left */
1717 if (value
->range
.startPosition
== outer
->range
.startPosition
) {
1718 left
= alloc_layout_range_from(outer
, &value
->range
);
1719 if (!left
) return E_OUTOFMEMORY
;
1721 changed
= set_layout_range_attrval(left
, attr
, value
);
1722 list_add_before(&outer
->entry
, &left
->entry
);
1723 outer
->range
.startPosition
+= value
->range
.length
;
1724 outer
->range
.length
-= value
->range
.length
;
1728 /* add new range to the right */
1729 if (value
->range
.startPosition
+ value
->range
.length
== outer
->range
.startPosition
+ outer
->range
.length
) {
1730 right
= alloc_layout_range_from(outer
, &value
->range
);
1731 if (!right
) return E_OUTOFMEMORY
;
1733 changed
= set_layout_range_attrval(right
, attr
, value
);
1734 list_add_after(&outer
->entry
, &right
->entry
);
1735 outer
->range
.length
-= value
->range
.length
;
1739 r
.startPosition
= value
->range
.startPosition
+ value
->range
.length
;
1740 r
.length
= outer
->range
.length
+ outer
->range
.startPosition
- r
.startPosition
;
1743 right
= alloc_layout_range_from(outer
, &r
);
1744 /* new range in the middle */
1745 cur
= alloc_layout_range_from(outer
, &value
->range
);
1746 if (!right
|| !cur
) {
1747 free_layout_range(right
);
1748 free_layout_range(cur
);
1749 return E_OUTOFMEMORY
;
1752 /* reuse container range as a left part */
1753 outer
->range
.length
= value
->range
.startPosition
- outer
->range
.startPosition
;
1756 set_layout_range_attrval(cur
, attr
, value
);
1758 list_add_after(&outer
->entry
, &cur
->entry
);
1759 list_add_after(&cur
->entry
, &right
->entry
);
1764 /* Now it's only possible that given range contains some existing ranges, fully or partially.
1765 Update all of them. */
1766 left
= get_layout_range_header_by_pos(ranges
, value
->range
.startPosition
);
1767 if (left
->range
.startPosition
== value
->range
.startPosition
)
1768 changed
= set_layout_range_attrval(left
, attr
, value
);
1769 else /* need to split */ {
1770 r
.startPosition
= value
->range
.startPosition
;
1771 r
.length
= left
->range
.length
- value
->range
.startPosition
+ left
->range
.startPosition
;
1772 left
->range
.length
-= r
.length
;
1773 cur
= alloc_layout_range_from(left
, &r
);
1774 changed
= set_layout_range_attrval(cur
, attr
, value
);
1775 list_add_after(&left
->entry
, &cur
->entry
);
1777 cur
= LIST_ENTRY(list_next(ranges
, &left
->entry
), struct layout_range_header
, entry
);
1779 /* for all existing ranges covered by new one update value */
1780 while (cur
&& is_in_layout_range(&value
->range
, &cur
->range
)) {
1781 changed
= set_layout_range_attrval(cur
, attr
, value
);
1782 cur
= LIST_ENTRY(list_next(ranges
, &cur
->entry
), struct layout_range_header
, entry
);
1785 /* it's possible rightmost range intersects */
1786 if (cur
&& (cur
->range
.startPosition
< value
->range
.startPosition
+ value
->range
.length
)) {
1787 r
.startPosition
= cur
->range
.startPosition
;
1788 r
.length
= value
->range
.startPosition
+ value
->range
.length
- cur
->range
.startPosition
;
1789 left
= alloc_layout_range_from(cur
, &r
);
1790 changed
= set_layout_range_attrval(left
, attr
, value
);
1791 cur
->range
.startPosition
+= left
->range
.length
;
1792 cur
->range
.length
-= left
->range
.length
;
1793 list_add_before(&cur
->entry
, &left
->entry
);
1798 struct list
*next
, *i
;
1800 layout
->recompute
= RECOMPUTE_EVERYTHING
;
1801 i
= list_head(ranges
);
1802 while ((next
= list_next(ranges
, i
))) {
1803 struct layout_range_header
*next_range
= LIST_ENTRY(next
, struct layout_range_header
, entry
);
1805 cur
= LIST_ENTRY(i
, struct layout_range_header
, entry
);
1806 if (is_same_layout_attributes(cur
, next_range
)) {
1807 /* remove similar range */
1808 cur
->range
.length
+= next_range
->range
.length
;
1810 free_layout_range(next_range
);
1813 i
= list_next(ranges
, i
);
1820 static inline const WCHAR
*get_string_attribute_ptr(struct layout_range
*range
, enum layout_range_attr_kind kind
)
1825 case LAYOUT_RANGE_ATTR_LOCALE
:
1826 str
= range
->locale
;
1828 case LAYOUT_RANGE_ATTR_FONTFAMILY
:
1829 str
= range
->fontfamily
;
1838 static HRESULT
get_string_attribute_length(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind kind
, UINT32 position
,
1839 UINT32
*length
, DWRITE_TEXT_RANGE
*r
)
1841 struct layout_range
*range
;
1844 range
= get_layout_range_by_pos(layout
, position
);
1850 str
= get_string_attribute_ptr(range
, kind
);
1851 *length
= strlenW(str
);
1852 return return_range(&range
->h
, r
);
1855 static HRESULT
get_string_attribute_value(struct dwrite_textlayout
*layout
, enum layout_range_attr_kind kind
, UINT32 position
,
1856 WCHAR
*ret
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
1858 struct layout_range
*range
;
1862 return E_INVALIDARG
;
1865 range
= get_layout_range_by_pos(layout
, position
);
1867 return E_INVALIDARG
;
1869 str
= get_string_attribute_ptr(range
, kind
);
1870 if (length
< strlenW(str
) + 1)
1871 return E_NOT_SUFFICIENT_BUFFER
;
1874 return return_range(&range
->h
, r
);
1877 static HRESULT WINAPI
dwritetextlayout_QueryInterface(IDWriteTextLayout2
*iface
, REFIID riid
, void **obj
)
1879 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1881 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1885 if (IsEqualIID(riid
, &IID_IDWriteTextLayout2
) ||
1886 IsEqualIID(riid
, &IID_IDWriteTextLayout1
) ||
1887 IsEqualIID(riid
, &IID_IDWriteTextLayout
) ||
1888 IsEqualIID(riid
, &IID_IUnknown
))
1892 else if (IsEqualIID(riid
, &IID_IDWriteTextFormat1
) ||
1893 IsEqualIID(riid
, &IID_IDWriteTextFormat
))
1894 *obj
= &This
->IDWriteTextFormat1_iface
;
1897 IDWriteTextLayout2_AddRef(iface
);
1901 return E_NOINTERFACE
;
1904 static ULONG WINAPI
dwritetextlayout_AddRef(IDWriteTextLayout2
*iface
)
1906 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1907 ULONG ref
= InterlockedIncrement(&This
->ref
);
1908 TRACE("(%p)->(%d)\n", This
, ref
);
1912 static ULONG WINAPI
dwritetextlayout_Release(IDWriteTextLayout2
*iface
)
1914 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1915 ULONG ref
= InterlockedDecrement(&This
->ref
);
1917 TRACE("(%p)->(%d)\n", This
, ref
);
1920 free_layout_ranges_list(This
);
1921 free_layout_eruns(This
);
1922 free_layout_runs(This
);
1923 release_format_data(&This
->format
);
1924 heap_free(This
->nominal_breakpoints
);
1925 heap_free(This
->actual_breakpoints
);
1926 heap_free(This
->clustermetrics
);
1927 heap_free(This
->clusters
);
1928 heap_free(This
->lines
);
1929 heap_free(This
->str
);
1936 static HRESULT WINAPI
dwritetextlayout_SetTextAlignment(IDWriteTextLayout2
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
1938 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1939 TRACE("(%p)->(%d)\n", This
, alignment
);
1940 return IDWriteTextFormat1_SetTextAlignment(&This
->IDWriteTextFormat1_iface
, alignment
);
1943 static HRESULT WINAPI
dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout2
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
1945 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1946 TRACE("(%p)->(%d)\n", This
, alignment
);
1947 return IDWriteTextFormat1_SetParagraphAlignment(&This
->IDWriteTextFormat1_iface
, alignment
);
1950 static HRESULT WINAPI
dwritetextlayout_SetWordWrapping(IDWriteTextLayout2
*iface
, DWRITE_WORD_WRAPPING wrapping
)
1952 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1953 TRACE("(%p)->(%d)\n", This
, wrapping
);
1954 return IDWriteTextFormat1_SetWordWrapping(&This
->IDWriteTextFormat1_iface
, wrapping
);
1957 static HRESULT WINAPI
dwritetextlayout_SetReadingDirection(IDWriteTextLayout2
*iface
, DWRITE_READING_DIRECTION direction
)
1959 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1960 TRACE("(%p)->(%d)\n", This
, direction
);
1961 return IDWriteTextFormat1_SetReadingDirection(&This
->IDWriteTextFormat1_iface
, direction
);
1964 static HRESULT WINAPI
dwritetextlayout_SetFlowDirection(IDWriteTextLayout2
*iface
, DWRITE_FLOW_DIRECTION direction
)
1966 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1967 TRACE("(%p)->(%d)\n", This
, direction
);
1968 return IDWriteTextFormat1_SetFlowDirection(&This
->IDWriteTextFormat1_iface
, direction
);
1971 static HRESULT WINAPI
dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout2
*iface
, FLOAT tabstop
)
1973 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1974 TRACE("(%p)->(%.2f)\n", This
, tabstop
);
1975 return IDWriteTextFormat1_SetIncrementalTabStop(&This
->IDWriteTextFormat1_iface
, tabstop
);
1978 static HRESULT WINAPI
dwritetextlayout_SetTrimming(IDWriteTextLayout2
*iface
, DWRITE_TRIMMING
const *trimming
,
1979 IDWriteInlineObject
*trimming_sign
)
1981 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1982 TRACE("(%p)->(%p %p)\n", This
, trimming
, trimming_sign
);
1983 return IDWriteTextFormat1_SetTrimming(&This
->IDWriteTextFormat1_iface
, trimming
, trimming_sign
);
1986 static HRESULT WINAPI
dwritetextlayout_SetLineSpacing(IDWriteTextLayout2
*iface
, DWRITE_LINE_SPACING_METHOD spacing
,
1987 FLOAT line_spacing
, FLOAT baseline
)
1989 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1990 TRACE("(%p)->(%d %.2f %.2f)\n", This
, spacing
, line_spacing
, baseline
);
1991 return IDWriteTextFormat1_SetLineSpacing(&This
->IDWriteTextFormat1_iface
, spacing
, line_spacing
, baseline
);
1994 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextlayout_GetTextAlignment(IDWriteTextLayout2
*iface
)
1996 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
1997 TRACE("(%p)\n", This
);
1998 return IDWriteTextFormat1_GetTextAlignment(&This
->IDWriteTextFormat1_iface
);
2001 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout2
*iface
)
2003 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2004 TRACE("(%p)\n", This
);
2005 return IDWriteTextFormat1_GetParagraphAlignment(&This
->IDWriteTextFormat1_iface
);
2008 static DWRITE_WORD_WRAPPING WINAPI
dwritetextlayout_GetWordWrapping(IDWriteTextLayout2
*iface
)
2010 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2011 TRACE("(%p)\n", This
);
2012 return IDWriteTextFormat1_GetWordWrapping(&This
->IDWriteTextFormat1_iface
);
2015 static DWRITE_READING_DIRECTION WINAPI
dwritetextlayout_GetReadingDirection(IDWriteTextLayout2
*iface
)
2017 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2018 TRACE("(%p)\n", This
);
2019 return IDWriteTextFormat1_GetReadingDirection(&This
->IDWriteTextFormat1_iface
);
2022 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextlayout_GetFlowDirection(IDWriteTextLayout2
*iface
)
2024 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2025 TRACE("(%p)\n", This
);
2026 return IDWriteTextFormat1_GetFlowDirection(&This
->IDWriteTextFormat1_iface
);
2029 static FLOAT WINAPI
dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout2
*iface
)
2031 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2032 TRACE("(%p)\n", This
);
2033 return IDWriteTextFormat1_GetIncrementalTabStop(&This
->IDWriteTextFormat1_iface
);
2036 static HRESULT WINAPI
dwritetextlayout_GetTrimming(IDWriteTextLayout2
*iface
, DWRITE_TRIMMING
*options
,
2037 IDWriteInlineObject
**trimming_sign
)
2039 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2040 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
2041 return IDWriteTextFormat1_GetTrimming(&This
->IDWriteTextFormat1_iface
, options
, trimming_sign
);
2044 static HRESULT WINAPI
dwritetextlayout_GetLineSpacing(IDWriteTextLayout2
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
2045 FLOAT
*spacing
, FLOAT
*baseline
)
2047 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2048 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
2049 return IDWriteTextFormat1_GetLineSpacing(&This
->IDWriteTextFormat1_iface
, method
, spacing
, baseline
);
2052 static HRESULT WINAPI
dwritetextlayout_GetFontCollection(IDWriteTextLayout2
*iface
, IDWriteFontCollection
**collection
)
2054 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2055 TRACE("(%p)->(%p)\n", This
, collection
);
2056 return IDWriteTextFormat1_GetFontCollection(&This
->IDWriteTextFormat1_iface
, collection
);
2059 static UINT32 WINAPI
dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout2
*iface
)
2061 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2062 TRACE("(%p)\n", This
);
2063 return IDWriteTextFormat1_GetFontFamilyNameLength(&This
->IDWriteTextFormat1_iface
);
2066 static HRESULT WINAPI
dwritetextlayout_GetFontFamilyName(IDWriteTextLayout2
*iface
, WCHAR
*name
, UINT32 size
)
2068 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2069 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
2070 return IDWriteTextFormat1_GetFontFamilyName(&This
->IDWriteTextFormat1_iface
, name
, size
);
2073 static DWRITE_FONT_WEIGHT WINAPI
dwritetextlayout_GetFontWeight(IDWriteTextLayout2
*iface
)
2075 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2076 TRACE("(%p)\n", This
);
2077 return IDWriteTextFormat1_GetFontWeight(&This
->IDWriteTextFormat1_iface
);
2080 static DWRITE_FONT_STYLE WINAPI
dwritetextlayout_GetFontStyle(IDWriteTextLayout2
*iface
)
2082 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2083 TRACE("(%p)\n", This
);
2084 return IDWriteTextFormat1_GetFontStyle(&This
->IDWriteTextFormat1_iface
);
2087 static DWRITE_FONT_STRETCH WINAPI
dwritetextlayout_GetFontStretch(IDWriteTextLayout2
*iface
)
2089 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2090 TRACE("(%p)\n", This
);
2091 return IDWriteTextFormat1_GetFontStretch(&This
->IDWriteTextFormat1_iface
);
2094 static FLOAT WINAPI
dwritetextlayout_GetFontSize(IDWriteTextLayout2
*iface
)
2096 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2097 TRACE("(%p)\n", This
);
2098 return IDWriteTextFormat1_GetFontSize(&This
->IDWriteTextFormat1_iface
);
2101 static UINT32 WINAPI
dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout2
*iface
)
2103 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2104 TRACE("(%p)\n", This
);
2105 return IDWriteTextFormat1_GetLocaleNameLength(&This
->IDWriteTextFormat1_iface
);
2108 static HRESULT WINAPI
dwritetextlayout_GetLocaleName(IDWriteTextLayout2
*iface
, WCHAR
*name
, UINT32 size
)
2110 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2111 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
2112 return IDWriteTextFormat1_GetLocaleName(&This
->IDWriteTextFormat1_iface
, name
, size
);
2115 static HRESULT WINAPI
dwritetextlayout_SetMaxWidth(IDWriteTextLayout2
*iface
, FLOAT maxWidth
)
2117 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2118 TRACE("(%p)->(%.1f)\n", This
, maxWidth
);
2121 return E_INVALIDARG
;
2123 This
->maxwidth
= maxWidth
;
2127 static HRESULT WINAPI
dwritetextlayout_SetMaxHeight(IDWriteTextLayout2
*iface
, FLOAT maxHeight
)
2129 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2130 TRACE("(%p)->(%.1f)\n", This
, maxHeight
);
2132 if (maxHeight
< 0.0)
2133 return E_INVALIDARG
;
2135 This
->maxheight
= maxHeight
;
2139 static HRESULT WINAPI
dwritetextlayout_SetFontCollection(IDWriteTextLayout2
*iface
, IDWriteFontCollection
* collection
, DWRITE_TEXT_RANGE range
)
2141 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2142 struct layout_range_attr_value value
;
2144 TRACE("(%p)->(%p %s)\n", This
, collection
, debugstr_range(&range
));
2146 value
.range
= range
;
2147 value
.u
.collection
= collection
;
2148 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTCOLL
, &value
);
2151 static HRESULT WINAPI
dwritetextlayout_SetFontFamilyName(IDWriteTextLayout2
*iface
, WCHAR
const *name
, DWRITE_TEXT_RANGE range
)
2153 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2154 struct layout_range_attr_value value
;
2156 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(name
), debugstr_range(&range
));
2159 return E_INVALIDARG
;
2161 value
.range
= range
;
2162 value
.u
.fontfamily
= name
;
2163 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, &value
);
2166 static HRESULT WINAPI
dwritetextlayout_SetFontWeight(IDWriteTextLayout2
*iface
, DWRITE_FONT_WEIGHT weight
, DWRITE_TEXT_RANGE range
)
2168 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2169 struct layout_range_attr_value value
;
2171 TRACE("(%p)->(%d %s)\n", This
, weight
, debugstr_range(&range
));
2173 value
.range
= range
;
2174 value
.u
.weight
= weight
;
2175 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_WEIGHT
, &value
);
2178 static HRESULT WINAPI
dwritetextlayout_SetFontStyle(IDWriteTextLayout2
*iface
, DWRITE_FONT_STYLE style
, 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
, style
, debugstr_range(&range
));
2185 if ((UINT32
)style
> DWRITE_FONT_STYLE_ITALIC
)
2186 return E_INVALIDARG
;
2188 value
.range
= range
;
2189 value
.u
.style
= style
;
2190 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STYLE
, &value
);
2193 static HRESULT WINAPI
dwritetextlayout_SetFontStretch(IDWriteTextLayout2
*iface
, DWRITE_FONT_STRETCH stretch
, DWRITE_TEXT_RANGE range
)
2195 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2196 struct layout_range_attr_value value
;
2198 TRACE("(%p)->(%d %s)\n", This
, stretch
, debugstr_range(&range
));
2200 if (stretch
== DWRITE_FONT_STRETCH_UNDEFINED
|| (UINT32
)stretch
> DWRITE_FONT_STRETCH_ULTRA_EXPANDED
)
2201 return E_INVALIDARG
;
2203 value
.range
= range
;
2204 value
.u
.stretch
= stretch
;
2205 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STRETCH
, &value
);
2208 static HRESULT WINAPI
dwritetextlayout_SetFontSize(IDWriteTextLayout2
*iface
, FLOAT size
, DWRITE_TEXT_RANGE range
)
2210 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2211 struct layout_range_attr_value value
;
2213 TRACE("(%p)->(%.2f %s)\n", This
, size
, debugstr_range(&range
));
2216 return E_INVALIDARG
;
2218 value
.range
= range
;
2219 value
.u
.fontsize
= size
;
2220 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_FONTSIZE
, &value
);
2223 static HRESULT WINAPI
dwritetextlayout_SetUnderline(IDWriteTextLayout2
*iface
, BOOL underline
, DWRITE_TEXT_RANGE range
)
2225 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2226 struct layout_range_attr_value value
;
2228 TRACE("(%p)->(%d %s)\n", This
, underline
, debugstr_range(&range
));
2230 value
.range
= range
;
2231 value
.u
.underline
= underline
;
2232 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_UNDERLINE
, &value
);
2235 static HRESULT WINAPI
dwritetextlayout_SetStrikethrough(IDWriteTextLayout2
*iface
, BOOL strikethrough
, DWRITE_TEXT_RANGE range
)
2237 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2238 struct layout_range_attr_value value
;
2240 TRACE("(%p)->(%d %s)\n", This
, strikethrough
, debugstr_range(&range
));
2242 value
.range
= range
;
2243 value
.u
.strikethrough
= strikethrough
;
2244 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_STRIKETHROUGH
, &value
);
2247 static HRESULT WINAPI
dwritetextlayout_SetDrawingEffect(IDWriteTextLayout2
*iface
, IUnknown
* effect
, DWRITE_TEXT_RANGE range
)
2249 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2250 struct layout_range_attr_value value
;
2252 TRACE("(%p)->(%p %s)\n", This
, effect
, debugstr_range(&range
));
2254 value
.range
= range
;
2255 value
.u
.effect
= effect
;
2256 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_EFFECT
, &value
);
2259 static HRESULT WINAPI
dwritetextlayout_SetInlineObject(IDWriteTextLayout2
*iface
, IDWriteInlineObject
*object
, DWRITE_TEXT_RANGE range
)
2261 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2262 struct layout_range_attr_value value
;
2264 TRACE("(%p)->(%p %s)\n", This
, object
, debugstr_range(&range
));
2266 value
.range
= range
;
2267 value
.u
.object
= object
;
2268 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_INLINE
, &value
);
2271 static HRESULT WINAPI
dwritetextlayout_SetTypography(IDWriteTextLayout2
*iface
, IDWriteTypography
* typography
, DWRITE_TEXT_RANGE range
)
2273 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2274 FIXME("(%p)->(%p %s): stub\n", This
, typography
, debugstr_range(&range
));
2278 static HRESULT WINAPI
dwritetextlayout_SetLocaleName(IDWriteTextLayout2
*iface
, WCHAR
const* locale
, DWRITE_TEXT_RANGE range
)
2280 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2281 struct layout_range_attr_value value
;
2283 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(locale
), debugstr_range(&range
));
2285 if (!locale
|| strlenW(locale
) > LOCALE_NAME_MAX_LENGTH
-1)
2286 return E_INVALIDARG
;
2288 value
.range
= range
;
2289 value
.u
.locale
= locale
;
2290 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_LOCALE
, &value
);
2293 static FLOAT WINAPI
dwritetextlayout_GetMaxWidth(IDWriteTextLayout2
*iface
)
2295 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2296 TRACE("(%p)\n", This
);
2297 return This
->maxwidth
;
2300 static FLOAT WINAPI
dwritetextlayout_GetMaxHeight(IDWriteTextLayout2
*iface
)
2302 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2303 TRACE("(%p)\n", This
);
2304 return This
->maxheight
;
2307 static HRESULT WINAPI
dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout2
*iface
, UINT32 position
,
2308 IDWriteFontCollection
** collection
, DWRITE_TEXT_RANGE
*r
)
2310 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2311 struct layout_range
*range
;
2313 TRACE("(%p)->(%u %p %p)\n", This
, position
, collection
, r
);
2315 if (position
>= This
->len
)
2318 range
= get_layout_range_by_pos(This
, position
);
2319 *collection
= range
->collection
;
2321 IDWriteFontCollection_AddRef(*collection
);
2323 return return_range(&range
->h
, r
);
2326 static HRESULT WINAPI
dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout2
*iface
,
2327 UINT32 position
, UINT32
*length
, DWRITE_TEXT_RANGE
*r
)
2329 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2330 TRACE("(%p)->(%d %p %p)\n", This
, position
, length
, r
);
2331 return get_string_attribute_length(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, position
, length
, r
);
2334 static HRESULT WINAPI
dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout2
*iface
,
2335 UINT32 position
, WCHAR
*name
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
2337 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2338 TRACE("(%p)->(%u %p %u %p)\n", This
, position
, name
, length
, r
);
2339 return get_string_attribute_value(This
, LAYOUT_RANGE_ATTR_FONTFAMILY
, position
, name
, length
, r
);
2342 static HRESULT WINAPI
dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout2
*iface
,
2343 UINT32 position
, DWRITE_FONT_WEIGHT
*weight
, DWRITE_TEXT_RANGE
*r
)
2345 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2346 struct layout_range
*range
;
2348 TRACE("(%p)->(%u %p %p)\n", This
, position
, weight
, r
);
2350 if (position
>= This
->len
)
2353 range
= get_layout_range_by_pos(This
, position
);
2354 *weight
= range
->weight
;
2356 return return_range(&range
->h
, r
);
2359 static HRESULT WINAPI
dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout2
*iface
,
2360 UINT32 position
, DWRITE_FONT_STYLE
*style
, DWRITE_TEXT_RANGE
*r
)
2362 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2363 struct layout_range
*range
;
2365 TRACE("(%p)->(%u %p %p)\n", This
, position
, style
, r
);
2367 range
= get_layout_range_by_pos(This
, position
);
2368 *style
= range
->style
;
2369 return return_range(&range
->h
, r
);
2372 static HRESULT WINAPI
dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout2
*iface
,
2373 UINT32 position
, DWRITE_FONT_STRETCH
*stretch
, DWRITE_TEXT_RANGE
*r
)
2375 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2376 struct layout_range
*range
;
2378 TRACE("(%p)->(%u %p %p)\n", This
, position
, stretch
, r
);
2380 range
= get_layout_range_by_pos(This
, position
);
2381 *stretch
= range
->stretch
;
2382 return return_range(&range
->h
, r
);
2385 static HRESULT WINAPI
dwritetextlayout_layout_GetFontSize(IDWriteTextLayout2
*iface
,
2386 UINT32 position
, FLOAT
*size
, DWRITE_TEXT_RANGE
*r
)
2388 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2389 struct layout_range
*range
;
2391 TRACE("(%p)->(%u %p %p)\n", This
, position
, size
, r
);
2393 range
= get_layout_range_by_pos(This
, position
);
2394 *size
= range
->fontsize
;
2395 return return_range(&range
->h
, r
);
2398 static HRESULT WINAPI
dwritetextlayout_GetUnderline(IDWriteTextLayout2
*iface
,
2399 UINT32 position
, BOOL
*underline
, DWRITE_TEXT_RANGE
*r
)
2401 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2402 struct layout_range
*range
;
2404 TRACE("(%p)->(%u %p %p)\n", This
, position
, underline
, r
);
2406 if (position
>= This
->len
)
2409 range
= get_layout_range_by_pos(This
, position
);
2410 *underline
= range
->underline
;
2412 return return_range(&range
->h
, r
);
2415 static HRESULT WINAPI
dwritetextlayout_GetStrikethrough(IDWriteTextLayout2
*iface
,
2416 UINT32 position
, BOOL
*strikethrough
, DWRITE_TEXT_RANGE
*r
)
2418 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2419 struct layout_range_bool
*range
;
2421 TRACE("(%p)->(%u %p %p)\n", This
, position
, strikethrough
, r
);
2423 range
= (struct layout_range_bool
*)get_layout_range_header_by_pos(&This
->strike_ranges
, position
);
2424 *strikethrough
= range
->value
;
2426 return return_range(&range
->h
, r
);
2429 static HRESULT WINAPI
dwritetextlayout_GetDrawingEffect(IDWriteTextLayout2
*iface
,
2430 UINT32 position
, IUnknown
**effect
, DWRITE_TEXT_RANGE
*r
)
2432 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2433 struct layout_range_effect
*range
;
2435 TRACE("(%p)->(%u %p %p)\n", This
, position
, effect
, r
);
2437 range
= (struct layout_range_effect
*)get_layout_range_header_by_pos(&This
->effects
, position
);
2438 *effect
= range
->effect
;
2440 IUnknown_AddRef(*effect
);
2442 return return_range(&range
->h
, r
);
2445 static HRESULT WINAPI
dwritetextlayout_GetInlineObject(IDWriteTextLayout2
*iface
,
2446 UINT32 position
, IDWriteInlineObject
**object
, DWRITE_TEXT_RANGE
*r
)
2448 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2449 struct layout_range
*range
;
2451 TRACE("(%p)->(%u %p %p)\n", This
, position
, object
, r
);
2453 if (position
>= This
->len
)
2456 range
= get_layout_range_by_pos(This
, position
);
2457 *object
= range
->object
;
2459 IDWriteInlineObject_AddRef(*object
);
2461 return return_range(&range
->h
, r
);
2464 static HRESULT WINAPI
dwritetextlayout_GetTypography(IDWriteTextLayout2
*iface
,
2465 UINT32 position
, IDWriteTypography
** typography
, DWRITE_TEXT_RANGE
*range
)
2467 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2468 FIXME("(%p)->(%u %p %p): stub\n", This
, position
, typography
, range
);
2472 static HRESULT WINAPI
dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout2
*iface
,
2473 UINT32 position
, UINT32
* length
, DWRITE_TEXT_RANGE
*r
)
2475 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2476 TRACE("(%p)->(%u %p %p)\n", This
, position
, length
, r
);
2477 return get_string_attribute_length(This
, LAYOUT_RANGE_ATTR_LOCALE
, position
, length
, r
);
2480 static HRESULT WINAPI
dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout2
*iface
,
2481 UINT32 position
, WCHAR
* locale
, UINT32 length
, DWRITE_TEXT_RANGE
*r
)
2483 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2484 TRACE("(%p)->(%u %p %u %p)\n", This
, position
, locale
, length
, r
);
2485 return get_string_attribute_value(This
, LAYOUT_RANGE_ATTR_LOCALE
, position
, locale
, length
, r
);
2488 static HRESULT WINAPI
dwritetextlayout_Draw(IDWriteTextLayout2
*iface
,
2489 void *context
, IDWriteTextRenderer
* renderer
, FLOAT origin_x
, FLOAT origin_y
)
2491 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2492 struct layout_effective_inline
*inlineobject
;
2493 struct layout_effective_run
*run
;
2494 struct layout_strikethrough
*s
;
2497 TRACE("(%p)->(%p %p %.2f %.2f)\n", This
, context
, renderer
, origin_x
, origin_y
);
2499 hr
= layout_compute_effective_runs(This
);
2503 /* 1. Regular runs */
2504 LIST_FOR_EACH_ENTRY(run
, &This
->eruns
, struct layout_effective_run
, entry
) {
2505 const struct regular_layout_run
*regular
= &run
->run
->u
.regular
;
2506 UINT32 start_glyph
= regular
->clustermap
[run
->start
];
2507 DWRITE_GLYPH_RUN_DESCRIPTION descr
;
2508 DWRITE_GLYPH_RUN glyph_run
;
2510 /* Everything but cluster map will be reused from nominal run, as we only need
2511 to adjust some pointers. Cluster map however is rebuilt when effective run is added,
2512 it can't be reused because it has to start with 0 index for each reported run. */
2513 glyph_run
= regular
->run
;
2514 glyph_run
.glyphCount
= run
->glyphcount
;
2516 /* fixup glyph data arrays */
2517 glyph_run
.glyphIndices
+= start_glyph
;
2518 glyph_run
.glyphAdvances
+= start_glyph
;
2519 glyph_run
.glyphOffsets
+= start_glyph
;
2522 descr
= regular
->descr
;
2523 descr
.stringLength
= run
->length
;
2524 descr
.string
+= run
->start
;
2525 descr
.clusterMap
= run
->clustermap
;
2526 descr
.textPosition
+= run
->start
;
2528 /* return value is ignored */
2529 IDWriteTextRenderer_DrawGlyphRun(renderer
,
2531 run
->origin_x
+ origin_x
,
2532 run
->origin_y
+ origin_y
,
2533 DWRITE_MEASURING_MODE_NATURAL
,
2539 /* 2. Inline objects */
2540 LIST_FOR_EACH_ENTRY(inlineobject
, &This
->inlineobjects
, struct layout_effective_inline
, entry
) {
2541 IDWriteTextRenderer_DrawInlineObject(renderer
,
2543 inlineobject
->origin_x
,
2544 inlineobject
->origin_y
,
2545 inlineobject
->object
,
2546 inlineobject
->is_sideways
,
2547 inlineobject
->is_rtl
,
2548 inlineobject
->effect
);
2551 /* TODO: 3. Underlines */
2553 /* 4. Strikethrough */
2554 LIST_FOR_EACH_ENTRY(s
, &This
->strikethrough
, struct layout_strikethrough
, entry
) {
2555 IDWriteTextRenderer_DrawStrikethrough(renderer
,
2566 static HRESULT WINAPI
dwritetextlayout_GetLineMetrics(IDWriteTextLayout2
*iface
,
2567 DWRITE_LINE_METRICS
*metrics
, UINT32 max_count
, UINT32
*count
)
2569 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2572 TRACE("(%p)->(%p %u %p)\n", This
, metrics
, max_count
, count
);
2574 hr
= layout_compute_effective_runs(This
);
2579 memcpy(metrics
, This
->lines
, sizeof(DWRITE_LINE_METRICS
)*min(max_count
, This
->line_count
));
2581 *count
= This
->line_count
;
2582 return max_count
>= This
->line_count
? S_OK
: E_NOT_SUFFICIENT_BUFFER
;
2585 static HRESULT WINAPI
dwritetextlayout_GetMetrics(IDWriteTextLayout2
*iface
, DWRITE_TEXT_METRICS
*metrics
)
2587 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2588 DWRITE_TEXT_METRICS1 metrics1
;
2591 TRACE("(%p)->(%p)\n", This
, metrics
);
2593 hr
= IDWriteTextLayout2_GetMetrics(iface
, &metrics1
);
2595 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
2600 static HRESULT WINAPI
dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout2
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
2602 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2603 FIXME("(%p)->(%p): stub\n", This
, overhangs
);
2607 static HRESULT WINAPI
dwritetextlayout_GetClusterMetrics(IDWriteTextLayout2
*iface
,
2608 DWRITE_CLUSTER_METRICS
*metrics
, UINT32 max_count
, UINT32
*count
)
2610 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2613 TRACE("(%p)->(%p %u %p)\n", This
, metrics
, max_count
, count
);
2615 hr
= layout_compute(This
);
2620 memcpy(metrics
, This
->clustermetrics
, sizeof(DWRITE_CLUSTER_METRICS
)*min(max_count
, This
->cluster_count
));
2622 *count
= This
->cluster_count
;
2623 return max_count
>= This
->cluster_count
? S_OK
: E_NOT_SUFFICIENT_BUFFER
;
2626 /* Only to be used with DetermineMinWidth() to find the longest cluster sequence that we don't want to try
2627 too hard to break. */
2628 static inline BOOL
is_terminal_cluster(struct dwrite_textlayout
*layout
, UINT32 index
)
2630 if (layout
->clustermetrics
[index
].isWhitespace
|| layout
->clustermetrics
[index
].isNewline
||
2631 (index
== layout
->cluster_count
- 1))
2633 /* check next one */
2634 return (index
< layout
->cluster_count
- 1) && layout
->clustermetrics
[index
+1].isWhitespace
;
2637 static HRESULT WINAPI
dwritetextlayout_DetermineMinWidth(IDWriteTextLayout2
*iface
, FLOAT
* min_width
)
2639 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2644 TRACE("(%p)->(%p)\n", This
, min_width
);
2647 return E_INVALIDARG
;
2649 if (!(This
->recompute
& RECOMPUTE_MINIMAL_WIDTH
))
2653 hr
= layout_compute(This
);
2657 for (i
= 0; i
< This
->cluster_count
;) {
2658 if (is_terminal_cluster(This
, i
)) {
2659 width
= This
->clustermetrics
[i
].width
;
2664 while (!is_terminal_cluster(This
, i
)) {
2665 width
+= This
->clustermetrics
[i
].width
;
2668 /* count last one too */
2669 width
+= This
->clustermetrics
[i
].width
;
2672 if (width
> This
->minwidth
)
2673 This
->minwidth
= width
;
2675 This
->recompute
&= ~RECOMPUTE_MINIMAL_WIDTH
;
2678 *min_width
= This
->minwidth
;
2682 static HRESULT WINAPI
dwritetextlayout_HitTestPoint(IDWriteTextLayout2
*iface
,
2683 FLOAT pointX
, FLOAT pointY
, BOOL
* is_trailinghit
, BOOL
* is_inside
, DWRITE_HIT_TEST_METRICS
*metrics
)
2685 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2686 FIXME("(%p)->(%f %f %p %p %p): stub\n", This
, pointX
, pointY
, is_trailinghit
, is_inside
, metrics
);
2690 static HRESULT WINAPI
dwritetextlayout_HitTestTextPosition(IDWriteTextLayout2
*iface
,
2691 UINT32 textPosition
, BOOL is_trailinghit
, FLOAT
* pointX
, FLOAT
* pointY
, DWRITE_HIT_TEST_METRICS
*metrics
)
2693 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2694 FIXME("(%p)->(%u %d %p %p %p): stub\n", This
, textPosition
, is_trailinghit
, pointX
, pointY
, metrics
);
2698 static HRESULT WINAPI
dwritetextlayout_HitTestTextRange(IDWriteTextLayout2
*iface
,
2699 UINT32 textPosition
, UINT32 textLength
, FLOAT originX
, FLOAT originY
,
2700 DWRITE_HIT_TEST_METRICS
*metrics
, UINT32 max_metricscount
, UINT32
* actual_metricscount
)
2702 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2703 FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This
, textPosition
, textLength
, originX
, originY
, metrics
,
2704 max_metricscount
, actual_metricscount
);
2708 static HRESULT WINAPI
dwritetextlayout1_SetPairKerning(IDWriteTextLayout2
*iface
, BOOL is_pairkerning_enabled
,
2709 DWRITE_TEXT_RANGE range
)
2711 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2712 struct layout_range_attr_value value
;
2714 TRACE("(%p)->(%d %s)\n", This
, is_pairkerning_enabled
, debugstr_range(&range
));
2716 value
.range
= range
;
2717 value
.u
.pair_kerning
= !!is_pairkerning_enabled
;
2718 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_PAIR_KERNING
, &value
);
2721 static HRESULT WINAPI
dwritetextlayout1_GetPairKerning(IDWriteTextLayout2
*iface
, UINT32 position
, BOOL
*is_pairkerning_enabled
,
2722 DWRITE_TEXT_RANGE
*r
)
2724 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2725 struct layout_range
*range
;
2727 TRACE("(%p)->(%u %p %p)\n", This
, position
, is_pairkerning_enabled
, r
);
2729 if (position
>= This
->len
)
2732 range
= get_layout_range_by_pos(This
, position
);
2733 *is_pairkerning_enabled
= range
->pair_kerning
;
2735 return return_range(&range
->h
, r
);
2738 static HRESULT WINAPI
dwritetextlayout1_SetCharacterSpacing(IDWriteTextLayout2
*iface
, FLOAT leading
, FLOAT trailing
,
2739 FLOAT min_advance
, DWRITE_TEXT_RANGE range
)
2741 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2742 struct layout_range_attr_value value
;
2744 TRACE("(%p)->(%.2f %.2f %.2f %s)\n", This
, leading
, trailing
, min_advance
, debugstr_range(&range
));
2746 if (min_advance
< 0.0)
2747 return E_INVALIDARG
;
2749 value
.range
= range
;
2750 value
.u
.spacing
[0] = leading
;
2751 value
.u
.spacing
[1] = trailing
;
2752 value
.u
.spacing
[2] = min_advance
;
2753 return set_layout_range_attr(This
, LAYOUT_RANGE_ATTR_SPACING
, &value
);
2756 static HRESULT WINAPI
dwritetextlayout1_GetCharacterSpacing(IDWriteTextLayout2
*iface
, UINT32 position
, FLOAT
*leading
,
2757 FLOAT
*trailing
, FLOAT
*min_advance
, DWRITE_TEXT_RANGE
*r
)
2759 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2760 struct layout_range_spacing
*range
;
2762 TRACE("(%p)->(%u %p %p %p %p)\n", This
, position
, leading
, trailing
, min_advance
, r
);
2764 range
= (struct layout_range_spacing
*)get_layout_range_header_by_pos(&This
->spacing
, position
);
2765 *leading
= range
->leading
;
2766 *trailing
= range
->trailing
;
2767 *min_advance
= range
->min_advance
;
2769 return return_range(&range
->h
, r
);
2772 static HRESULT WINAPI
dwritetextlayout2_GetMetrics(IDWriteTextLayout2
*iface
, DWRITE_TEXT_METRICS1
*metrics
)
2774 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2775 FIXME("(%p)->(%p): stub\n", This
, metrics
);
2779 static HRESULT WINAPI
dwritetextlayout2_SetVerticalGlyphOrientation(IDWriteTextLayout2
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
2781 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2783 TRACE("(%p)->(%d)\n", This
, orientation
);
2785 if ((UINT32
)orientation
> DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
)
2786 return E_INVALIDARG
;
2788 This
->format
.vertical_orientation
= orientation
;
2792 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextlayout2_GetVerticalGlyphOrientation(IDWriteTextLayout2
*iface
)
2794 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2795 TRACE("(%p)\n", This
);
2796 return This
->format
.vertical_orientation
;
2799 static HRESULT WINAPI
dwritetextlayout2_SetLastLineWrapping(IDWriteTextLayout2
*iface
, BOOL lastline_wrapping_enabled
)
2801 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2802 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
2806 static BOOL WINAPI
dwritetextlayout2_GetLastLineWrapping(IDWriteTextLayout2
*iface
)
2808 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2809 FIXME("(%p): stub\n", This
);
2813 static HRESULT WINAPI
dwritetextlayout2_SetOpticalAlignment(IDWriteTextLayout2
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
2815 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2816 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2820 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextlayout2_GetOpticalAlignment(IDWriteTextLayout2
*iface
)
2822 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2823 FIXME("(%p): stub\n", This
);
2824 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
2827 static HRESULT WINAPI
dwritetextlayout2_SetFontFallback(IDWriteTextLayout2
*iface
, IDWriteFontFallback
*fallback
)
2829 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2830 TRACE("(%p)->(%p)\n", This
, fallback
);
2831 return set_fontfallback_for_format(&This
->format
, fallback
);
2834 static HRESULT WINAPI
dwritetextlayout2_GetFontFallback(IDWriteTextLayout2
*iface
, IDWriteFontFallback
**fallback
)
2836 struct dwrite_textlayout
*This
= impl_from_IDWriteTextLayout2(iface
);
2837 TRACE("(%p)->(%p)\n", This
, fallback
);
2838 return get_fontfallback_from_format(&This
->format
, fallback
);
2841 static const IDWriteTextLayout2Vtbl dwritetextlayoutvtbl
= {
2842 dwritetextlayout_QueryInterface
,
2843 dwritetextlayout_AddRef
,
2844 dwritetextlayout_Release
,
2845 dwritetextlayout_SetTextAlignment
,
2846 dwritetextlayout_SetParagraphAlignment
,
2847 dwritetextlayout_SetWordWrapping
,
2848 dwritetextlayout_SetReadingDirection
,
2849 dwritetextlayout_SetFlowDirection
,
2850 dwritetextlayout_SetIncrementalTabStop
,
2851 dwritetextlayout_SetTrimming
,
2852 dwritetextlayout_SetLineSpacing
,
2853 dwritetextlayout_GetTextAlignment
,
2854 dwritetextlayout_GetParagraphAlignment
,
2855 dwritetextlayout_GetWordWrapping
,
2856 dwritetextlayout_GetReadingDirection
,
2857 dwritetextlayout_GetFlowDirection
,
2858 dwritetextlayout_GetIncrementalTabStop
,
2859 dwritetextlayout_GetTrimming
,
2860 dwritetextlayout_GetLineSpacing
,
2861 dwritetextlayout_GetFontCollection
,
2862 dwritetextlayout_GetFontFamilyNameLength
,
2863 dwritetextlayout_GetFontFamilyName
,
2864 dwritetextlayout_GetFontWeight
,
2865 dwritetextlayout_GetFontStyle
,
2866 dwritetextlayout_GetFontStretch
,
2867 dwritetextlayout_GetFontSize
,
2868 dwritetextlayout_GetLocaleNameLength
,
2869 dwritetextlayout_GetLocaleName
,
2870 dwritetextlayout_SetMaxWidth
,
2871 dwritetextlayout_SetMaxHeight
,
2872 dwritetextlayout_SetFontCollection
,
2873 dwritetextlayout_SetFontFamilyName
,
2874 dwritetextlayout_SetFontWeight
,
2875 dwritetextlayout_SetFontStyle
,
2876 dwritetextlayout_SetFontStretch
,
2877 dwritetextlayout_SetFontSize
,
2878 dwritetextlayout_SetUnderline
,
2879 dwritetextlayout_SetStrikethrough
,
2880 dwritetextlayout_SetDrawingEffect
,
2881 dwritetextlayout_SetInlineObject
,
2882 dwritetextlayout_SetTypography
,
2883 dwritetextlayout_SetLocaleName
,
2884 dwritetextlayout_GetMaxWidth
,
2885 dwritetextlayout_GetMaxHeight
,
2886 dwritetextlayout_layout_GetFontCollection
,
2887 dwritetextlayout_layout_GetFontFamilyNameLength
,
2888 dwritetextlayout_layout_GetFontFamilyName
,
2889 dwritetextlayout_layout_GetFontWeight
,
2890 dwritetextlayout_layout_GetFontStyle
,
2891 dwritetextlayout_layout_GetFontStretch
,
2892 dwritetextlayout_layout_GetFontSize
,
2893 dwritetextlayout_GetUnderline
,
2894 dwritetextlayout_GetStrikethrough
,
2895 dwritetextlayout_GetDrawingEffect
,
2896 dwritetextlayout_GetInlineObject
,
2897 dwritetextlayout_GetTypography
,
2898 dwritetextlayout_layout_GetLocaleNameLength
,
2899 dwritetextlayout_layout_GetLocaleName
,
2900 dwritetextlayout_Draw
,
2901 dwritetextlayout_GetLineMetrics
,
2902 dwritetextlayout_GetMetrics
,
2903 dwritetextlayout_GetOverhangMetrics
,
2904 dwritetextlayout_GetClusterMetrics
,
2905 dwritetextlayout_DetermineMinWidth
,
2906 dwritetextlayout_HitTestPoint
,
2907 dwritetextlayout_HitTestTextPosition
,
2908 dwritetextlayout_HitTestTextRange
,
2909 dwritetextlayout1_SetPairKerning
,
2910 dwritetextlayout1_GetPairKerning
,
2911 dwritetextlayout1_SetCharacterSpacing
,
2912 dwritetextlayout1_GetCharacterSpacing
,
2913 dwritetextlayout2_GetMetrics
,
2914 dwritetextlayout2_SetVerticalGlyphOrientation
,
2915 dwritetextlayout2_GetVerticalGlyphOrientation
,
2916 dwritetextlayout2_SetLastLineWrapping
,
2917 dwritetextlayout2_GetLastLineWrapping
,
2918 dwritetextlayout2_SetOpticalAlignment
,
2919 dwritetextlayout2_GetOpticalAlignment
,
2920 dwritetextlayout2_SetFontFallback
,
2921 dwritetextlayout2_GetFontFallback
2924 static HRESULT WINAPI
dwritetextformat1_layout_QueryInterface(IDWriteTextFormat1
*iface
, REFIID riid
, void **obj
)
2926 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2927 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2928 return IDWriteTextLayout2_QueryInterface(&This
->IDWriteTextLayout2_iface
, riid
, obj
);
2931 static ULONG WINAPI
dwritetextformat1_layout_AddRef(IDWriteTextFormat1
*iface
)
2933 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2934 return IDWriteTextLayout2_AddRef(&This
->IDWriteTextLayout2_iface
);
2937 static ULONG WINAPI
dwritetextformat1_layout_Release(IDWriteTextFormat1
*iface
)
2939 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2940 return IDWriteTextLayout2_Release(&This
->IDWriteTextLayout2_iface
);
2943 static HRESULT WINAPI
dwritetextformat1_layout_SetTextAlignment(IDWriteTextFormat1
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
2945 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2946 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2950 static HRESULT WINAPI
dwritetextformat1_layout_SetParagraphAlignment(IDWriteTextFormat1
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
2952 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2953 FIXME("(%p)->(%d): stub\n", This
, alignment
);
2957 static HRESULT WINAPI
dwritetextformat1_layout_SetWordWrapping(IDWriteTextFormat1
*iface
, DWRITE_WORD_WRAPPING wrapping
)
2959 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2960 FIXME("(%p)->(%d): stub\n", This
, wrapping
);
2964 static HRESULT WINAPI
dwritetextformat1_layout_SetReadingDirection(IDWriteTextFormat1
*iface
, DWRITE_READING_DIRECTION direction
)
2966 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2967 FIXME("(%p)->(%d): stub\n", This
, direction
);
2971 static HRESULT WINAPI
dwritetextformat1_layout_SetFlowDirection(IDWriteTextFormat1
*iface
, DWRITE_FLOW_DIRECTION direction
)
2973 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2974 FIXME("(%p)->(%d): stub\n", This
, direction
);
2978 static HRESULT WINAPI
dwritetextformat1_layout_SetIncrementalTabStop(IDWriteTextFormat1
*iface
, FLOAT tabstop
)
2980 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2981 FIXME("(%p)->(%f): stub\n", This
, tabstop
);
2985 static HRESULT WINAPI
dwritetextformat1_layout_SetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
const *trimming
,
2986 IDWriteInlineObject
*trimming_sign
)
2988 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2989 FIXME("(%p)->(%p %p): stub\n", This
, trimming
, trimming_sign
);
2993 static HRESULT WINAPI
dwritetextformat1_layout_SetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD spacing
,
2994 FLOAT line_spacing
, FLOAT baseline
)
2996 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
2997 FIXME("(%p)->(%d %f %f): stub\n", This
, spacing
, line_spacing
, baseline
);
3001 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextformat1_layout_GetTextAlignment(IDWriteTextFormat1
*iface
)
3003 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3004 TRACE("(%p)\n", This
);
3005 return This
->format
.textalignment
;
3008 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextformat1_layout_GetParagraphAlignment(IDWriteTextFormat1
*iface
)
3010 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3011 TRACE("(%p)\n", This
);
3012 return This
->format
.paralign
;
3015 static DWRITE_WORD_WRAPPING WINAPI
dwritetextformat1_layout_GetWordWrapping(IDWriteTextFormat1
*iface
)
3017 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3018 FIXME("(%p): stub\n", This
);
3019 return This
->format
.wrapping
;
3022 static DWRITE_READING_DIRECTION WINAPI
dwritetextformat1_layout_GetReadingDirection(IDWriteTextFormat1
*iface
)
3024 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3025 TRACE("(%p)\n", This
);
3026 return This
->format
.readingdir
;
3029 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextformat1_layout_GetFlowDirection(IDWriteTextFormat1
*iface
)
3031 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3032 TRACE("(%p)\n", This
);
3033 return This
->format
.flow
;
3036 static FLOAT WINAPI
dwritetextformat1_layout_GetIncrementalTabStop(IDWriteTextFormat1
*iface
)
3038 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3039 FIXME("(%p): stub\n", This
);
3043 static HRESULT WINAPI
dwritetextformat1_layout_GetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
*options
,
3044 IDWriteInlineObject
**trimming_sign
)
3046 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3048 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
3050 *options
= This
->format
.trimming
;
3051 *trimming_sign
= This
->format
.trimmingsign
;
3053 IDWriteInlineObject_AddRef(*trimming_sign
);
3057 static HRESULT WINAPI
dwritetextformat1_layout_GetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
3058 FLOAT
*spacing
, FLOAT
*baseline
)
3060 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3062 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
3064 *method
= This
->format
.spacingmethod
;
3065 *spacing
= This
->format
.spacing
;
3066 *baseline
= This
->format
.baseline
;
3070 static HRESULT WINAPI
dwritetextformat1_layout_GetFontCollection(IDWriteTextFormat1
*iface
, IDWriteFontCollection
**collection
)
3072 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3074 TRACE("(%p)->(%p)\n", This
, collection
);
3076 *collection
= This
->format
.collection
;
3078 IDWriteFontCollection_AddRef(*collection
);
3082 static UINT32 WINAPI
dwritetextformat1_layout_GetFontFamilyNameLength(IDWriteTextFormat1
*iface
)
3084 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3085 TRACE("(%p)\n", This
);
3086 return This
->format
.family_len
;
3089 static HRESULT WINAPI
dwritetextformat1_layout_GetFontFamilyName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
3091 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3093 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
3095 if (size
<= This
->format
.family_len
) return E_NOT_SUFFICIENT_BUFFER
;
3096 strcpyW(name
, This
->format
.family_name
);
3100 static DWRITE_FONT_WEIGHT WINAPI
dwritetextformat1_layout_GetFontWeight(IDWriteTextFormat1
*iface
)
3102 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3103 TRACE("(%p)\n", This
);
3104 return This
->format
.weight
;
3107 static DWRITE_FONT_STYLE WINAPI
dwritetextformat1_layout_GetFontStyle(IDWriteTextFormat1
*iface
)
3109 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3110 TRACE("(%p)\n", This
);
3111 return This
->format
.style
;
3114 static DWRITE_FONT_STRETCH WINAPI
dwritetextformat1_layout_GetFontStretch(IDWriteTextFormat1
*iface
)
3116 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3117 TRACE("(%p)\n", This
);
3118 return This
->format
.stretch
;
3121 static FLOAT WINAPI
dwritetextformat1_layout_GetFontSize(IDWriteTextFormat1
*iface
)
3123 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3124 TRACE("(%p)\n", This
);
3125 return This
->format
.fontsize
;
3128 static UINT32 WINAPI
dwritetextformat1_layout_GetLocaleNameLength(IDWriteTextFormat1
*iface
)
3130 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3131 TRACE("(%p)\n", This
);
3132 return This
->format
.locale_len
;
3135 static HRESULT WINAPI
dwritetextformat1_layout_GetLocaleName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
3137 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3139 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
3141 if (size
<= This
->format
.locale_len
) return E_NOT_SUFFICIENT_BUFFER
;
3142 strcpyW(name
, This
->format
.locale
);
3146 static HRESULT WINAPI
dwritetextformat1_layout_SetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
3148 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3149 FIXME("(%p)->(%d): stub\n", This
, orientation
);
3153 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextformat1_layout_GetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
)
3155 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3156 FIXME("(%p): stub\n", This
);
3157 return DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
3160 static HRESULT WINAPI
dwritetextformat1_layout_SetLastLineWrapping(IDWriteTextFormat1
*iface
, BOOL lastline_wrapping_enabled
)
3162 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3163 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
3167 static BOOL WINAPI
dwritetextformat1_layout_GetLastLineWrapping(IDWriteTextFormat1
*iface
)
3169 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3170 FIXME("(%p): stub\n", This
);
3174 static HRESULT WINAPI
dwritetextformat1_layout_SetOpticalAlignment(IDWriteTextFormat1
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
3176 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3177 FIXME("(%p)->(%d): stub\n", This
, alignment
);
3181 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextformat1_layout_GetOpticalAlignment(IDWriteTextFormat1
*iface
)
3183 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3184 FIXME("(%p): stub\n", This
);
3185 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
3188 static HRESULT WINAPI
dwritetextformat1_layout_SetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
*fallback
)
3190 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3191 TRACE("(%p)->(%p)\n", This
, fallback
);
3192 return IDWriteTextLayout2_SetFontFallback(&This
->IDWriteTextLayout2_iface
, fallback
);
3195 static HRESULT WINAPI
dwritetextformat1_layout_GetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
**fallback
)
3197 struct dwrite_textlayout
*This
= impl_layout_form_IDWriteTextFormat1(iface
);
3198 TRACE("(%p)->(%p)\n", This
, fallback
);
3199 return IDWriteTextLayout2_GetFontFallback(&This
->IDWriteTextLayout2_iface
, fallback
);
3202 static const IDWriteTextFormat1Vtbl dwritetextformat1_layout_vtbl
= {
3203 dwritetextformat1_layout_QueryInterface
,
3204 dwritetextformat1_layout_AddRef
,
3205 dwritetextformat1_layout_Release
,
3206 dwritetextformat1_layout_SetTextAlignment
,
3207 dwritetextformat1_layout_SetParagraphAlignment
,
3208 dwritetextformat1_layout_SetWordWrapping
,
3209 dwritetextformat1_layout_SetReadingDirection
,
3210 dwritetextformat1_layout_SetFlowDirection
,
3211 dwritetextformat1_layout_SetIncrementalTabStop
,
3212 dwritetextformat1_layout_SetTrimming
,
3213 dwritetextformat1_layout_SetLineSpacing
,
3214 dwritetextformat1_layout_GetTextAlignment
,
3215 dwritetextformat1_layout_GetParagraphAlignment
,
3216 dwritetextformat1_layout_GetWordWrapping
,
3217 dwritetextformat1_layout_GetReadingDirection
,
3218 dwritetextformat1_layout_GetFlowDirection
,
3219 dwritetextformat1_layout_GetIncrementalTabStop
,
3220 dwritetextformat1_layout_GetTrimming
,
3221 dwritetextformat1_layout_GetLineSpacing
,
3222 dwritetextformat1_layout_GetFontCollection
,
3223 dwritetextformat1_layout_GetFontFamilyNameLength
,
3224 dwritetextformat1_layout_GetFontFamilyName
,
3225 dwritetextformat1_layout_GetFontWeight
,
3226 dwritetextformat1_layout_GetFontStyle
,
3227 dwritetextformat1_layout_GetFontStretch
,
3228 dwritetextformat1_layout_GetFontSize
,
3229 dwritetextformat1_layout_GetLocaleNameLength
,
3230 dwritetextformat1_layout_GetLocaleName
,
3231 dwritetextformat1_layout_SetVerticalGlyphOrientation
,
3232 dwritetextformat1_layout_GetVerticalGlyphOrientation
,
3233 dwritetextformat1_layout_SetLastLineWrapping
,
3234 dwritetextformat1_layout_GetLastLineWrapping
,
3235 dwritetextformat1_layout_SetOpticalAlignment
,
3236 dwritetextformat1_layout_GetOpticalAlignment
,
3237 dwritetextformat1_layout_SetFontFallback
,
3238 dwritetextformat1_layout_GetFontFallback
3241 static HRESULT WINAPI
dwritetextlayout_sink_QueryInterface(IDWriteTextAnalysisSink
*iface
,
3242 REFIID riid
, void **obj
)
3244 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSink
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3246 IDWriteTextAnalysisSink_AddRef(iface
);
3251 return E_NOINTERFACE
;
3254 static ULONG WINAPI
dwritetextlayout_sink_AddRef(IDWriteTextAnalysisSink
*iface
)
3259 static ULONG WINAPI
dwritetextlayout_sink_Release(IDWriteTextAnalysisSink
*iface
)
3264 static HRESULT WINAPI
dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysisSink
*iface
,
3265 UINT32 position
, UINT32 length
, DWRITE_SCRIPT_ANALYSIS
const* sa
)
3267 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
3268 struct layout_run
*run
;
3270 TRACE("%u %u script=%d\n", position
, length
, sa
->script
);
3272 run
= alloc_layout_run(LAYOUT_RUN_REGULAR
);
3274 return E_OUTOFMEMORY
;
3276 run
->u
.regular
.descr
.string
= &layout
->str
[position
];
3277 run
->u
.regular
.descr
.stringLength
= length
;
3278 run
->u
.regular
.descr
.textPosition
= position
;
3279 run
->u
.regular
.sa
= *sa
;
3280 list_add_tail(&layout
->runs
, &run
->entry
);
3284 static HRESULT WINAPI
dwritetextlayout_sink_SetLineBreakpoints(IDWriteTextAnalysisSink
*iface
,
3285 UINT32 position
, UINT32 length
, DWRITE_LINE_BREAKPOINT
const* breakpoints
)
3287 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
3289 if (position
+ length
> layout
->len
)
3292 memcpy(&layout
->nominal_breakpoints
[position
], breakpoints
, length
*sizeof(DWRITE_LINE_BREAKPOINT
));
3296 static HRESULT WINAPI
dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink
*iface
, UINT32 position
,
3297 UINT32 length
, UINT8 explicitLevel
, UINT8 resolvedLevel
)
3299 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSink(iface
);
3300 struct layout_run
*cur_run
;
3302 TRACE("%u %u %u %u\n", position
, length
, explicitLevel
, resolvedLevel
);
3304 LIST_FOR_EACH_ENTRY(cur_run
, &layout
->runs
, struct layout_run
, entry
) {
3305 struct regular_layout_run
*cur
= &cur_run
->u
.regular
;
3306 struct layout_run
*run
;
3308 if (cur_run
->kind
== LAYOUT_RUN_INLINE
)
3311 /* FIXME: levels are reported in a natural forward direction, so start loop from a run we ended on */
3312 if (position
< cur
->descr
.textPosition
|| position
>= cur
->descr
.textPosition
+ cur
->descr
.stringLength
)
3315 /* full hit - just set run level */
3316 if (cur
->descr
.textPosition
== position
&& cur
->descr
.stringLength
== length
) {
3317 cur
->run
.bidiLevel
= resolvedLevel
;
3321 /* current run is fully covered, move to next one */
3322 if (cur
->descr
.textPosition
== position
&& cur
->descr
.stringLength
< length
) {
3323 cur
->run
.bidiLevel
= resolvedLevel
;
3324 position
+= cur
->descr
.stringLength
;
3325 length
-= cur
->descr
.stringLength
;
3329 /* all fully covered runs are processed at this point, reuse existing run for remaining
3330 reported bidi range and add another run for the rest of original one */
3332 run
= alloc_layout_run(LAYOUT_RUN_REGULAR
);
3334 return E_OUTOFMEMORY
;
3337 run
->u
.regular
.descr
.textPosition
= position
+ length
;
3338 run
->u
.regular
.descr
.stringLength
= cur
->descr
.stringLength
- length
;
3339 run
->u
.regular
.descr
.string
= &layout
->str
[position
+ length
];
3341 /* reduce existing run */
3342 cur
->run
.bidiLevel
= resolvedLevel
;
3343 cur
->descr
.stringLength
= length
;
3345 list_add_after(&cur_run
->entry
, &run
->entry
);
3352 static HRESULT WINAPI
dwritetextlayout_sink_SetNumberSubstitution(IDWriteTextAnalysisSink
*iface
,
3353 UINT32 position
, UINT32 length
, IDWriteNumberSubstitution
* substitution
)
3358 static const IDWriteTextAnalysisSinkVtbl dwritetextlayoutsinkvtbl
= {
3359 dwritetextlayout_sink_QueryInterface
,
3360 dwritetextlayout_sink_AddRef
,
3361 dwritetextlayout_sink_Release
,
3362 dwritetextlayout_sink_SetScriptAnalysis
,
3363 dwritetextlayout_sink_SetLineBreakpoints
,
3364 dwritetextlayout_sink_SetBidiLevel
,
3365 dwritetextlayout_sink_SetNumberSubstitution
3368 static HRESULT WINAPI
dwritetextlayout_source_QueryInterface(IDWriteTextAnalysisSource
*iface
,
3369 REFIID riid
, void **obj
)
3371 if (IsEqualIID(riid
, &IID_IDWriteTextAnalysisSource
) ||
3372 IsEqualIID(riid
, &IID_IUnknown
))
3375 IDWriteTextAnalysisSource_AddRef(iface
);
3380 return E_NOINTERFACE
;
3383 static ULONG WINAPI
dwritetextlayout_source_AddRef(IDWriteTextAnalysisSource
*iface
)
3388 static ULONG WINAPI
dwritetextlayout_source_Release(IDWriteTextAnalysisSource
*iface
)
3393 static HRESULT WINAPI
dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnalysisSource
*iface
,
3394 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
3396 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSource(iface
);
3398 TRACE("(%p)->(%u %p %p)\n", layout
, position
, text
, text_len
);
3400 if (position
< layout
->len
) {
3401 *text
= &layout
->str
[position
];
3402 *text_len
= layout
->len
- position
;
3412 static HRESULT WINAPI
dwritetextlayout_source_GetTextBeforePosition(IDWriteTextAnalysisSource
*iface
,
3413 UINT32 position
, WCHAR
const** text
, UINT32
* text_len
)
3415 FIXME("%u %p %p: stub\n", position
, text
, text_len
);
3419 static DWRITE_READING_DIRECTION WINAPI
dwritetextlayout_source_GetParagraphReadingDirection(IDWriteTextAnalysisSource
*iface
)
3421 struct dwrite_textlayout
*layout
= impl_from_IDWriteTextAnalysisSource(iface
);
3422 return IDWriteTextLayout2_GetReadingDirection(&layout
->IDWriteTextLayout2_iface
);
3425 static HRESULT WINAPI
dwritetextlayout_source_GetLocaleName(IDWriteTextAnalysisSource
*iface
,
3426 UINT32 position
, UINT32
* text_len
, WCHAR
const** locale
)
3428 FIXME("%u %p %p: stub\n", position
, text_len
, locale
);
3432 static HRESULT WINAPI
dwritetextlayout_source_GetNumberSubstitution(IDWriteTextAnalysisSource
*iface
,
3433 UINT32 position
, UINT32
* text_len
, IDWriteNumberSubstitution
**substitution
)
3435 FIXME("%u %p %p: stub\n", position
, text_len
, substitution
);
3439 static const IDWriteTextAnalysisSourceVtbl dwritetextlayoutsourcevtbl
= {
3440 dwritetextlayout_source_QueryInterface
,
3441 dwritetextlayout_source_AddRef
,
3442 dwritetextlayout_source_Release
,
3443 dwritetextlayout_source_GetTextAtPosition
,
3444 dwritetextlayout_source_GetTextBeforePosition
,
3445 dwritetextlayout_source_GetParagraphReadingDirection
,
3446 dwritetextlayout_source_GetLocaleName
,
3447 dwritetextlayout_source_GetNumberSubstitution
3450 static HRESULT
layout_format_from_textformat(struct dwrite_textlayout
*layout
, IDWriteTextFormat
*format
)
3452 IDWriteTextFormat1
*format1
;
3456 layout
->format
.weight
= IDWriteTextFormat_GetFontWeight(format
);
3457 layout
->format
.style
= IDWriteTextFormat_GetFontStyle(format
);
3458 layout
->format
.stretch
= IDWriteTextFormat_GetFontStretch(format
);
3459 layout
->format
.fontsize
= IDWriteTextFormat_GetFontSize(format
);
3460 layout
->format
.textalignment
= IDWriteTextFormat_GetTextAlignment(format
);
3461 layout
->format
.paralign
= IDWriteTextFormat_GetParagraphAlignment(format
);
3462 layout
->format
.wrapping
= IDWriteTextFormat_GetWordWrapping(format
);
3463 layout
->format
.readingdir
= IDWriteTextFormat_GetReadingDirection(format
);
3464 layout
->format
.flow
= IDWriteTextFormat_GetFlowDirection(format
);
3465 layout
->format
.fallback
= NULL
;
3466 hr
= IDWriteTextFormat_GetLineSpacing(format
, &layout
->format
.spacingmethod
,
3467 &layout
->format
.spacing
, &layout
->format
.baseline
);
3471 hr
= IDWriteTextFormat_GetTrimming(format
, &layout
->format
.trimming
, &layout
->format
.trimmingsign
);
3475 /* locale name and length */
3476 len
= IDWriteTextFormat_GetLocaleNameLength(format
);
3477 layout
->format
.locale
= heap_alloc((len
+1)*sizeof(WCHAR
));
3478 if (!layout
->format
.locale
)
3479 return E_OUTOFMEMORY
;
3481 hr
= IDWriteTextFormat_GetLocaleName(format
, layout
->format
.locale
, len
+1);
3484 layout
->format
.locale_len
= len
;
3486 /* font family name and length */
3487 len
= IDWriteTextFormat_GetFontFamilyNameLength(format
);
3488 layout
->format
.family_name
= heap_alloc((len
+1)*sizeof(WCHAR
));
3489 if (!layout
->format
.family_name
)
3490 return E_OUTOFMEMORY
;
3492 hr
= IDWriteTextFormat_GetFontFamilyName(format
, layout
->format
.family_name
, len
+1);
3495 layout
->format
.family_len
= len
;
3497 hr
= IDWriteTextFormat_QueryInterface(format
, &IID_IDWriteTextFormat1
, (void**)&format1
);
3499 layout
->format
.vertical_orientation
= IDWriteTextFormat1_GetVerticalGlyphOrientation(format1
);
3500 IDWriteTextFormat1_GetFontFallback(format1
, &layout
->format
.fallback
);
3501 IDWriteTextFormat1_Release(format1
);
3504 layout
->format
.vertical_orientation
= DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
3506 return IDWriteTextFormat_GetFontCollection(format
, &layout
->format
.collection
);
3509 static HRESULT
init_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
, struct dwrite_textlayout
*layout
)
3511 struct layout_range_header
*range
, *strike
, *effect
, *spacing
;
3512 DWRITE_TEXT_RANGE r
= { 0, ~0u };
3515 layout
->IDWriteTextLayout2_iface
.lpVtbl
= &dwritetextlayoutvtbl
;
3516 layout
->IDWriteTextFormat1_iface
.lpVtbl
= &dwritetextformat1_layout_vtbl
;
3517 layout
->IDWriteTextAnalysisSink_iface
.lpVtbl
= &dwritetextlayoutsinkvtbl
;
3518 layout
->IDWriteTextAnalysisSource_iface
.lpVtbl
= &dwritetextlayoutsourcevtbl
;
3521 layout
->maxwidth
= maxwidth
;
3522 layout
->maxheight
= maxheight
;
3523 layout
->recompute
= RECOMPUTE_EVERYTHING
;
3524 layout
->nominal_breakpoints
= NULL
;
3525 layout
->actual_breakpoints
= NULL
;
3526 layout
->cluster_count
= 0;
3527 layout
->clustermetrics
= NULL
;
3528 layout
->clusters
= NULL
;
3529 layout
->lines
= NULL
;
3530 layout
->line_count
= 0;
3531 layout
->line_alloc
= 0;
3532 layout
->minwidth
= 0.0;
3533 list_init(&layout
->eruns
);
3534 list_init(&layout
->inlineobjects
);
3535 list_init(&layout
->strikethrough
);
3536 list_init(&layout
->runs
);
3537 list_init(&layout
->ranges
);
3538 list_init(&layout
->strike_ranges
);
3539 list_init(&layout
->effects
);
3540 list_init(&layout
->spacing
);
3541 memset(&layout
->format
, 0, sizeof(layout
->format
));
3543 layout
->gdicompatible
= FALSE
;
3544 layout
->pixels_per_dip
= 0.0;
3545 layout
->use_gdi_natural
= FALSE
;
3546 memset(&layout
->transform
, 0, sizeof(layout
->transform
));
3548 layout
->str
= heap_strdupnW(str
, len
);
3549 if (len
&& !layout
->str
) {
3554 hr
= layout_format_from_textformat(layout
, format
);
3558 range
= alloc_layout_range(layout
, &r
, LAYOUT_RANGE_REGULAR
);
3559 strike
= alloc_layout_range(layout
, &r
, LAYOUT_RANGE_STRIKETHROUGH
);
3560 effect
= alloc_layout_range(layout
, &r
, LAYOUT_RANGE_EFFECT
);
3561 spacing
= alloc_layout_range(layout
, &r
, LAYOUT_RANGE_SPACING
);
3562 if (!range
|| !strike
|| !effect
|| !spacing
) {
3563 free_layout_range(range
);
3564 free_layout_range(strike
);
3565 free_layout_range(effect
);
3566 free_layout_range(spacing
);
3571 list_add_head(&layout
->ranges
, &range
->entry
);
3572 list_add_head(&layout
->strike_ranges
, &strike
->entry
);
3573 list_add_head(&layout
->effects
, &effect
->entry
);
3574 list_add_head(&layout
->spacing
, &spacing
->entry
);
3578 IDWriteTextLayout2_Release(&layout
->IDWriteTextLayout2_iface
);
3582 HRESULT
create_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
, IDWriteTextLayout
**ret
)
3584 struct dwrite_textlayout
*layout
;
3589 layout
= heap_alloc(sizeof(struct dwrite_textlayout
));
3590 if (!layout
) return E_OUTOFMEMORY
;
3592 hr
= init_textlayout(str
, len
, format
, maxwidth
, maxheight
, layout
);
3594 *ret
= (IDWriteTextLayout
*)&layout
->IDWriteTextLayout2_iface
;
3599 HRESULT
create_gdicompat_textlayout(const WCHAR
*str
, UINT32 len
, IDWriteTextFormat
*format
, FLOAT maxwidth
, FLOAT maxheight
,
3600 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
, IDWriteTextLayout
**ret
)
3602 struct dwrite_textlayout
*layout
;
3607 layout
= heap_alloc(sizeof(struct dwrite_textlayout
));
3608 if (!layout
) return E_OUTOFMEMORY
;
3610 hr
= init_textlayout(str
, len
, format
, maxwidth
, maxheight
, layout
);
3612 /* set gdi-specific properties */
3613 layout
->gdicompatible
= TRUE
;
3614 layout
->pixels_per_dip
= pixels_per_dip
;
3615 layout
->use_gdi_natural
= use_gdi_natural
;
3616 layout
->transform
= transform
? *transform
: identity
;
3618 *ret
= (IDWriteTextLayout
*)&layout
->IDWriteTextLayout2_iface
;
3624 static HRESULT WINAPI
dwritetrimmingsign_QueryInterface(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
3626 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3628 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3630 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteInlineObject
)) {
3632 IDWriteInlineObject_AddRef(iface
);
3637 return E_NOINTERFACE
;
3640 static ULONG WINAPI
dwritetrimmingsign_AddRef(IDWriteInlineObject
*iface
)
3642 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3643 ULONG ref
= InterlockedIncrement(&This
->ref
);
3644 TRACE("(%p)->(%d)\n", This
, ref
);
3648 static ULONG WINAPI
dwritetrimmingsign_Release(IDWriteInlineObject
*iface
)
3650 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3651 ULONG ref
= InterlockedDecrement(&This
->ref
);
3653 TRACE("(%p)->(%d)\n", This
, ref
);
3656 IDWriteTextLayout_Release(This
->layout
);
3663 static HRESULT WINAPI
dwritetrimmingsign_Draw(IDWriteInlineObject
*iface
, void *context
, IDWriteTextRenderer
*renderer
,
3664 FLOAT originX
, FLOAT originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*effect
)
3666 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3667 DWRITE_TEXT_RANGE range
= { 0, ~0u };
3669 TRACE("(%p)->(%p %p %.2f %.2f %d %d %p)\n", This
, context
, renderer
, originX
, originY
, is_sideways
, is_rtl
, effect
);
3671 IDWriteTextLayout_SetDrawingEffect(This
->layout
, effect
, range
);
3672 return IDWriteTextLayout_Draw(This
->layout
, context
, renderer
, originX
, originY
);
3675 static HRESULT WINAPI
dwritetrimmingsign_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*metrics
)
3677 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3678 FIXME("(%p)->(%p): stub\n", This
, metrics
);
3679 memset(metrics
, 0, sizeof(*metrics
));
3683 static HRESULT WINAPI
dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
3685 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3686 FIXME("(%p)->(%p): stub\n", This
, overhangs
);
3690 static HRESULT WINAPI
dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
3691 DWRITE_BREAK_CONDITION
*after
)
3693 struct dwrite_trimmingsign
*This
= impl_from_IDWriteInlineObject(iface
);
3695 TRACE("(%p)->(%p %p)\n", This
, before
, after
);
3697 *before
= *after
= DWRITE_BREAK_CONDITION_NEUTRAL
;
3701 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl
= {
3702 dwritetrimmingsign_QueryInterface
,
3703 dwritetrimmingsign_AddRef
,
3704 dwritetrimmingsign_Release
,
3705 dwritetrimmingsign_Draw
,
3706 dwritetrimmingsign_GetMetrics
,
3707 dwritetrimmingsign_GetOverhangMetrics
,
3708 dwritetrimmingsign_GetBreakConditions
3711 static inline BOOL
is_reading_direction_horz(DWRITE_READING_DIRECTION direction
)
3713 return (direction
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
) ||
3714 (direction
== DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
);
3717 static inline BOOL
is_reading_direction_vert(DWRITE_READING_DIRECTION direction
)
3719 return (direction
== DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
) ||
3720 (direction
== DWRITE_READING_DIRECTION_BOTTOM_TO_TOP
);
3723 static inline BOOL
is_flow_direction_horz(DWRITE_FLOW_DIRECTION direction
)
3725 return (direction
== DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
) ||
3726 (direction
== DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT
);
3729 static inline BOOL
is_flow_direction_vert(DWRITE_FLOW_DIRECTION direction
)
3731 return (direction
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
) ||
3732 (direction
== DWRITE_FLOW_DIRECTION_BOTTOM_TO_TOP
);
3735 HRESULT
create_trimmingsign(IDWriteFactory2
*factory
, IDWriteTextFormat
*format
, IDWriteInlineObject
**sign
)
3737 static const WCHAR ellipsisW
= 0x2026;
3738 struct dwrite_trimmingsign
*This
;
3739 DWRITE_READING_DIRECTION reading
;
3740 DWRITE_FLOW_DIRECTION flow
;
3745 /* Validate reading/flow direction here, layout creation won't complain about
3746 invalid combinations. */
3747 reading
= IDWriteTextFormat_GetReadingDirection(format
);
3748 flow
= IDWriteTextFormat_GetFlowDirection(format
);
3750 if ((is_reading_direction_horz(reading
) && is_flow_direction_horz(flow
)) ||
3751 (is_reading_direction_vert(reading
) && is_flow_direction_vert(flow
)))
3752 return DWRITE_E_FLOWDIRECTIONCONFLICTS
;
3754 This
= heap_alloc(sizeof(*This
));
3756 return E_OUTOFMEMORY
;
3758 This
->IDWriteInlineObject_iface
.lpVtbl
= &dwritetrimmingsignvtbl
;
3761 hr
= IDWriteFactory2_CreateTextLayout(factory
, &ellipsisW
, 1, format
, 0.0, 0.0, &This
->layout
);
3767 IDWriteTextLayout_SetWordWrapping(This
->layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
3768 *sign
= &This
->IDWriteInlineObject_iface
;
3773 static HRESULT WINAPI
dwritetextformat_QueryInterface(IDWriteTextFormat1
*iface
, REFIID riid
, void **obj
)
3775 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3777 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3779 if (IsEqualIID(riid
, &IID_IDWriteTextFormat1
) ||
3780 IsEqualIID(riid
, &IID_IDWriteTextFormat
) ||
3781 IsEqualIID(riid
, &IID_IUnknown
))
3784 IDWriteTextFormat1_AddRef(iface
);
3790 return E_NOINTERFACE
;
3793 static ULONG WINAPI
dwritetextformat_AddRef(IDWriteTextFormat1
*iface
)
3795 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3796 ULONG ref
= InterlockedIncrement(&This
->ref
);
3797 TRACE("(%p)->(%d)\n", This
, ref
);
3801 static ULONG WINAPI
dwritetextformat_Release(IDWriteTextFormat1
*iface
)
3803 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3804 ULONG ref
= InterlockedDecrement(&This
->ref
);
3806 TRACE("(%p)->(%d)\n", This
, ref
);
3810 release_format_data(&This
->format
);
3817 static HRESULT WINAPI
dwritetextformat_SetTextAlignment(IDWriteTextFormat1
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
3819 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3821 TRACE("(%p)->(%d)\n", This
, alignment
);
3823 if ((UINT32
)alignment
> DWRITE_TEXT_ALIGNMENT_JUSTIFIED
)
3824 return E_INVALIDARG
;
3826 This
->format
.textalignment
= alignment
;
3830 static HRESULT WINAPI
dwritetextformat_SetParagraphAlignment(IDWriteTextFormat1
*iface
, DWRITE_PARAGRAPH_ALIGNMENT alignment
)
3832 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3834 TRACE("(%p)->(%d)\n", This
, alignment
);
3836 if ((UINT32
)alignment
> DWRITE_PARAGRAPH_ALIGNMENT_CENTER
)
3837 return E_INVALIDARG
;
3839 This
->format
.paralign
= alignment
;
3843 static HRESULT WINAPI
dwritetextformat_SetWordWrapping(IDWriteTextFormat1
*iface
, DWRITE_WORD_WRAPPING wrapping
)
3845 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3847 TRACE("(%p)->(%d)\n", This
, wrapping
);
3849 if ((UINT32
)wrapping
> DWRITE_WORD_WRAPPING_CHARACTER
)
3850 return E_INVALIDARG
;
3852 This
->format
.wrapping
= wrapping
;
3856 static HRESULT WINAPI
dwritetextformat_SetReadingDirection(IDWriteTextFormat1
*iface
, DWRITE_READING_DIRECTION direction
)
3858 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3860 TRACE("(%p)->(%d)\n", This
, direction
);
3862 if ((UINT32
)direction
> DWRITE_READING_DIRECTION_BOTTOM_TO_TOP
)
3863 return E_INVALIDARG
;
3865 This
->format
.readingdir
= direction
;
3869 static HRESULT WINAPI
dwritetextformat_SetFlowDirection(IDWriteTextFormat1
*iface
, DWRITE_FLOW_DIRECTION direction
)
3871 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3873 TRACE("(%p)->(%d)\n", This
, direction
);
3875 if ((UINT32
)direction
> DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT
)
3876 return E_INVALIDARG
;
3878 This
->format
.flow
= direction
;
3882 static HRESULT WINAPI
dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat1
*iface
, FLOAT tabstop
)
3884 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3885 FIXME("(%p)->(%f): stub\n", This
, tabstop
);
3889 static HRESULT WINAPI
dwritetextformat_SetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
const *trimming
,
3890 IDWriteInlineObject
*trimming_sign
)
3892 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3893 TRACE("(%p)->(%p %p)\n", This
, trimming
, trimming_sign
);
3895 This
->format
.trimming
= *trimming
;
3896 if (This
->format
.trimmingsign
)
3897 IDWriteInlineObject_Release(This
->format
.trimmingsign
);
3898 This
->format
.trimmingsign
= trimming_sign
;
3899 if (This
->format
.trimmingsign
)
3900 IDWriteInlineObject_AddRef(This
->format
.trimmingsign
);
3904 static HRESULT WINAPI
dwritetextformat_SetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD method
,
3905 FLOAT spacing
, FLOAT baseline
)
3907 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3909 TRACE("(%p)->(%d %f %f)\n", This
, method
, spacing
, baseline
);
3911 if (spacing
< 0.0 || (UINT32
)method
> DWRITE_LINE_SPACING_METHOD_UNIFORM
)
3912 return E_INVALIDARG
;
3914 This
->format
.spacingmethod
= method
;
3915 This
->format
.spacing
= spacing
;
3916 This
->format
.baseline
= baseline
;
3920 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextformat_GetTextAlignment(IDWriteTextFormat1
*iface
)
3922 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3923 TRACE("(%p)\n", This
);
3924 return This
->format
.textalignment
;
3927 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextformat_GetParagraphAlignment(IDWriteTextFormat1
*iface
)
3929 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3930 TRACE("(%p)\n", This
);
3931 return This
->format
.paralign
;
3934 static DWRITE_WORD_WRAPPING WINAPI
dwritetextformat_GetWordWrapping(IDWriteTextFormat1
*iface
)
3936 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3937 TRACE("(%p)\n", This
);
3938 return This
->format
.wrapping
;
3941 static DWRITE_READING_DIRECTION WINAPI
dwritetextformat_GetReadingDirection(IDWriteTextFormat1
*iface
)
3943 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3944 TRACE("(%p)\n", This
);
3945 return This
->format
.readingdir
;
3948 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextformat_GetFlowDirection(IDWriteTextFormat1
*iface
)
3950 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3951 TRACE("(%p)\n", This
);
3952 return This
->format
.flow
;
3955 static FLOAT WINAPI
dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat1
*iface
)
3957 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3958 FIXME("(%p): stub\n", This
);
3962 static HRESULT WINAPI
dwritetextformat_GetTrimming(IDWriteTextFormat1
*iface
, DWRITE_TRIMMING
*options
,
3963 IDWriteInlineObject
**trimming_sign
)
3965 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3966 TRACE("(%p)->(%p %p)\n", This
, options
, trimming_sign
);
3968 *options
= This
->format
.trimming
;
3969 if ((*trimming_sign
= This
->format
.trimmingsign
))
3970 IDWriteInlineObject_AddRef(*trimming_sign
);
3975 static HRESULT WINAPI
dwritetextformat_GetLineSpacing(IDWriteTextFormat1
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
3976 FLOAT
*spacing
, FLOAT
*baseline
)
3978 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3979 TRACE("(%p)->(%p %p %p)\n", This
, method
, spacing
, baseline
);
3981 *method
= This
->format
.spacingmethod
;
3982 *spacing
= This
->format
.spacing
;
3983 *baseline
= This
->format
.baseline
;
3987 static HRESULT WINAPI
dwritetextformat_GetFontCollection(IDWriteTextFormat1
*iface
, IDWriteFontCollection
**collection
)
3989 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
3991 TRACE("(%p)->(%p)\n", This
, collection
);
3993 *collection
= This
->format
.collection
;
3994 IDWriteFontCollection_AddRef(*collection
);
3999 static UINT32 WINAPI
dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat1
*iface
)
4001 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4002 TRACE("(%p)\n", This
);
4003 return This
->format
.family_len
;
4006 static HRESULT WINAPI
dwritetextformat_GetFontFamilyName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
4008 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4010 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
4012 if (size
<= This
->format
.family_len
) return E_NOT_SUFFICIENT_BUFFER
;
4013 strcpyW(name
, This
->format
.family_name
);
4017 static DWRITE_FONT_WEIGHT WINAPI
dwritetextformat_GetFontWeight(IDWriteTextFormat1
*iface
)
4019 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4020 TRACE("(%p)\n", This
);
4021 return This
->format
.weight
;
4024 static DWRITE_FONT_STYLE WINAPI
dwritetextformat_GetFontStyle(IDWriteTextFormat1
*iface
)
4026 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4027 TRACE("(%p)\n", This
);
4028 return This
->format
.style
;
4031 static DWRITE_FONT_STRETCH WINAPI
dwritetextformat_GetFontStretch(IDWriteTextFormat1
*iface
)
4033 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4034 TRACE("(%p)\n", This
);
4035 return This
->format
.stretch
;
4038 static FLOAT WINAPI
dwritetextformat_GetFontSize(IDWriteTextFormat1
*iface
)
4040 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4041 TRACE("(%p)\n", This
);
4042 return This
->format
.fontsize
;
4045 static UINT32 WINAPI
dwritetextformat_GetLocaleNameLength(IDWriteTextFormat1
*iface
)
4047 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4048 TRACE("(%p)\n", This
);
4049 return This
->format
.locale_len
;
4052 static HRESULT WINAPI
dwritetextformat_GetLocaleName(IDWriteTextFormat1
*iface
, WCHAR
*name
, UINT32 size
)
4054 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4056 TRACE("(%p)->(%p %u)\n", This
, name
, size
);
4058 if (size
<= This
->format
.locale_len
) return E_NOT_SUFFICIENT_BUFFER
;
4059 strcpyW(name
, This
->format
.locale
);
4063 static HRESULT WINAPI
dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
4065 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4067 TRACE("(%p)->(%d)\n", This
, orientation
);
4069 if ((UINT32
)orientation
> DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
)
4070 return E_INVALIDARG
;
4072 This
->format
.vertical_orientation
= orientation
;
4076 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat1
*iface
)
4078 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4079 TRACE("(%p)\n", This
);
4080 return This
->format
.vertical_orientation
;
4083 static HRESULT WINAPI
dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat1
*iface
, BOOL lastline_wrapping_enabled
)
4085 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4086 FIXME("(%p)->(%d): stub\n", This
, lastline_wrapping_enabled
);
4090 static BOOL WINAPI
dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat1
*iface
)
4092 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4093 FIXME("(%p): stub\n", This
);
4097 static HRESULT WINAPI
dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat1
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
4099 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4100 FIXME("(%p)->(%d): stub\n", This
, alignment
);
4104 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat1
*iface
)
4106 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4107 FIXME("(%p): stub\n", This
);
4108 return DWRITE_OPTICAL_ALIGNMENT_NONE
;
4111 static HRESULT WINAPI
dwritetextformat1_SetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
*fallback
)
4113 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4114 TRACE("(%p)->(%p)\n", This
, fallback
);
4115 return set_fontfallback_for_format(&This
->format
, fallback
);
4118 static HRESULT WINAPI
dwritetextformat1_GetFontFallback(IDWriteTextFormat1
*iface
, IDWriteFontFallback
**fallback
)
4120 struct dwrite_textformat
*This
= impl_from_IDWriteTextFormat1(iface
);
4121 TRACE("(%p)->(%p)\n", This
, fallback
);
4122 return get_fontfallback_from_format(&This
->format
, fallback
);
4125 static const IDWriteTextFormat1Vtbl dwritetextformatvtbl
= {
4126 dwritetextformat_QueryInterface
,
4127 dwritetextformat_AddRef
,
4128 dwritetextformat_Release
,
4129 dwritetextformat_SetTextAlignment
,
4130 dwritetextformat_SetParagraphAlignment
,
4131 dwritetextformat_SetWordWrapping
,
4132 dwritetextformat_SetReadingDirection
,
4133 dwritetextformat_SetFlowDirection
,
4134 dwritetextformat_SetIncrementalTabStop
,
4135 dwritetextformat_SetTrimming
,
4136 dwritetextformat_SetLineSpacing
,
4137 dwritetextformat_GetTextAlignment
,
4138 dwritetextformat_GetParagraphAlignment
,
4139 dwritetextformat_GetWordWrapping
,
4140 dwritetextformat_GetReadingDirection
,
4141 dwritetextformat_GetFlowDirection
,
4142 dwritetextformat_GetIncrementalTabStop
,
4143 dwritetextformat_GetTrimming
,
4144 dwritetextformat_GetLineSpacing
,
4145 dwritetextformat_GetFontCollection
,
4146 dwritetextformat_GetFontFamilyNameLength
,
4147 dwritetextformat_GetFontFamilyName
,
4148 dwritetextformat_GetFontWeight
,
4149 dwritetextformat_GetFontStyle
,
4150 dwritetextformat_GetFontStretch
,
4151 dwritetextformat_GetFontSize
,
4152 dwritetextformat_GetLocaleNameLength
,
4153 dwritetextformat_GetLocaleName
,
4154 dwritetextformat1_SetVerticalGlyphOrientation
,
4155 dwritetextformat1_GetVerticalGlyphOrientation
,
4156 dwritetextformat1_SetLastLineWrapping
,
4157 dwritetextformat1_GetLastLineWrapping
,
4158 dwritetextformat1_SetOpticalAlignment
,
4159 dwritetextformat1_GetOpticalAlignment
,
4160 dwritetextformat1_SetFontFallback
,
4161 dwritetextformat1_GetFontFallback
4164 HRESULT
create_textformat(const WCHAR
*family_name
, IDWriteFontCollection
*collection
, DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STYLE style
,
4165 DWRITE_FONT_STRETCH stretch
, FLOAT size
, const WCHAR
*locale
, IDWriteTextFormat
**format
)
4167 struct dwrite_textformat
*This
;
4171 This
= heap_alloc(sizeof(struct dwrite_textformat
));
4172 if (!This
) return E_OUTOFMEMORY
;
4174 This
->IDWriteTextFormat1_iface
.lpVtbl
= &dwritetextformatvtbl
;
4176 This
->format
.family_name
= heap_strdupW(family_name
);
4177 This
->format
.family_len
= strlenW(family_name
);
4178 This
->format
.locale
= heap_strdupW(locale
);
4179 This
->format
.locale_len
= strlenW(locale
);
4180 This
->format
.weight
= weight
;
4181 This
->format
.style
= style
;
4182 This
->format
.fontsize
= size
;
4183 This
->format
.stretch
= stretch
;
4184 This
->format
.textalignment
= DWRITE_TEXT_ALIGNMENT_LEADING
;
4185 This
->format
.paralign
= DWRITE_PARAGRAPH_ALIGNMENT_NEAR
;
4186 This
->format
.wrapping
= DWRITE_WORD_WRAPPING_WRAP
;
4187 This
->format
.readingdir
= DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
;
4188 This
->format
.flow
= DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
;
4189 This
->format
.spacingmethod
= DWRITE_LINE_SPACING_METHOD_DEFAULT
;
4190 This
->format
.vertical_orientation
= DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT
;
4191 This
->format
.spacing
= 0.0;
4192 This
->format
.baseline
= 0.0;
4193 This
->format
.trimming
.granularity
= DWRITE_TRIMMING_GRANULARITY_NONE
;
4194 This
->format
.trimming
.delimiter
= 0;
4195 This
->format
.trimming
.delimiterCount
= 0;
4196 This
->format
.trimmingsign
= NULL
;
4197 This
->format
.collection
= collection
;
4198 This
->format
.fallback
= NULL
;
4199 IDWriteFontCollection_AddRef(collection
);
4201 *format
= (IDWriteTextFormat
*)&This
->IDWriteTextFormat1_iface
;
4206 static HRESULT WINAPI
dwritetypography_QueryInterface(IDWriteTypography
*iface
, REFIID riid
, void **obj
)
4208 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
4210 TRACE("(%p)->(%s %p)\n", typography
, debugstr_guid(riid
), obj
);
4212 if (IsEqualIID(riid
, &IID_IDWriteTypography
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4214 IDWriteTypography_AddRef(iface
);
4220 return E_NOINTERFACE
;
4223 static ULONG WINAPI
dwritetypography_AddRef(IDWriteTypography
*iface
)
4225 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
4226 ULONG ref
= InterlockedIncrement(&typography
->ref
);
4227 TRACE("(%p)->(%d)\n", typography
, ref
);
4231 static ULONG WINAPI
dwritetypography_Release(IDWriteTypography
*iface
)
4233 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
4234 ULONG ref
= InterlockedDecrement(&typography
->ref
);
4236 TRACE("(%p)->(%d)\n", typography
, ref
);
4239 heap_free(typography
->features
);
4240 heap_free(typography
);
4246 static HRESULT WINAPI
dwritetypography_AddFontFeature(IDWriteTypography
*iface
, DWRITE_FONT_FEATURE feature
)
4248 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
4250 TRACE("(%p)->(%x %u)\n", typography
, feature
.nameTag
, feature
.parameter
);
4252 if (typography
->count
== typography
->allocated
) {
4253 DWRITE_FONT_FEATURE
*ptr
= heap_realloc(typography
->features
, 2*typography
->allocated
*sizeof(DWRITE_FONT_FEATURE
));
4255 return E_OUTOFMEMORY
;
4257 typography
->features
= ptr
;
4258 typography
->allocated
*= 2;
4261 typography
->features
[typography
->count
++] = feature
;
4265 static UINT32 WINAPI
dwritetypography_GetFontFeatureCount(IDWriteTypography
*iface
)
4267 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
4268 TRACE("(%p)\n", typography
);
4269 return typography
->count
;
4272 static HRESULT WINAPI
dwritetypography_GetFontFeature(IDWriteTypography
*iface
, UINT32 index
, DWRITE_FONT_FEATURE
*feature
)
4274 struct dwrite_typography
*typography
= impl_from_IDWriteTypography(iface
);
4276 TRACE("(%p)->(%u %p)\n", typography
, index
, feature
);
4278 if (index
>= typography
->count
)
4279 return E_INVALIDARG
;
4281 *feature
= typography
->features
[index
];
4285 static const IDWriteTypographyVtbl dwritetypographyvtbl
= {
4286 dwritetypography_QueryInterface
,
4287 dwritetypography_AddRef
,
4288 dwritetypography_Release
,
4289 dwritetypography_AddFontFeature
,
4290 dwritetypography_GetFontFeatureCount
,
4291 dwritetypography_GetFontFeature
4294 HRESULT
create_typography(IDWriteTypography
**ret
)
4296 struct dwrite_typography
*typography
;
4300 typography
= heap_alloc(sizeof(*typography
));
4302 return E_OUTOFMEMORY
;
4304 typography
->IDWriteTypography_iface
.lpVtbl
= &dwritetypographyvtbl
;
4305 typography
->ref
= 1;
4306 typography
->allocated
= 2;
4307 typography
->count
= 0;
4309 typography
->features
= heap_alloc(typography
->allocated
*sizeof(DWRITE_FONT_FEATURE
));
4310 if (!typography
->features
) {
4311 heap_free(typography
);
4312 return E_OUTOFMEMORY
;
4315 *ret
= &typography
->IDWriteTypography_iface
;