vkd3d: Disable printf format checks.
[wine.git] / dlls / dwrite / format.c
blob01a6dfd06c9fc01d0cee00e7d2903fbe234078be
1 /*
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
19 #define COBJMACROS
21 #include "dwrite_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
27 struct dwrite_trimmingsign
29 IDWriteInlineObject IDWriteInlineObject_iface;
30 LONG refcount;
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)
42 if (data->collection)
43 IDWriteFontCollection_Release(data->collection);
44 if (data->fallback)
45 IDWriteFontFallback_Release(data->fallback);
46 if (data->trimmingsign)
47 IDWriteInlineObject_Release(data->trimmingsign);
48 free(data->family_name);
49 free(data->locale);
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,
59 BOOL *changed)
61 if ((UINT32)alignment > DWRITE_TEXT_ALIGNMENT_JUSTIFIED)
62 return E_INVALIDARG;
63 if (changed) *changed = format->textalignment != alignment;
64 format->textalignment = alignment;
65 return S_OK;
68 HRESULT format_set_paralignment(struct dwrite_textformat_data *format, DWRITE_PARAGRAPH_ALIGNMENT alignment, BOOL *changed)
70 if ((UINT32)alignment > DWRITE_PARAGRAPH_ALIGNMENT_CENTER)
71 return E_INVALIDARG;
72 if (changed) *changed = format->paralign != alignment;
73 format->paralign = alignment;
74 return S_OK;
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)
80 return E_INVALIDARG;
81 if (changed) *changed = format->readingdir != direction;
82 format->readingdir = direction;
83 return S_OK;
86 HRESULT format_set_wordwrapping(struct dwrite_textformat_data *format, DWRITE_WORD_WRAPPING wrapping, BOOL *changed)
88 if ((UINT32)wrapping > DWRITE_WORD_WRAPPING_CHARACTER)
89 return E_INVALIDARG;
90 if (changed) *changed = format->wrapping != wrapping;
91 format->wrapping = wrapping;
92 return S_OK;
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)
98 return E_INVALIDARG;
99 if (changed) *changed = format->flow != direction;
100 format->flow = direction;
101 return S_OK;
104 HRESULT format_set_trimming(struct dwrite_textformat_data *format, DWRITE_TRIMMING const *trimming,
105 IDWriteInlineObject *trimming_sign, BOOL *changed)
107 if (changed)
108 *changed = FALSE;
110 if ((UINT32)trimming->granularity > DWRITE_TRIMMING_GRANULARITY_WORD)
111 return E_INVALIDARG;
113 if (changed) {
114 *changed = !!memcmp(&format->trimming, trimming, sizeof(*trimming));
115 if (format->trimmingsign != trimming_sign)
116 *changed = TRUE;
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);
125 return S_OK;
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)
132 return E_INVALIDARG;
134 if (changed)
135 *changed = memcmp(spacing, &format->spacing, sizeof(*spacing));
137 format->spacing = *spacing;
138 return S_OK;
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;
148 if (num_values)
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;
156 return S_OK;
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));
165 return S_OK;
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));
173 return S_OK;
176 HRESULT format_get_fontfallback(const struct dwrite_textformat_data *format, IDWriteFontFallback **fallback)
178 *fallback = format->fallback;
179 if (*fallback)
180 IDWriteFontFallback_AddRef(*fallback);
181 return S_OK;
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;
189 if (fallback)
190 IDWriteFontFallback_AddRef(fallback);
191 return S_OK;
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)
197 return E_INVALIDARG;
198 format->optical_alignment = alignment;
199 return S_OK;
202 HRESULT format_set_vertical_orientation(struct dwrite_textformat_data *format, DWRITE_VERTICAL_GLYPH_ORIENTATION orientation,
203 BOOL *changed)
205 if ((UINT32)orientation > DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED)
206 return E_INVALIDARG;
208 if (changed)
209 *changed = format->vertical_orientation != orientation;
211 format->vertical_orientation = orientation;
212 return S_OK;
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))
225 *obj = iface;
226 IDWriteTextFormat3_AddRef(iface);
227 return S_OK;
230 WARN("%s not implemented.\n", debugstr_guid(riid));
232 *obj = NULL;
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);
244 return 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);
254 if (!refcount)
256 release_format_data(&format->format);
257 free(format);
260 return refcount;
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);
315 if (tabstop <= 0.0f)
316 return E_INVALIDARG;
318 format->format.tabstop = tabstop;
319 return S_OK;
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);
413 return S_OK;
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;
426 return S_OK;
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);
438 return S_OK;
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);
459 return S_OK;
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);
516 return S_OK;
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;
545 return S_OK;
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;
609 return S_OK;
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;
658 return S_OK;
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;
719 HRESULT hr;
721 *out = NULL;
723 if (size <= 0.0f)
724 return E_INVALIDARG;
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)
731 return E_INVALIDARG;
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);
757 return hr;
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)) {
765 *obj = iface;
766 IDWriteInlineObject_AddRef(iface);
767 return S_OK;
770 WARN("%s not implemented.\n", debugstr_guid(riid));
772 *obj = NULL;
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);
783 return 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);
793 if (!refcount)
795 IDWriteTextLayout_Release(sign->layout);
796 free(sign);
799 return refcount;
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;
807 UINT32 line_count;
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;
820 HRESULT hr;
822 TRACE("%p, %p.\n", iface, ret);
824 hr = IDWriteTextLayout_GetMetrics(sign->layout, &metrics);
825 if (FAILED(hr))
827 memset(ret, 0, sizeof(*ret));
828 return hr;
831 ret->width = metrics.width;
832 ret->height = 0.0f;
833 ret->baseline = 0.0f;
834 ret->supportsSideways = FALSE;
835 return S_OK;
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;
853 return S_OK;
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;
896 HRESULT hr;
898 *sign = NULL;
900 if (!format)
901 return E_INVALIDARG;
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);
919 if (FAILED(hr))
921 free(object);
922 return hr;
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;
931 return S_OK;