advapi32: Close hTemp on error (Coverity).
[wine] / dlls / dwrite / layout.c
1 /*
2  *    Text format and layout
3  *
4  * Copyright 2012 Nikolay Sivov for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #define COBJMACROS
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "dwrite.h"
29 #include "dwrite_private.h"
30
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
34
35 struct dwrite_textformat_data {
36     WCHAR *family_name;
37     UINT32 family_len;
38     WCHAR *locale;
39     UINT32 locale_len;
40
41     DWRITE_FONT_WEIGHT weight;
42     DWRITE_FONT_STYLE style;
43     DWRITE_FONT_STRETCH stretch;
44
45     FLOAT size;
46
47     IDWriteFontCollection *collection;
48 };
49
50 struct dwrite_textlayout {
51     IDWriteTextLayout IDWriteTextLayout_iface;
52     LONG ref;
53
54     WCHAR *str;
55     UINT32 len;
56     struct dwrite_textformat_data format;
57 };
58
59 struct dwrite_textformat {
60     IDWriteTextFormat IDWriteTextFormat_iface;
61     LONG ref;
62     struct dwrite_textformat_data format;
63 };
64
65 static const IDWriteTextFormatVtbl dwritetextformatvtbl;
66
67 static void release_format_data(struct dwrite_textformat_data *data)
68 {
69     if (data->collection) IDWriteFontCollection_Release(data->collection);
70     heap_free(data->family_name);
71     heap_free(data->locale);
72 }
73
74 static inline struct dwrite_textlayout *impl_from_IDWriteTextLayout(IDWriteTextLayout *iface)
75 {
76     return CONTAINING_RECORD(iface, struct dwrite_textlayout, IDWriteTextLayout_iface);
77 }
78
79 static inline struct dwrite_textformat *impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
80 {
81     return CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat_iface);
82 }
83
84 static inline struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat(IDWriteTextFormat *iface)
85 {
86     return iface->lpVtbl == &dwritetextformatvtbl ? impl_from_IDWriteTextFormat(iface) : NULL;
87 }
88
89 static HRESULT WINAPI dwritetextlayout_QueryInterface(IDWriteTextLayout *iface, REFIID riid, void **obj)
90 {
91     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
92
93     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
94
95     if (IsEqualIID(riid, &IID_IUnknown) ||
96         IsEqualIID(riid, &IID_IDWriteTextFormat) ||
97         IsEqualIID(riid, &IID_IDWriteTextLayout))
98     {
99         *obj = iface;
100         IDWriteTextLayout_AddRef(iface);
101         return S_OK;
102     }
103
104     *obj = NULL;
105
106     return E_NOINTERFACE;
107 }
108
109 static ULONG WINAPI dwritetextlayout_AddRef(IDWriteTextLayout *iface)
110 {
111     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
112     ULONG ref = InterlockedIncrement(&This->ref);
113     TRACE("(%p)->(%d)\n", This, ref);
114     return ref;
115 }
116
117 static ULONG WINAPI dwritetextlayout_Release(IDWriteTextLayout *iface)
118 {
119     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
120     ULONG ref = InterlockedDecrement(&This->ref);
121
122     TRACE("(%p)->(%d)\n", This, ref);
123
124     if (!ref)
125     {
126         release_format_data(&This->format);
127         heap_free(This->str);
128         heap_free(This);
129     }
130
131     return ref;
132 }
133
134 static HRESULT WINAPI dwritetextlayout_SetTextAlignment(IDWriteTextLayout *iface, DWRITE_TEXT_ALIGNMENT alignment)
135 {
136     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
137     FIXME("(%p)->(%d): stub\n", This, alignment);
138     return E_NOTIMPL;
139 }
140
141 static HRESULT WINAPI dwritetextlayout_SetParagraphAlignment(IDWriteTextLayout *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
142 {
143     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
144     FIXME("(%p)->(%d): stub\n", This, alignment);
145     return E_NOTIMPL;
146 }
147
148 static HRESULT WINAPI dwritetextlayout_SetWordWrapping(IDWriteTextLayout *iface, DWRITE_WORD_WRAPPING wrapping)
149 {
150     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
151     FIXME("(%p)->(%d): stub\n", This, wrapping);
152     return E_NOTIMPL;
153 }
154
155 static HRESULT WINAPI dwritetextlayout_SetReadingDirection(IDWriteTextLayout *iface, DWRITE_READING_DIRECTION direction)
156 {
157     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
158     FIXME("(%p)->(%d): stub\n", This, direction);
159     return E_NOTIMPL;
160 }
161
162 static HRESULT WINAPI dwritetextlayout_SetFlowDirection(IDWriteTextLayout *iface, DWRITE_FLOW_DIRECTION direction)
163 {
164     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
165     FIXME("(%p)->(%d): stub\n", This, direction);
166     return E_NOTIMPL;
167 }
168
169 static HRESULT WINAPI dwritetextlayout_SetIncrementalTabStop(IDWriteTextLayout *iface, FLOAT tabstop)
170 {
171     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
172     FIXME("(%p)->(%f): stub\n", This, tabstop);
173     return E_NOTIMPL;
174 }
175
176 static HRESULT WINAPI dwritetextlayout_SetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING const *trimming,
177     IDWriteInlineObject *trimming_sign)
178 {
179     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
180     FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
181     return E_NOTIMPL;
182 }
183
184 static HRESULT WINAPI dwritetextlayout_SetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD spacing,
185     FLOAT line_spacing, FLOAT baseline)
186 {
187     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
188     FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
189     return E_NOTIMPL;
190 }
191
192 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextlayout_GetTextAlignment(IDWriteTextLayout *iface)
193 {
194     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
195     FIXME("(%p): stub\n", This);
196     return DWRITE_TEXT_ALIGNMENT_LEADING;
197 }
198
199 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextlayout_GetParagraphAlignment(IDWriteTextLayout *iface)
200 {
201     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
202     FIXME("(%p): stub\n", This);
203     return DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
204 }
205
206 static DWRITE_WORD_WRAPPING WINAPI dwritetextlayout_GetWordWrapping(IDWriteTextLayout *iface)
207 {
208     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
209     FIXME("(%p): stub\n", This);
210     return DWRITE_WORD_WRAPPING_NO_WRAP;
211 }
212
213 static DWRITE_READING_DIRECTION WINAPI dwritetextlayout_GetReadingDirection(IDWriteTextLayout *iface)
214 {
215     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
216     FIXME("(%p): stub\n", This);
217     return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
218 }
219
220 static DWRITE_FLOW_DIRECTION WINAPI dwritetextlayout_GetFlowDirection(IDWriteTextLayout *iface)
221 {
222     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
223     FIXME("(%p): stub\n", This);
224     return DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
225 }
226
227 static FLOAT WINAPI dwritetextlayout_GetIncrementalTabStop(IDWriteTextLayout *iface)
228 {
229     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
230     FIXME("(%p): stub\n", This);
231     return 0.0;
232 }
233
234 static HRESULT WINAPI dwritetextlayout_GetTrimming(IDWriteTextLayout *iface, DWRITE_TRIMMING *options,
235     IDWriteInlineObject **trimming_sign)
236 {
237     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
238     FIXME("(%p)->(%p %p): stub\n", This, options, trimming_sign);
239     return E_NOTIMPL;
240 }
241
242 static HRESULT WINAPI dwritetextlayout_GetLineSpacing(IDWriteTextLayout *iface, DWRITE_LINE_SPACING_METHOD *method,
243     FLOAT *spacing, FLOAT *baseline)
244 {
245     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
246     FIXME("(%p)->(%p %p %p): stub\n", This, method, spacing, baseline);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI dwritetextlayout_GetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection **collection)
251 {
252     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
253     FIXME("(%p)->(%p): stub\n", This, collection);
254     return E_NOTIMPL;
255 }
256
257 static UINT32 WINAPI dwritetextlayout_GetFontFamilyNameLength(IDWriteTextLayout *iface)
258 {
259     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
260     FIXME("(%p): stub\n", This);
261     return 0;
262 }
263
264 static HRESULT WINAPI dwritetextlayout_GetFontFamilyName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
265 {
266     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
267     FIXME("(%p)->(%p %u): stub\n", This, name, size);
268     return E_NOTIMPL;
269 }
270
271 static DWRITE_FONT_WEIGHT WINAPI dwritetextlayout_GetFontWeight(IDWriteTextLayout *iface)
272 {
273     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
274     FIXME("(%p): stub\n", This);
275     return DWRITE_FONT_WEIGHT_NORMAL;
276 }
277
278 static DWRITE_FONT_STYLE WINAPI dwritetextlayout_GetFontStyle(IDWriteTextLayout *iface)
279 {
280     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
281     FIXME("(%p): stub\n", This);
282     return DWRITE_FONT_STYLE_NORMAL;
283 }
284
285 static DWRITE_FONT_STRETCH WINAPI dwritetextlayout_GetFontStretch(IDWriteTextLayout *iface)
286 {
287     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
288     FIXME("(%p): stub\n", This);
289     return DWRITE_FONT_STRETCH_NORMAL;
290 }
291
292 static FLOAT WINAPI dwritetextlayout_GetFontSize(IDWriteTextLayout *iface)
293 {
294     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
295     FIXME("(%p): stub\n", This);
296     return 0.0;
297 }
298
299 static UINT32 WINAPI dwritetextlayout_GetLocaleNameLength(IDWriteTextLayout *iface)
300 {
301     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
302     TRACE("(%p)\n", This);
303     return This->format.locale_len;
304 }
305
306 static HRESULT WINAPI dwritetextlayout_GetLocaleName(IDWriteTextLayout *iface, WCHAR *name, UINT32 size)
307 {
308     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
309
310     TRACE("(%p)->(%p %u)\n", This, name, size);
311
312     if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
313     strcpyW(name, This->format.locale);
314     return S_OK;
315 }
316
317 static HRESULT WINAPI dwritetextlayout_SetMaxWidth(IDWriteTextLayout *iface, FLOAT maxWidth)
318 {
319     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
320     FIXME("(%p)->(%f): stub\n", This, maxWidth);
321     return E_NOTIMPL;
322 }
323
324 static HRESULT WINAPI dwritetextlayout_SetMaxHeight(IDWriteTextLayout *iface, FLOAT maxHeight)
325 {
326     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
327     FIXME("(%p)->(%f): stub\n", This, maxHeight);
328     return E_NOTIMPL;
329 }
330
331 static HRESULT WINAPI dwritetextlayout_SetFontCollection(IDWriteTextLayout *iface, IDWriteFontCollection* collection, DWRITE_TEXT_RANGE range)
332 {
333     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
334     FIXME("(%p)->(%p %u:%u): stub\n", This, collection, range.startPosition, range.length);
335     return E_NOTIMPL;
336 }
337
338 static HRESULT WINAPI dwritetextlayout_SetFontFamilyName(IDWriteTextLayout *iface, WCHAR const *name, DWRITE_TEXT_RANGE range)
339 {
340     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
341     FIXME("(%p)->(%s %u:%u): stub\n", This, debugstr_w(name), range.startPosition, range.length);
342     return E_NOTIMPL;
343 }
344
345 static HRESULT WINAPI dwritetextlayout_SetFontWeight(IDWriteTextLayout *iface, DWRITE_FONT_WEIGHT weight, DWRITE_TEXT_RANGE range)
346 {
347     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
348     FIXME("(%p)->(%d %u:%u): stub\n", This, weight, range.startPosition, range.length);
349     return E_NOTIMPL;
350 }
351
352 static HRESULT WINAPI dwritetextlayout_SetFontStyle(IDWriteTextLayout *iface, DWRITE_FONT_STYLE style, DWRITE_TEXT_RANGE range)
353 {
354     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
355     FIXME("(%p)->(%d %u:%u): stub\n", This, style, range.startPosition, range.length);
356     return E_NOTIMPL;
357 }
358
359 static HRESULT WINAPI dwritetextlayout_SetFontStretch(IDWriteTextLayout *iface, DWRITE_FONT_STRETCH stretch, DWRITE_TEXT_RANGE range)
360 {
361     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
362     FIXME("(%p)->(%d %u:%u): stub\n", This, stretch, range.startPosition, range.length);
363     return E_NOTIMPL;
364 }
365
366 static HRESULT WINAPI dwritetextlayout_SetFontSize(IDWriteTextLayout *iface, FLOAT size, DWRITE_TEXT_RANGE range)
367 {
368     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
369     FIXME("(%p)->(%f %u:%u): stub\n", This, size, range.startPosition, range.length);
370     return E_NOTIMPL;
371 }
372
373 static HRESULT WINAPI dwritetextlayout_SetUnderline(IDWriteTextLayout *iface, BOOL underline, DWRITE_TEXT_RANGE range)
374 {
375     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
376     FIXME("(%p)->(%d %u:%u): stub\n", This, underline, range.startPosition, range.length);
377     return E_NOTIMPL;
378 }
379
380 static HRESULT WINAPI dwritetextlayout_SetStrikethrough(IDWriteTextLayout *iface, BOOL strikethrough, DWRITE_TEXT_RANGE range)
381 {
382     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
383     FIXME("(%p)->(%d %u:%u): stub\n", This, strikethrough, range.startPosition, range.length);
384     return E_NOTIMPL;
385 }
386
387 static HRESULT WINAPI dwritetextlayout_SetDrawingEffect(IDWriteTextLayout *iface, IUnknown* effect, DWRITE_TEXT_RANGE range)
388 {
389     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
390     FIXME("(%p)->(%p %u:%u): stub\n", This, effect, range.startPosition, range.length);
391     return E_NOTIMPL;
392 }
393
394 static HRESULT WINAPI dwritetextlayout_SetInlineObject(IDWriteTextLayout *iface, IDWriteInlineObject *object, DWRITE_TEXT_RANGE range)
395 {
396     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
397     FIXME("(%p)->(%p %u:%u): stub\n", This, object, range.startPosition, range.length);
398     return E_NOTIMPL;
399 }
400
401 static HRESULT WINAPI dwritetextlayout_SetTypography(IDWriteTextLayout *iface, IDWriteTypography* typography, DWRITE_TEXT_RANGE range)
402 {
403     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
404     FIXME("(%p)->(%p %u:%u): stub\n", This, typography, range.startPosition, range.length);
405     return E_NOTIMPL;
406 }
407
408 static HRESULT WINAPI dwritetextlayout_SetLocaleName(IDWriteTextLayout *iface, WCHAR const* locale, DWRITE_TEXT_RANGE range)
409 {
410     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
411     FIXME("(%p)->(%s %u:%u): stub\n", This, debugstr_w(locale), range.startPosition, range.length);
412     return E_NOTIMPL;
413 }
414
415 static FLOAT WINAPI dwritetextlayout_GetMaxWidth(IDWriteTextLayout *iface)
416 {
417     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
418     FIXME("(%p): stub\n", This);
419     return 0.0;
420 }
421
422 static FLOAT WINAPI dwritetextlayout_GetMaxHeight(IDWriteTextLayout *iface)
423 {
424     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
425     FIXME("(%p): stub\n", This);
426     return 0.0;
427 }
428
429 static HRESULT WINAPI dwritetextlayout_layout_GetFontCollection(IDWriteTextLayout *iface, UINT32 pos,
430     IDWriteFontCollection** collection, DWRITE_TEXT_RANGE *range)
431 {
432     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
433     FIXME("(%p)->(%p %p): stub\n", This, collection, range);
434     return E_NOTIMPL;
435 }
436
437 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyNameLength(IDWriteTextLayout *iface,
438     UINT32 pos, UINT32* len, DWRITE_TEXT_RANGE *range)
439 {
440     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
441     FIXME("(%p)->(%d %p %p): stub\n", This, pos, len, range);
442     return E_NOTIMPL;
443 }
444
445 static HRESULT WINAPI dwritetextlayout_layout_GetFontFamilyName(IDWriteTextLayout *iface,
446     UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
447 {
448     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
449     FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
450     return E_NOTIMPL;
451 }
452
453 static HRESULT WINAPI dwritetextlayout_layout_GetFontWeight(IDWriteTextLayout *iface,
454     UINT32 position, DWRITE_FONT_WEIGHT *weight, DWRITE_TEXT_RANGE *range)
455 {
456     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
457     FIXME("(%p)->(%u %p %p): stub\n", This, position, weight, range);
458     return E_NOTIMPL;
459 }
460
461 static HRESULT WINAPI dwritetextlayout_layout_GetFontStyle(IDWriteTextLayout *iface,
462     UINT32 currentPosition, DWRITE_FONT_STYLE *style, DWRITE_TEXT_RANGE *range)
463 {
464     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
465     FIXME("(%p)->(%u %p %p): stub\n", This, currentPosition, style, range);
466     return E_NOTIMPL;
467 }
468
469 static HRESULT WINAPI dwritetextlayout_layout_GetFontStretch(IDWriteTextLayout *iface,
470     UINT32 position, DWRITE_FONT_STRETCH *stretch, DWRITE_TEXT_RANGE *range)
471 {
472     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
473     FIXME("(%p)->(%u %p %p): stub\n", This, position, stretch, range);
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI dwritetextlayout_layout_GetFontSize(IDWriteTextLayout *iface,
478     UINT32 position, FLOAT *size, DWRITE_TEXT_RANGE *range)
479 {
480     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
481     FIXME("(%p)->(%u %p %p): stub\n", This, position, size, range);
482     return E_NOTIMPL;
483 }
484
485 static HRESULT WINAPI dwritetextlayout_GetUnderline(IDWriteTextLayout *iface,
486     UINT32 position, BOOL *has_underline, DWRITE_TEXT_RANGE *range)
487 {
488     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
489     FIXME("(%p)->(%u %p %p): stub\n", This, position, has_underline, range);
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI dwritetextlayout_GetStrikethrough(IDWriteTextLayout *iface,
494     UINT32 position, BOOL *has_strikethrough, DWRITE_TEXT_RANGE *range)
495 {
496     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
497     FIXME("(%p)->(%u %p %p): stub\n", This, position, has_strikethrough, range);
498     return E_NOTIMPL;
499 }
500
501 static HRESULT WINAPI dwritetextlayout_GetDrawingEffect(IDWriteTextLayout *iface,
502     UINT32 position, IUnknown **effect, DWRITE_TEXT_RANGE *range)
503 {
504     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
505     FIXME("(%p)->(%u %p %p): stub\n", This, position, effect, range);
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI dwritetextlayout_GetInlineObject(IDWriteTextLayout *iface,
510     UINT32 position, IDWriteInlineObject **object, DWRITE_TEXT_RANGE *range)
511 {
512     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
513     FIXME("(%p)->(%u %p %p): stub\n", This, position, object, range);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI dwritetextlayout_GetTypography(IDWriteTextLayout *iface,
518     UINT32 position, IDWriteTypography** typography, DWRITE_TEXT_RANGE *range)
519 {
520     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
521     FIXME("(%p)->(%u %p %p): stub\n", This, position, typography, range);
522     return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleNameLength(IDWriteTextLayout *iface,
526     UINT32 position, UINT32* length, DWRITE_TEXT_RANGE *range)
527 {
528     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
529     FIXME("(%p)->(%u %p %p): stub\n", This, position, length, range);
530     return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI dwritetextlayout_layout_GetLocaleName(IDWriteTextLayout *iface,
534     UINT32 position, WCHAR* name, UINT32 name_size, DWRITE_TEXT_RANGE *range)
535 {
536     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
537     FIXME("(%p)->(%u %p %u %p): stub\n", This, position, name, name_size, range);
538     return E_NOTIMPL;
539 }
540
541 static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout *iface,
542     void *context, IDWriteTextRenderer* renderer, FLOAT originX, FLOAT originY)
543 {
544     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
545     FIXME("(%p)->(%p %p %f %f): stub\n", This, context, renderer, originX, originY);
546     return E_NOTIMPL;
547 }
548
549 static HRESULT WINAPI dwritetextlayout_GetLineMetrics(IDWriteTextLayout *iface,
550     DWRITE_LINE_METRICS *metrics, UINT32 max_count, UINT32 *actual_count)
551 {
552     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
553     FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, actual_count);
554     return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI dwritetextlayout_GetMetrics(IDWriteTextLayout *iface, DWRITE_TEXT_METRICS *metrics)
558 {
559     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
560     FIXME("(%p)->(%p): stub\n", This, metrics);
561     return E_NOTIMPL;
562 }
563
564 static HRESULT WINAPI dwritetextlayout_GetOverhangMetrics(IDWriteTextLayout *iface, DWRITE_OVERHANG_METRICS *overhangs)
565 {
566     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
567     FIXME("(%p)->(%p): stub\n", This, overhangs);
568     return E_NOTIMPL;
569 }
570
571 static HRESULT WINAPI dwritetextlayout_GetClusterMetrics(IDWriteTextLayout *iface,
572     DWRITE_CLUSTER_METRICS *metrics, UINT32 max_count, UINT32* act_count)
573 {
574     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
575     FIXME("(%p)->(%p %u %p): stub\n", This, metrics, max_count, act_count);
576     return E_NOTIMPL;
577 }
578
579 static HRESULT WINAPI dwritetextlayout_DetermineMinWidth(IDWriteTextLayout *iface, FLOAT* min_width)
580 {
581     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
582     FIXME("(%p)->(%p): stub\n", This, min_width);
583     return E_NOTIMPL;
584 }
585
586 static HRESULT WINAPI dwritetextlayout_HitTestPoint(IDWriteTextLayout *iface,
587     FLOAT pointX, FLOAT pointY, BOOL* is_trailinghit, BOOL* is_inside, DWRITE_HIT_TEST_METRICS *metrics)
588 {
589     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
590     FIXME("(%p)->(%f %f %p %p %p): stub\n", This, pointX, pointY, is_trailinghit, is_inside, metrics);
591     return E_NOTIMPL;
592 }
593
594 static HRESULT WINAPI dwritetextlayout_HitTestTextPosition(IDWriteTextLayout *iface,
595     UINT32 textPosition, BOOL is_trailinghit, FLOAT* pointX, FLOAT* pointY, DWRITE_HIT_TEST_METRICS *metrics)
596 {
597     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
598     FIXME("(%p)->(%u %d %p %p %p): stub\n", This, textPosition, is_trailinghit, pointX, pointY, metrics);
599     return E_NOTIMPL;
600 }
601
602 static HRESULT WINAPI dwritetextlayout_HitTestTextRange(IDWriteTextLayout *iface,
603     UINT32 textPosition, UINT32 textLength, FLOAT originX, FLOAT originY,
604     DWRITE_HIT_TEST_METRICS *metrics, UINT32 max_metricscount, UINT32* actual_metricscount)
605 {
606     struct dwrite_textlayout *This = impl_from_IDWriteTextLayout(iface);
607     FIXME("(%p)->(%u %u %f %f %p %u %p): stub\n", This, textPosition, textLength, originX, originY, metrics,
608         max_metricscount, actual_metricscount);
609     return E_NOTIMPL;
610 }
611
612 static const IDWriteTextLayoutVtbl dwritetextlayoutvtbl = {
613     dwritetextlayout_QueryInterface,
614     dwritetextlayout_AddRef,
615     dwritetextlayout_Release,
616     dwritetextlayout_SetTextAlignment,
617     dwritetextlayout_SetParagraphAlignment,
618     dwritetextlayout_SetWordWrapping,
619     dwritetextlayout_SetReadingDirection,
620     dwritetextlayout_SetFlowDirection,
621     dwritetextlayout_SetIncrementalTabStop,
622     dwritetextlayout_SetTrimming,
623     dwritetextlayout_SetLineSpacing,
624     dwritetextlayout_GetTextAlignment,
625     dwritetextlayout_GetParagraphAlignment,
626     dwritetextlayout_GetWordWrapping,
627     dwritetextlayout_GetReadingDirection,
628     dwritetextlayout_GetFlowDirection,
629     dwritetextlayout_GetIncrementalTabStop,
630     dwritetextlayout_GetTrimming,
631     dwritetextlayout_GetLineSpacing,
632     dwritetextlayout_GetFontCollection,
633     dwritetextlayout_GetFontFamilyNameLength,
634     dwritetextlayout_GetFontFamilyName,
635     dwritetextlayout_GetFontWeight,
636     dwritetextlayout_GetFontStyle,
637     dwritetextlayout_GetFontStretch,
638     dwritetextlayout_GetFontSize,
639     dwritetextlayout_GetLocaleNameLength,
640     dwritetextlayout_GetLocaleName,
641     dwritetextlayout_SetMaxWidth,
642     dwritetextlayout_SetMaxHeight,
643     dwritetextlayout_SetFontCollection,
644     dwritetextlayout_SetFontFamilyName,
645     dwritetextlayout_SetFontWeight,
646     dwritetextlayout_SetFontStyle,
647     dwritetextlayout_SetFontStretch,
648     dwritetextlayout_SetFontSize,
649     dwritetextlayout_SetUnderline,
650     dwritetextlayout_SetStrikethrough,
651     dwritetextlayout_SetDrawingEffect,
652     dwritetextlayout_SetInlineObject,
653     dwritetextlayout_SetTypography,
654     dwritetextlayout_SetLocaleName,
655     dwritetextlayout_GetMaxWidth,
656     dwritetextlayout_GetMaxHeight,
657     dwritetextlayout_layout_GetFontCollection,
658     dwritetextlayout_layout_GetFontFamilyNameLength,
659     dwritetextlayout_layout_GetFontFamilyName,
660     dwritetextlayout_layout_GetFontWeight,
661     dwritetextlayout_layout_GetFontStyle,
662     dwritetextlayout_layout_GetFontStretch,
663     dwritetextlayout_layout_GetFontSize,
664     dwritetextlayout_GetUnderline,
665     dwritetextlayout_GetStrikethrough,
666     dwritetextlayout_GetDrawingEffect,
667     dwritetextlayout_GetInlineObject,
668     dwritetextlayout_GetTypography,
669     dwritetextlayout_layout_GetLocaleNameLength,
670     dwritetextlayout_layout_GetLocaleName,
671     dwritetextlayout_Draw,
672     dwritetextlayout_GetLineMetrics,
673     dwritetextlayout_GetMetrics,
674     dwritetextlayout_GetOverhangMetrics,
675     dwritetextlayout_GetClusterMetrics,
676     dwritetextlayout_DetermineMinWidth,
677     dwritetextlayout_HitTestPoint,
678     dwritetextlayout_HitTestTextPosition,
679     dwritetextlayout_HitTestTextRange
680 };
681
682 static void layout_format_from_textformat(struct dwrite_textlayout *layout, IDWriteTextFormat *format)
683 {
684     struct dwrite_textformat *f;
685
686     memset(&layout->format, 0, sizeof(layout->format));
687
688     if ((f = unsafe_impl_from_IDWriteTextFormat(format)))
689     {
690         layout->format = f->format;
691         layout->format.locale = heap_strdupW(f->format.locale);
692         layout->format.family_name = heap_strdupW(f->format.family_name);
693     }
694     else
695     {
696         UINT32 locale_len, family_len;
697
698         layout->format.weight  = IDWriteTextFormat_GetFontWeight(format);
699         layout->format.style   = IDWriteTextFormat_GetFontStyle(format);
700         layout->format.stretch = IDWriteTextFormat_GetFontStretch(format);
701         layout->format.size    = IDWriteTextFormat_GetFontSize(format);
702
703         /* locale name and length */
704         locale_len = IDWriteTextFormat_GetLocaleNameLength(format);
705         layout->format.locale  = heap_alloc((locale_len+1)*sizeof(WCHAR));
706         IDWriteTextFormat_GetLocaleName(format, layout->format.locale, locale_len+1);
707         layout->format.locale_len = locale_len;
708
709         /* font family name and length */
710         family_len = IDWriteTextFormat_GetFontFamilyNameLength(format);
711         layout->format.family_name = heap_alloc((family_len+1)*sizeof(WCHAR));
712         IDWriteTextFormat_GetFontFamilyName(format, layout->format.family_name, family_len+1);
713         layout->format.family_len = family_len;
714     }
715
716     IDWriteTextFormat_GetFontCollection(format, &layout->format.collection);
717 }
718
719 HRESULT create_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *format, IDWriteTextLayout **layout)
720 {
721     struct dwrite_textlayout *This;
722
723     *layout = NULL;
724
725     This = heap_alloc(sizeof(struct dwrite_textlayout));
726     if (!This) return E_OUTOFMEMORY;
727
728     This->IDWriteTextLayout_iface.lpVtbl = &dwritetextlayoutvtbl;
729     This->ref = 1;
730     This->str = heap_strdupnW(str, len);
731     This->len = len;
732     layout_format_from_textformat(This, format);
733
734     *layout = &This->IDWriteTextLayout_iface;
735
736     return S_OK;
737 }
738
739 static HRESULT WINAPI dwritetextformat_QueryInterface(IDWriteTextFormat *iface, REFIID riid, void **obj)
740 {
741     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
742
743     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
744
745     if (IsEqualIID(riid, &IID_IUnknown) ||
746         IsEqualIID(riid, &IID_IDWriteTextFormat))
747     {
748         *obj = iface;
749         IDWriteTextFormat_AddRef(iface);
750         return S_OK;
751     }
752
753     *obj = NULL;
754
755     return E_NOINTERFACE;
756 }
757
758 static ULONG WINAPI dwritetextformat_AddRef(IDWriteTextFormat *iface)
759 {
760     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
761     ULONG ref = InterlockedIncrement(&This->ref);
762     TRACE("(%p)->(%d)\n", This, ref);
763     return ref;
764 }
765
766 static ULONG WINAPI dwritetextformat_Release(IDWriteTextFormat *iface)
767 {
768     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
769     ULONG ref = InterlockedDecrement(&This->ref);
770
771     TRACE("(%p)->(%d)\n", This, ref);
772
773     if (!ref)
774     {
775         release_format_data(&This->format);
776         heap_free(This);
777     }
778
779     return ref;
780 }
781
782 static HRESULT WINAPI dwritetextformat_SetTextAlignment(IDWriteTextFormat *iface, DWRITE_TEXT_ALIGNMENT alignment)
783 {
784     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
785     FIXME("(%p)->(%d): stub\n", This, alignment);
786     return E_NOTIMPL;
787 }
788
789 static HRESULT WINAPI dwritetextformat_SetParagraphAlignment(IDWriteTextFormat *iface, DWRITE_PARAGRAPH_ALIGNMENT alignment)
790 {
791     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
792     FIXME("(%p)->(%d): stub\n", This, alignment);
793     return E_NOTIMPL;
794 }
795
796 static HRESULT WINAPI dwritetextformat_SetWordWrapping(IDWriteTextFormat *iface, DWRITE_WORD_WRAPPING wrapping)
797 {
798     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
799     FIXME("(%p)->(%d): stub\n", This, wrapping);
800     return E_NOTIMPL;
801 }
802
803 static HRESULT WINAPI dwritetextformat_SetReadingDirection(IDWriteTextFormat *iface, DWRITE_READING_DIRECTION direction)
804 {
805     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
806     FIXME("(%p)->(%d): stub\n", This, direction);
807     return E_NOTIMPL;
808 }
809
810 static HRESULT WINAPI dwritetextformat_SetFlowDirection(IDWriteTextFormat *iface, DWRITE_FLOW_DIRECTION direction)
811 {
812     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
813     FIXME("(%p)->(%d): stub\n", This, direction);
814     return E_NOTIMPL;
815 }
816
817 static HRESULT WINAPI dwritetextformat_SetIncrementalTabStop(IDWriteTextFormat *iface, FLOAT tabstop)
818 {
819     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
820     FIXME("(%p)->(%f): stub\n", This, tabstop);
821     return E_NOTIMPL;
822 }
823
824 static HRESULT WINAPI dwritetextformat_SetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING const *trimming,
825     IDWriteInlineObject *trimming_sign)
826 {
827     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
828     FIXME("(%p)->(%p %p): stub\n", This, trimming, trimming_sign);
829     return E_NOTIMPL;
830 }
831
832 static HRESULT WINAPI dwritetextformat_SetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD spacing,
833     FLOAT line_spacing, FLOAT baseline)
834 {
835     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
836     FIXME("(%p)->(%d %f %f): stub\n", This, spacing, line_spacing, baseline);
837     return E_NOTIMPL;
838 }
839
840 static DWRITE_TEXT_ALIGNMENT WINAPI dwritetextformat_GetTextAlignment(IDWriteTextFormat *iface)
841 {
842     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
843     FIXME("(%p): stub\n", This);
844     return DWRITE_TEXT_ALIGNMENT_LEADING;
845 }
846
847 static DWRITE_PARAGRAPH_ALIGNMENT WINAPI dwritetextformat_GetParagraphAlignment(IDWriteTextFormat *iface)
848 {
849     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
850     FIXME("(%p): stub\n", This);
851     return DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
852 }
853
854 static DWRITE_WORD_WRAPPING WINAPI dwritetextformat_GetWordWrapping(IDWriteTextFormat *iface)
855 {
856     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
857     FIXME("(%p): stub\n", This);
858     return DWRITE_WORD_WRAPPING_NO_WRAP;
859 }
860
861 static DWRITE_READING_DIRECTION WINAPI dwritetextformat_GetReadingDirection(IDWriteTextFormat *iface)
862 {
863     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
864     FIXME("(%p): stub\n", This);
865     return DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
866 }
867
868 static DWRITE_FLOW_DIRECTION WINAPI dwritetextformat_GetFlowDirection(IDWriteTextFormat *iface)
869 {
870     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
871     FIXME("(%p): stub\n", This);
872     return DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
873 }
874
875 static FLOAT WINAPI dwritetextformat_GetIncrementalTabStop(IDWriteTextFormat *iface)
876 {
877     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
878     FIXME("(%p): stub\n", This);
879     return 0.0;
880 }
881
882 static HRESULT WINAPI dwritetextformat_GetTrimming(IDWriteTextFormat *iface, DWRITE_TRIMMING *options,
883     IDWriteInlineObject **trimming_sign)
884 {
885     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
886     FIXME("(%p)->(%p %p): stub\n", This, options, trimming_sign);
887     return E_NOTIMPL;
888 }
889
890 static HRESULT WINAPI dwritetextformat_GetLineSpacing(IDWriteTextFormat *iface, DWRITE_LINE_SPACING_METHOD *method,
891     FLOAT *spacing, FLOAT *baseline)
892 {
893     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
894     FIXME("(%p)->(%p %p %p): stub\n", This, method, spacing, baseline);
895     return E_NOTIMPL;
896 }
897
898 static HRESULT WINAPI dwritetextformat_GetFontCollection(IDWriteTextFormat *iface, IDWriteFontCollection **collection)
899 {
900     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
901
902     TRACE("(%p)->(%p)\n", This, collection);
903
904     *collection = This->format.collection;
905     IDWriteFontCollection_AddRef(*collection);
906
907     return S_OK;
908 }
909
910 static UINT32 WINAPI dwritetextformat_GetFontFamilyNameLength(IDWriteTextFormat *iface)
911 {
912     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
913     TRACE("(%p)\n", This);
914     return This->format.family_len;
915 }
916
917 static HRESULT WINAPI dwritetextformat_GetFontFamilyName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
918 {
919     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
920
921     TRACE("(%p)->(%p %u)\n", This, name, size);
922
923     if (size <= This->format.family_len) return E_NOT_SUFFICIENT_BUFFER;
924     strcpyW(name, This->format.family_name);
925     return S_OK;
926 }
927
928 static DWRITE_FONT_WEIGHT WINAPI dwritetextformat_GetFontWeight(IDWriteTextFormat *iface)
929 {
930     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
931     TRACE("(%p)\n", This);
932     return This->format.weight;
933 }
934
935 static DWRITE_FONT_STYLE WINAPI dwritetextformat_GetFontStyle(IDWriteTextFormat *iface)
936 {
937     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
938     TRACE("(%p)\n", This);
939     return This->format.style;
940 }
941
942 static DWRITE_FONT_STRETCH WINAPI dwritetextformat_GetFontStretch(IDWriteTextFormat *iface)
943 {
944     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
945     TRACE("(%p)\n", This);
946     return This->format.stretch;
947 }
948
949 static FLOAT WINAPI dwritetextformat_GetFontSize(IDWriteTextFormat *iface)
950 {
951     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
952     TRACE("(%p)\n", This);
953     return This->format.size;
954 }
955
956 static UINT32 WINAPI dwritetextformat_GetLocaleNameLength(IDWriteTextFormat *iface)
957 {
958     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
959     TRACE("(%p)\n", This);
960     return This->format.locale_len;
961 }
962
963 static HRESULT WINAPI dwritetextformat_GetLocaleName(IDWriteTextFormat *iface, WCHAR *name, UINT32 size)
964 {
965     struct dwrite_textformat *This = impl_from_IDWriteTextFormat(iface);
966
967     TRACE("(%p)->(%p %u)\n", This, name, size);
968
969     if (size <= This->format.locale_len) return E_NOT_SUFFICIENT_BUFFER;
970     strcpyW(name, This->format.locale);
971     return S_OK;
972 }
973
974 static const IDWriteTextFormatVtbl dwritetextformatvtbl = {
975     dwritetextformat_QueryInterface,
976     dwritetextformat_AddRef,
977     dwritetextformat_Release,
978     dwritetextformat_SetTextAlignment,
979     dwritetextformat_SetParagraphAlignment,
980     dwritetextformat_SetWordWrapping,
981     dwritetextformat_SetReadingDirection,
982     dwritetextformat_SetFlowDirection,
983     dwritetextformat_SetIncrementalTabStop,
984     dwritetextformat_SetTrimming,
985     dwritetextformat_SetLineSpacing,
986     dwritetextformat_GetTextAlignment,
987     dwritetextformat_GetParagraphAlignment,
988     dwritetextformat_GetWordWrapping,
989     dwritetextformat_GetReadingDirection,
990     dwritetextformat_GetFlowDirection,
991     dwritetextformat_GetIncrementalTabStop,
992     dwritetextformat_GetTrimming,
993     dwritetextformat_GetLineSpacing,
994     dwritetextformat_GetFontCollection,
995     dwritetextformat_GetFontFamilyNameLength,
996     dwritetextformat_GetFontFamilyName,
997     dwritetextformat_GetFontWeight,
998     dwritetextformat_GetFontStyle,
999     dwritetextformat_GetFontStretch,
1000     dwritetextformat_GetFontSize,
1001     dwritetextformat_GetLocaleNameLength,
1002     dwritetextformat_GetLocaleName
1003 };
1004
1005 HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
1006     DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
1007 {
1008     struct dwrite_textformat *This;
1009
1010     *format = NULL;
1011
1012     This = heap_alloc(sizeof(struct dwrite_textformat));
1013     if (!This) return E_OUTOFMEMORY;
1014
1015     This->IDWriteTextFormat_iface.lpVtbl = &dwritetextformatvtbl;
1016     This->ref = 1;
1017     This->format.family_name = heap_strdupW(family_name);
1018     This->format.family_len = strlenW(family_name);
1019     This->format.locale = heap_strdupW(locale);
1020     This->format.locale_len = strlenW(locale);
1021     This->format.weight = weight;
1022     This->format.style = style;
1023     This->format.size = size;
1024
1025     if (collection)
1026     {
1027         This->format.collection = collection;
1028         IDWriteFontCollection_AddRef(collection);
1029     }
1030     else
1031     {
1032         HRESULT hr = get_system_fontcollection(&This->format.collection);
1033         if (hr != S_OK)
1034         {
1035             IDWriteTextFormat_Release(&This->IDWriteTextFormat_iface);
1036             return hr;
1037         }
1038     }
1039
1040     *format = &This->IDWriteTextFormat_iface;
1041
1042     return S_OK;
1043 }