2 * Copyright 2012, 2014-2022 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "dwrite_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
27 struct dwrite_trimmingsign
29 IDWriteInlineObject IDWriteInlineObject_iface
;
32 IDWriteTextLayout
*layout
;
35 static inline struct dwrite_trimmingsign
*impl_from_IDWriteInlineObject(IDWriteInlineObject
*iface
)
37 return CONTAINING_RECORD(iface
, struct dwrite_trimmingsign
, IDWriteInlineObject_iface
);
40 void release_format_data(struct dwrite_textformat_data
*data
)
43 IDWriteFontCollection_Release(data
->collection
);
45 IDWriteFontFallback_Release(data
->fallback
);
46 if (data
->trimmingsign
)
47 IDWriteInlineObject_Release(data
->trimmingsign
);
48 free(data
->family_name
);
50 free(data
->axis_values
);
53 static inline struct dwrite_textformat
*impl_from_IDWriteTextFormat3(IDWriteTextFormat3
*iface
)
55 return CONTAINING_RECORD(iface
, struct dwrite_textformat
, IDWriteTextFormat3_iface
);
58 HRESULT
format_set_textalignment(struct dwrite_textformat_data
*format
, DWRITE_TEXT_ALIGNMENT alignment
,
61 if ((UINT32
)alignment
> DWRITE_TEXT_ALIGNMENT_JUSTIFIED
)
63 if (changed
) *changed
= format
->textalignment
!= alignment
;
64 format
->textalignment
= alignment
;
68 HRESULT
format_set_paralignment(struct dwrite_textformat_data
*format
, DWRITE_PARAGRAPH_ALIGNMENT alignment
, BOOL
*changed
)
70 if ((UINT32
)alignment
> DWRITE_PARAGRAPH_ALIGNMENT_CENTER
)
72 if (changed
) *changed
= format
->paralign
!= alignment
;
73 format
->paralign
= alignment
;
77 HRESULT
format_set_readingdirection(struct dwrite_textformat_data
*format
, DWRITE_READING_DIRECTION direction
, BOOL
*changed
)
79 if ((UINT32
)direction
> DWRITE_READING_DIRECTION_BOTTOM_TO_TOP
)
81 if (changed
) *changed
= format
->readingdir
!= direction
;
82 format
->readingdir
= direction
;
86 HRESULT
format_set_wordwrapping(struct dwrite_textformat_data
*format
, DWRITE_WORD_WRAPPING wrapping
, BOOL
*changed
)
88 if ((UINT32
)wrapping
> DWRITE_WORD_WRAPPING_CHARACTER
)
90 if (changed
) *changed
= format
->wrapping
!= wrapping
;
91 format
->wrapping
= wrapping
;
95 HRESULT
format_set_flowdirection(struct dwrite_textformat_data
*format
, DWRITE_FLOW_DIRECTION direction
, BOOL
*changed
)
97 if ((UINT32
)direction
> DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT
)
99 if (changed
) *changed
= format
->flow
!= direction
;
100 format
->flow
= direction
;
104 HRESULT
format_set_trimming(struct dwrite_textformat_data
*format
, DWRITE_TRIMMING
const *trimming
,
105 IDWriteInlineObject
*trimming_sign
, BOOL
*changed
)
110 if ((UINT32
)trimming
->granularity
> DWRITE_TRIMMING_GRANULARITY_WORD
)
114 *changed
= !!memcmp(&format
->trimming
, trimming
, sizeof(*trimming
));
115 if (format
->trimmingsign
!= trimming_sign
)
119 format
->trimming
= *trimming
;
120 if (format
->trimmingsign
)
121 IDWriteInlineObject_Release(format
->trimmingsign
);
122 format
->trimmingsign
= trimming_sign
;
123 if (format
->trimmingsign
)
124 IDWriteInlineObject_AddRef(format
->trimmingsign
);
128 HRESULT
format_set_linespacing(struct dwrite_textformat_data
*format
, DWRITE_LINE_SPACING
const *spacing
, BOOL
*changed
)
130 if (spacing
->height
< 0.0f
|| spacing
->leadingBefore
< 0.0f
|| spacing
->leadingBefore
> 1.0f
||
131 (UINT32
)spacing
->method
> DWRITE_LINE_SPACING_METHOD_PROPORTIONAL
)
135 *changed
= memcmp(spacing
, &format
->spacing
, sizeof(*spacing
));
137 format
->spacing
= *spacing
;
141 HRESULT
format_set_font_axisvalues(struct dwrite_textformat_data
*format
, DWRITE_FONT_AXIS_VALUE
const *axis_values
,
142 unsigned int num_values
)
144 free(format
->axis_values
);
145 format
->axis_values
= NULL
;
146 format
->axis_values_count
= 0;
150 if (!(format
->axis_values
= calloc(num_values
, sizeof(*axis_values
))))
151 return E_OUTOFMEMORY
;
152 memcpy(format
->axis_values
, axis_values
, num_values
* sizeof(*axis_values
));
153 format
->axis_values_count
= num_values
;
159 HRESULT
format_get_font_axisvalues(struct dwrite_textformat_data
*format
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
160 unsigned int num_values
)
162 if (!format
->axis_values_count
)
164 if (num_values
) memset(axis_values
, 0, num_values
* sizeof(*axis_values
));
168 if (num_values
< format
->axis_values_count
)
169 return E_NOT_SUFFICIENT_BUFFER
;
171 memcpy(axis_values
, format
->axis_values
, min(num_values
, format
->axis_values_count
) * sizeof(*axis_values
));
176 HRESULT
format_get_fontfallback(const struct dwrite_textformat_data
*format
, IDWriteFontFallback
**fallback
)
178 *fallback
= format
->fallback
;
180 IDWriteFontFallback_AddRef(*fallback
);
184 HRESULT
format_set_fontfallback(struct dwrite_textformat_data
*format
, IDWriteFontFallback
*fallback
)
186 if (format
->fallback
)
187 IDWriteFontFallback_Release(format
->fallback
);
188 format
->fallback
= fallback
;
190 IDWriteFontFallback_AddRef(fallback
);
194 HRESULT
format_set_optical_alignment(struct dwrite_textformat_data
*format
, DWRITE_OPTICAL_ALIGNMENT alignment
)
196 if ((UINT32
)alignment
> DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS
)
198 format
->optical_alignment
= alignment
;
202 HRESULT
format_set_vertical_orientation(struct dwrite_textformat_data
*format
, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
,
205 if ((UINT32
)orientation
> DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED
)
209 *changed
= format
->vertical_orientation
!= orientation
;
211 format
->vertical_orientation
= orientation
;
215 static HRESULT WINAPI
dwritetextformat_QueryInterface(IDWriteTextFormat3
*iface
, REFIID riid
, void **obj
)
217 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
219 if (IsEqualIID(riid
, &IID_IDWriteTextFormat3
) ||
220 IsEqualIID(riid
, &IID_IDWriteTextFormat2
) ||
221 IsEqualIID(riid
, &IID_IDWriteTextFormat1
) ||
222 IsEqualIID(riid
, &IID_IDWriteTextFormat
) ||
223 IsEqualIID(riid
, &IID_IUnknown
))
226 IDWriteTextFormat3_AddRef(iface
);
230 WARN("%s not implemented.\n", debugstr_guid(riid
));
234 return E_NOINTERFACE
;
237 static ULONG WINAPI
dwritetextformat_AddRef(IDWriteTextFormat3
*iface
)
239 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
240 ULONG refcount
= InterlockedIncrement(&format
->refcount
);
242 TRACE("%p, refcount %ld.\n", iface
, refcount
);
247 static ULONG WINAPI
dwritetextformat_Release(IDWriteTextFormat3
*iface
)
249 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
250 ULONG refcount
= InterlockedDecrement(&format
->refcount
);
252 TRACE("%p, refcount %ld.\n", iface
, refcount
);
256 release_format_data(&format
->format
);
263 static HRESULT WINAPI
dwritetextformat_SetTextAlignment(IDWriteTextFormat3
*iface
, DWRITE_TEXT_ALIGNMENT alignment
)
265 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
267 TRACE("%p, %d.\n", iface
, alignment
);
269 return format_set_textalignment(&format
->format
, alignment
, NULL
);
272 static HRESULT WINAPI
dwritetextformat_SetParagraphAlignment(IDWriteTextFormat3
*iface
,
273 DWRITE_PARAGRAPH_ALIGNMENT alignment
)
275 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
277 TRACE("%p, %d.\n", iface
, alignment
);
279 return format_set_paralignment(&format
->format
, alignment
, NULL
);
282 static HRESULT WINAPI
dwritetextformat_SetWordWrapping(IDWriteTextFormat3
*iface
, DWRITE_WORD_WRAPPING wrapping
)
284 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
286 TRACE("%p, %d.\n", iface
, wrapping
);
288 return format_set_wordwrapping(&format
->format
, wrapping
, NULL
);
291 static HRESULT WINAPI
dwritetextformat_SetReadingDirection(IDWriteTextFormat3
*iface
, DWRITE_READING_DIRECTION direction
)
293 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
295 TRACE("%p, %d.\n", iface
, direction
);
297 return format_set_readingdirection(&format
->format
, direction
, NULL
);
300 static HRESULT WINAPI
dwritetextformat_SetFlowDirection(IDWriteTextFormat3
*iface
, DWRITE_FLOW_DIRECTION direction
)
302 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
304 TRACE("%p, %d.\n", iface
, direction
);
306 return format_set_flowdirection(&format
->format
, direction
, NULL
);
309 static HRESULT WINAPI
dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat3
*iface
, float tabstop
)
311 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
313 TRACE("%p, %f.\n", iface
, tabstop
);
318 format
->format
.tabstop
= tabstop
;
322 static HRESULT WINAPI
dwritetextformat_SetTrimming(IDWriteTextFormat3
*iface
, DWRITE_TRIMMING
const *trimming
,
323 IDWriteInlineObject
*trimming_sign
)
325 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
327 TRACE("%p, %p, %p.\n", iface
, trimming
, trimming_sign
);
329 return format_set_trimming(&format
->format
, trimming
, trimming_sign
, NULL
);
332 static HRESULT WINAPI
dwritetextformat_SetLineSpacing(IDWriteTextFormat3
*iface
, DWRITE_LINE_SPACING_METHOD method
,
333 float height
, float baseline
)
335 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
336 DWRITE_LINE_SPACING spacing
;
338 TRACE("%p, %d, %f, %f.\n", iface
, method
, height
, baseline
);
340 spacing
= format
->format
.spacing
;
341 spacing
.method
= method
;
342 spacing
.height
= height
;
343 spacing
.baseline
= baseline
;
345 return format_set_linespacing(&format
->format
, &spacing
, NULL
);
348 static DWRITE_TEXT_ALIGNMENT WINAPI
dwritetextformat_GetTextAlignment(IDWriteTextFormat3
*iface
)
350 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
352 TRACE("%p.\n", iface
);
354 return format
->format
.textalignment
;
357 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI
dwritetextformat_GetParagraphAlignment(IDWriteTextFormat3
*iface
)
359 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
361 TRACE("%p.\n", iface
);
363 return format
->format
.paralign
;
366 static DWRITE_WORD_WRAPPING WINAPI
dwritetextformat_GetWordWrapping(IDWriteTextFormat3
*iface
)
368 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
370 TRACE("%p.\n", iface
);
372 return format
->format
.wrapping
;
375 static DWRITE_READING_DIRECTION WINAPI
dwritetextformat_GetReadingDirection(IDWriteTextFormat3
*iface
)
377 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
379 TRACE("%p.\n", iface
);
381 return format
->format
.readingdir
;
384 static DWRITE_FLOW_DIRECTION WINAPI
dwritetextformat_GetFlowDirection(IDWriteTextFormat3
*iface
)
386 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
388 TRACE("%p.\n", iface
);
390 return format
->format
.flow
;
393 static float WINAPI
dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat3
*iface
)
395 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
397 TRACE("%p.\n", iface
);
399 return format
->format
.tabstop
;
402 static HRESULT WINAPI
dwritetextformat_GetTrimming(IDWriteTextFormat3
*iface
, DWRITE_TRIMMING
*options
,
403 IDWriteInlineObject
**trimming_sign
)
405 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
407 TRACE("%p, %p, %p.\n", iface
, options
, trimming_sign
);
409 *options
= format
->format
.trimming
;
410 if ((*trimming_sign
= format
->format
.trimmingsign
))
411 IDWriteInlineObject_AddRef(*trimming_sign
);
416 static HRESULT WINAPI
dwritetextformat_GetLineSpacing(IDWriteTextFormat3
*iface
, DWRITE_LINE_SPACING_METHOD
*method
,
417 float *spacing
, float *baseline
)
419 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
421 TRACE("%p, %p, %p, %p.\n", iface
, method
, spacing
, baseline
);
423 *method
= format
->format
.spacing
.method
;
424 *spacing
= format
->format
.spacing
.height
;
425 *baseline
= format
->format
.spacing
.baseline
;
429 static HRESULT WINAPI
dwritetextformat_GetFontCollection(IDWriteTextFormat3
*iface
, IDWriteFontCollection
**collection
)
431 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
433 TRACE("%p, %p.\n", iface
, collection
);
435 *collection
= format
->format
.collection
;
436 IDWriteFontCollection_AddRef(*collection
);
441 static UINT32 WINAPI
dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat3
*iface
)
443 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
445 TRACE("%p.\n", iface
);
447 return format
->format
.family_len
;
450 static HRESULT WINAPI
dwritetextformat_GetFontFamilyName(IDWriteTextFormat3
*iface
, WCHAR
*name
, UINT32 size
)
452 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
454 TRACE("%p, %p, %u.\n", iface
, name
, size
);
456 if (size
<= format
->format
.family_len
)
457 return E_NOT_SUFFICIENT_BUFFER
;
458 wcscpy(name
, format
->format
.family_name
);
462 static DWRITE_FONT_WEIGHT WINAPI
dwritetextformat_GetFontWeight(IDWriteTextFormat3
*iface
)
464 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
466 TRACE("%p.\n", iface
);
468 return format
->format
.weight
;
471 static DWRITE_FONT_STYLE WINAPI
dwritetextformat_GetFontStyle(IDWriteTextFormat3
*iface
)
473 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
475 TRACE("%p.\n", iface
);
477 return format
->format
.style
;
480 static DWRITE_FONT_STRETCH WINAPI
dwritetextformat_GetFontStretch(IDWriteTextFormat3
*iface
)
482 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
484 TRACE("%p.\n", iface
);
486 return format
->format
.stretch
;
489 static float WINAPI
dwritetextformat_GetFontSize(IDWriteTextFormat3
*iface
)
491 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
493 TRACE("%p.\n", iface
);
495 return format
->format
.fontsize
;
498 static UINT32 WINAPI
dwritetextformat_GetLocaleNameLength(IDWriteTextFormat3
*iface
)
500 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
502 TRACE("%p.\n", iface
);
504 return format
->format
.locale_len
;
507 static HRESULT WINAPI
dwritetextformat_GetLocaleName(IDWriteTextFormat3
*iface
, WCHAR
*name
, UINT32 size
)
509 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
511 TRACE("%p, %p %u.\n", iface
, name
, size
);
513 if (size
<= format
->format
.locale_len
)
514 return E_NOT_SUFFICIENT_BUFFER
;
515 wcscpy(name
, format
->format
.locale
);
519 static HRESULT WINAPI
dwritetextformat1_SetVerticalGlyphOrientation(IDWriteTextFormat3
*iface
,
520 DWRITE_VERTICAL_GLYPH_ORIENTATION orientation
)
522 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
524 TRACE("%p, %d.\n", iface
, orientation
);
526 return format_set_vertical_orientation(&format
->format
, orientation
, NULL
);
529 static DWRITE_VERTICAL_GLYPH_ORIENTATION WINAPI
dwritetextformat1_GetVerticalGlyphOrientation(IDWriteTextFormat3
*iface
)
531 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
533 TRACE("%p.\n", iface
);
535 return format
->format
.vertical_orientation
;
538 static HRESULT WINAPI
dwritetextformat1_SetLastLineWrapping(IDWriteTextFormat3
*iface
, BOOL lastline_wrapping_enabled
)
540 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
542 TRACE("%p, %d.\n", iface
, lastline_wrapping_enabled
);
544 format
->format
.last_line_wrapping
= !!lastline_wrapping_enabled
;
548 static BOOL WINAPI
dwritetextformat1_GetLastLineWrapping(IDWriteTextFormat3
*iface
)
550 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
552 TRACE("%p.\n", iface
);
554 return format
->format
.last_line_wrapping
;
557 static HRESULT WINAPI
dwritetextformat1_SetOpticalAlignment(IDWriteTextFormat3
*iface
, DWRITE_OPTICAL_ALIGNMENT alignment
)
559 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
561 TRACE("%p, %d.\n", iface
, alignment
);
563 return format_set_optical_alignment(&format
->format
, alignment
);
566 static DWRITE_OPTICAL_ALIGNMENT WINAPI
dwritetextformat1_GetOpticalAlignment(IDWriteTextFormat3
*iface
)
568 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
570 TRACE("%p.\n", iface
);
572 return format
->format
.optical_alignment
;
575 static HRESULT WINAPI
dwritetextformat1_SetFontFallback(IDWriteTextFormat3
*iface
, IDWriteFontFallback
*fallback
)
577 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
579 TRACE("%p, %p.\n", iface
, fallback
);
581 return format_set_fontfallback(&format
->format
, fallback
);
584 static HRESULT WINAPI
dwritetextformat1_GetFontFallback(IDWriteTextFormat3
*iface
, IDWriteFontFallback
**fallback
)
586 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
588 TRACE("%p, %p.\n", iface
, fallback
);
590 return format_get_fontfallback(&format
->format
, fallback
);
593 static HRESULT WINAPI
dwritetextformat2_SetLineSpacing(IDWriteTextFormat3
*iface
, DWRITE_LINE_SPACING
const *spacing
)
595 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
597 TRACE("%p, %p.\n", iface
, spacing
);
599 return format_set_linespacing(&format
->format
, spacing
, NULL
);
602 static HRESULT WINAPI
dwritetextformat2_GetLineSpacing(IDWriteTextFormat3
*iface
, DWRITE_LINE_SPACING
*spacing
)
604 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
606 TRACE("%p, %p.\n", iface
, spacing
);
608 *spacing
= format
->format
.spacing
;
612 static HRESULT WINAPI
dwritetextformat3_SetFontAxisValues(IDWriteTextFormat3
*iface
,
613 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
)
615 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
617 TRACE("%p, %p, %u.\n", iface
, axis_values
, num_values
);
619 return format_set_font_axisvalues(&format
->format
, axis_values
, num_values
);
622 static UINT32 WINAPI
dwritetextformat3_GetFontAxisValueCount(IDWriteTextFormat3
*iface
)
624 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
626 TRACE("%p.\n", iface
);
628 return format
->format
.axis_values_count
;
631 static HRESULT WINAPI
dwritetextformat3_GetFontAxisValues(IDWriteTextFormat3
*iface
,
632 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 num_values
)
634 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
636 TRACE("%p, %p, %u.\n", iface
, axis_values
, num_values
);
638 return format_get_font_axisvalues(&format
->format
, axis_values
, num_values
);
641 static DWRITE_AUTOMATIC_FONT_AXES WINAPI
dwritetextformat3_GetAutomaticFontAxes(IDWriteTextFormat3
*iface
)
643 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
645 TRACE("%p.\n", iface
);
647 return format
->format
.automatic_axes
;
650 static HRESULT WINAPI
dwritetextformat3_SetAutomaticFontAxes(IDWriteTextFormat3
*iface
, DWRITE_AUTOMATIC_FONT_AXES axes
)
652 struct dwrite_textformat
*format
= impl_from_IDWriteTextFormat3(iface
);
654 TRACE("%p, %d.\n", iface
, axes
);
656 format
->format
.automatic_axes
= axes
;
661 static const IDWriteTextFormat3Vtbl dwritetextformatvtbl
=
663 dwritetextformat_QueryInterface
,
664 dwritetextformat_AddRef
,
665 dwritetextformat_Release
,
666 dwritetextformat_SetTextAlignment
,
667 dwritetextformat_SetParagraphAlignment
,
668 dwritetextformat_SetWordWrapping
,
669 dwritetextformat_SetReadingDirection
,
670 dwritetextformat_SetFlowDirection
,
671 dwritetextformat_SetIncrementalTabStop
,
672 dwritetextformat_SetTrimming
,
673 dwritetextformat_SetLineSpacing
,
674 dwritetextformat_GetTextAlignment
,
675 dwritetextformat_GetParagraphAlignment
,
676 dwritetextformat_GetWordWrapping
,
677 dwritetextformat_GetReadingDirection
,
678 dwritetextformat_GetFlowDirection
,
679 dwritetextformat_GetIncrementalTabStop
,
680 dwritetextformat_GetTrimming
,
681 dwritetextformat_GetLineSpacing
,
682 dwritetextformat_GetFontCollection
,
683 dwritetextformat_GetFontFamilyNameLength
,
684 dwritetextformat_GetFontFamilyName
,
685 dwritetextformat_GetFontWeight
,
686 dwritetextformat_GetFontStyle
,
687 dwritetextformat_GetFontStretch
,
688 dwritetextformat_GetFontSize
,
689 dwritetextformat_GetLocaleNameLength
,
690 dwritetextformat_GetLocaleName
,
691 dwritetextformat1_SetVerticalGlyphOrientation
,
692 dwritetextformat1_GetVerticalGlyphOrientation
,
693 dwritetextformat1_SetLastLineWrapping
,
694 dwritetextformat1_GetLastLineWrapping
,
695 dwritetextformat1_SetOpticalAlignment
,
696 dwritetextformat1_GetOpticalAlignment
,
697 dwritetextformat1_SetFontFallback
,
698 dwritetextformat1_GetFontFallback
,
699 dwritetextformat2_SetLineSpacing
,
700 dwritetextformat2_GetLineSpacing
,
701 dwritetextformat3_SetFontAxisValues
,
702 dwritetextformat3_GetFontAxisValueCount
,
703 dwritetextformat3_GetFontAxisValues
,
704 dwritetextformat3_GetAutomaticFontAxes
,
705 dwritetextformat3_SetAutomaticFontAxes
,
708 struct dwrite_textformat
*unsafe_impl_from_IDWriteTextFormat(IDWriteTextFormat
*iface
)
710 return (iface
->lpVtbl
== (IDWriteTextFormatVtbl
*)&dwritetextformatvtbl
) ?
711 CONTAINING_RECORD(iface
, struct dwrite_textformat
, IDWriteTextFormat3_iface
) : NULL
;
714 HRESULT
create_text_format(const WCHAR
*family_name
, IDWriteFontCollection
*collection
, DWRITE_FONT_WEIGHT weight
,
715 DWRITE_FONT_STYLE style
, DWRITE_FONT_STRETCH stretch
, float size
, const WCHAR
*locale
,
716 REFIID riid
, void **out
)
718 struct dwrite_textformat
*object
;
726 if ((UINT32
)weight
> DWRITE_FONT_WEIGHT_ULTRA_BLACK
727 || stretch
== DWRITE_FONT_STRETCH_UNDEFINED
728 || (UINT32
)stretch
> DWRITE_FONT_STRETCH_ULTRA_EXPANDED
729 || (UINT32
)style
> DWRITE_FONT_STYLE_ITALIC
)
734 if (!(object
= calloc(1, sizeof(*object
))))
735 return E_OUTOFMEMORY
;
737 object
->IDWriteTextFormat3_iface
.lpVtbl
= &dwritetextformatvtbl
;
738 object
->refcount
= 1;
739 object
->format
.family_name
= wcsdup(family_name
);
740 object
->format
.family_len
= wcslen(family_name
);
741 object
->format
.locale
= wcsdup(locale
);
742 object
->format
.locale_len
= wcslen(locale
);
743 /* Force locale name to lower case, layout will inherit this modified value. */
744 wcslwr(object
->format
.locale
);
745 object
->format
.weight
= weight
;
746 object
->format
.style
= style
;
747 object
->format
.fontsize
= size
;
748 object
->format
.tabstop
= 4.0f
* size
;
749 object
->format
.stretch
= stretch
;
750 object
->format
.last_line_wrapping
= TRUE
;
751 object
->format
.collection
= collection
;
752 IDWriteFontCollection_AddRef(object
->format
.collection
);
754 hr
= IDWriteTextFormat3_QueryInterface(&object
->IDWriteTextFormat3_iface
, riid
, out
);
755 IDWriteTextFormat3_Release(&object
->IDWriteTextFormat3_iface
);
760 static HRESULT WINAPI
dwritetrimmingsign_QueryInterface(IDWriteInlineObject
*iface
, REFIID riid
, void **obj
)
762 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
764 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteInlineObject
)) {
766 IDWriteInlineObject_AddRef(iface
);
770 WARN("%s not implemented.\n", debugstr_guid(riid
));
773 return E_NOINTERFACE
;
776 static ULONG WINAPI
dwritetrimmingsign_AddRef(IDWriteInlineObject
*iface
)
778 struct dwrite_trimmingsign
*sign
= impl_from_IDWriteInlineObject(iface
);
779 ULONG refcount
= InterlockedIncrement(&sign
->refcount
);
781 TRACE("%p, refcount %ld.\n", iface
, refcount
);
786 static ULONG WINAPI
dwritetrimmingsign_Release(IDWriteInlineObject
*iface
)
788 struct dwrite_trimmingsign
*sign
= impl_from_IDWriteInlineObject(iface
);
789 ULONG refcount
= InterlockedDecrement(&sign
->refcount
);
791 TRACE("%p, refcount %ld.\n", iface
, refcount
);
795 IDWriteTextLayout_Release(sign
->layout
);
802 static HRESULT WINAPI
dwritetrimmingsign_Draw(IDWriteInlineObject
*iface
, void *context
, IDWriteTextRenderer
*renderer
,
803 float originX
, float originY
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*effect
)
805 struct dwrite_trimmingsign
*sign
= impl_from_IDWriteInlineObject(iface
);
806 DWRITE_LINE_METRICS line
;
809 TRACE("%p, %p, %p, %.2f, %.2f, %d, %d, %p.\n", iface
, context
, renderer
, originX
, originY
,
810 is_sideways
, is_rtl
, effect
);
812 IDWriteTextLayout_GetLineMetrics(sign
->layout
, &line
, 1, &line_count
);
813 return IDWriteTextLayout_Draw(sign
->layout
, context
, renderer
, originX
, originY
- line
.baseline
);
816 static HRESULT WINAPI
dwritetrimmingsign_GetMetrics(IDWriteInlineObject
*iface
, DWRITE_INLINE_OBJECT_METRICS
*ret
)
818 struct dwrite_trimmingsign
*sign
= impl_from_IDWriteInlineObject(iface
);
819 DWRITE_TEXT_METRICS metrics
;
822 TRACE("%p, %p.\n", iface
, ret
);
824 hr
= IDWriteTextLayout_GetMetrics(sign
->layout
, &metrics
);
827 memset(ret
, 0, sizeof(*ret
));
831 ret
->width
= metrics
.width
;
833 ret
->baseline
= 0.0f
;
834 ret
->supportsSideways
= FALSE
;
838 static HRESULT WINAPI
dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject
*iface
, DWRITE_OVERHANG_METRICS
*overhangs
)
840 struct dwrite_trimmingsign
*sign
= impl_from_IDWriteInlineObject(iface
);
842 TRACE("%p, %p.\n", iface
, overhangs
);
844 return IDWriteTextLayout_GetOverhangMetrics(sign
->layout
, overhangs
);
847 static HRESULT WINAPI
dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject
*iface
, DWRITE_BREAK_CONDITION
*before
,
848 DWRITE_BREAK_CONDITION
*after
)
850 TRACE("%p, %p, %p.\n", iface
, before
, after
);
852 *before
= *after
= DWRITE_BREAK_CONDITION_NEUTRAL
;
856 static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl
=
858 dwritetrimmingsign_QueryInterface
,
859 dwritetrimmingsign_AddRef
,
860 dwritetrimmingsign_Release
,
861 dwritetrimmingsign_Draw
,
862 dwritetrimmingsign_GetMetrics
,
863 dwritetrimmingsign_GetOverhangMetrics
,
864 dwritetrimmingsign_GetBreakConditions
867 static inline BOOL
is_reading_direction_horz(DWRITE_READING_DIRECTION direction
)
869 return (direction
== DWRITE_READING_DIRECTION_LEFT_TO_RIGHT
) ||
870 (direction
== DWRITE_READING_DIRECTION_RIGHT_TO_LEFT
);
873 static inline BOOL
is_reading_direction_vert(DWRITE_READING_DIRECTION direction
)
875 return (direction
== DWRITE_READING_DIRECTION_TOP_TO_BOTTOM
) ||
876 (direction
== DWRITE_READING_DIRECTION_BOTTOM_TO_TOP
);
879 static inline BOOL
is_flow_direction_horz(DWRITE_FLOW_DIRECTION direction
)
881 return (direction
== DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT
) ||
882 (direction
== DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT
);
885 static inline BOOL
is_flow_direction_vert(DWRITE_FLOW_DIRECTION direction
)
887 return (direction
== DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM
) ||
888 (direction
== DWRITE_FLOW_DIRECTION_BOTTOM_TO_TOP
);
891 HRESULT
create_trimmingsign(IDWriteFactory7
*factory
, IDWriteTextFormat
*format
, IDWriteInlineObject
**sign
)
893 struct dwrite_trimmingsign
*object
;
894 DWRITE_READING_DIRECTION reading
;
895 DWRITE_FLOW_DIRECTION flow
;
903 /* Validate reading/flow direction here, layout creation won't complain about
904 invalid combinations. */
905 reading
= IDWriteTextFormat_GetReadingDirection(format
);
906 flow
= IDWriteTextFormat_GetFlowDirection(format
);
908 if ((is_reading_direction_horz(reading
) && is_flow_direction_horz(flow
)) ||
909 (is_reading_direction_vert(reading
) && is_flow_direction_vert(flow
)))
910 return DWRITE_E_FLOWDIRECTIONCONFLICTS
;
912 if (!(object
= calloc(1, sizeof(*object
))))
913 return E_OUTOFMEMORY
;
915 object
->IDWriteInlineObject_iface
.lpVtbl
= &dwritetrimmingsignvtbl
;
916 object
->refcount
= 1;
918 hr
= IDWriteFactory7_CreateTextLayout(factory
, L
"\x2026", 1, format
, 0.0f
, 0.0f
, &object
->layout
);
925 IDWriteTextLayout_SetWordWrapping(object
->layout
, DWRITE_WORD_WRAPPING_NO_WRAP
);
926 IDWriteTextLayout_SetParagraphAlignment(object
->layout
, DWRITE_PARAGRAPH_ALIGNMENT_NEAR
);
927 IDWriteTextLayout_SetTextAlignment(object
->layout
, DWRITE_TEXT_ALIGNMENT_LEADING
);
929 *sign
= &object
->IDWriteInlineObject_iface
;