dwrite: Fix a stupid copy/paste typo in Release return value.
[wine] / dlls / dwrite / main.c
1 /*
2  *    DWrite
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 "winuser.h"
28
29 #include "initguid.h"
30 #include "dwrite.h"
31
32 #include "dwrite_private.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
36
37 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
38 {
39     switch (reason)
40     {
41     case DLL_WINE_PREATTACH:
42         return FALSE;  /* prefer native version */
43     case DLL_PROCESS_ATTACH:
44         DisableThreadLibraryCalls( hinstDLL );
45         break;
46     }
47     return TRUE;
48 }
49
50 struct renderingparams {
51     IDWriteRenderingParams IDWriteRenderingParams_iface;
52     LONG ref;
53
54     FLOAT gamma;
55     FLOAT enh_contrast;
56     FLOAT cleartype_level;
57     DWRITE_PIXEL_GEOMETRY geometry;
58     DWRITE_RENDERING_MODE mode;
59 };
60
61 static inline struct renderingparams *impl_from_IDWriteRenderingParams(IDWriteRenderingParams *iface)
62 {
63     return CONTAINING_RECORD(iface, struct renderingparams, IDWriteRenderingParams_iface);
64 }
65
66 static HRESULT WINAPI renderingparams_QueryInterface(IDWriteRenderingParams *iface, REFIID riid, void **obj)
67 {
68     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
69
70     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
71
72     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteRenderingParams))
73     {
74         *obj = iface;
75         IDWriteRenderingParams_AddRef(iface);
76         return S_OK;
77     }
78
79     *obj = NULL;
80
81     return E_NOINTERFACE;
82 }
83
84 static ULONG WINAPI renderingparams_AddRef(IDWriteRenderingParams *iface)
85 {
86     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
87     ULONG ref = InterlockedIncrement(&This->ref);
88     TRACE("(%p)->(%d)\n", This, ref);
89     return ref;
90 }
91
92 static ULONG WINAPI renderingparams_Release(IDWriteRenderingParams *iface)
93 {
94     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
95     ULONG ref = InterlockedDecrement(&This->ref);
96
97     TRACE("(%p)->(%d)\n", This, ref);
98
99     if (!ref)
100         heap_free(This);
101
102     return ref;
103 }
104
105 static FLOAT WINAPI renderingparams_GetGamma(IDWriteRenderingParams *iface)
106 {
107     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
108     TRACE("(%p)\n", This);
109     return This->gamma;
110 }
111
112 static FLOAT WINAPI renderingparams_GetEnhancedContrast(IDWriteRenderingParams *iface)
113 {
114     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
115     TRACE("(%p)\n", This);
116     return This->enh_contrast;
117 }
118
119 static FLOAT WINAPI renderingparams_GetClearTypeLevel(IDWriteRenderingParams *iface)
120 {
121     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
122     TRACE("(%p)\n", This);
123     return This->cleartype_level;
124 }
125
126 static DWRITE_PIXEL_GEOMETRY WINAPI renderingparams_GetPixelGeometry(IDWriteRenderingParams *iface)
127 {
128     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
129     TRACE("(%p)\n", This);
130     return This->geometry;
131 }
132
133 static DWRITE_RENDERING_MODE WINAPI renderingparams_GetRenderingMode(IDWriteRenderingParams *iface)
134 {
135     struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
136     TRACE("(%p)\n", This);
137     return This->mode;
138 }
139
140 static const struct IDWriteRenderingParamsVtbl renderingparamsvtbl = {
141     renderingparams_QueryInterface,
142     renderingparams_AddRef,
143     renderingparams_Release,
144     renderingparams_GetGamma,
145     renderingparams_GetEnhancedContrast,
146     renderingparams_GetClearTypeLevel,
147     renderingparams_GetPixelGeometry,
148     renderingparams_GetRenderingMode
149 };
150
151 static HRESULT create_renderingparams(FLOAT gamma, FLOAT enhancedContrast, FLOAT cleartype_level,
152     DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode, IDWriteRenderingParams **params)
153 {
154     struct renderingparams *This;
155
156     *params = NULL;
157
158     This = heap_alloc(sizeof(struct renderingparams));
159     if (!This) return E_OUTOFMEMORY;
160
161     This->IDWriteRenderingParams_iface.lpVtbl = &renderingparamsvtbl;
162     This->ref = 1;
163
164     This->gamma = gamma;
165     This->enh_contrast = enhancedContrast;
166     This->cleartype_level = cleartype_level;
167     This->geometry = geometry;
168     This->mode = mode;
169
170     *params = &This->IDWriteRenderingParams_iface;
171
172     return S_OK;
173 }
174
175 struct localizedpair {
176     WCHAR *locale;
177     WCHAR *string;
178 };
179
180 struct localizedstrings {
181     IDWriteLocalizedStrings IDWriteLocalizedStrings_iface;
182     LONG ref;
183
184     struct localizedpair *data;
185     UINT32 count;
186     UINT32 alloc;
187 };
188
189 static inline struct localizedstrings *impl_from_IDWriteLocalizedStrings(IDWriteLocalizedStrings *iface)
190 {
191     return CONTAINING_RECORD(iface, struct localizedstrings, IDWriteLocalizedStrings_iface);
192 }
193
194 static HRESULT WINAPI localizedstrings_QueryInterface(IDWriteLocalizedStrings *iface, REFIID riid, void **obj)
195 {
196     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
197
198     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
199
200     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteLocalizedStrings))
201     {
202         *obj = iface;
203         IDWriteLocalizedStrings_AddRef(iface);
204         return S_OK;
205     }
206
207     *obj = NULL;
208
209     return E_NOINTERFACE;
210 }
211
212 static ULONG WINAPI localizedstrings_AddRef(IDWriteLocalizedStrings *iface)
213 {
214     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
215     ULONG ref = InterlockedIncrement(&This->ref);
216     TRACE("(%p)->(%d)\n", This, ref);
217     return ref;
218 }
219
220 static ULONG WINAPI localizedstrings_Release(IDWriteLocalizedStrings *iface)
221 {
222     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
223     ULONG ref = InterlockedDecrement(&This->ref);
224
225     TRACE("(%p)->(%d)\n", This, ref);
226
227     if (!ref) {
228         int i;
229
230         for (i = 0; i < This->count; i++) {
231             heap_free(This->data[i].locale);
232             heap_free(This->data[i].string);
233         }
234
235         heap_free(This->data);
236         heap_free(This);
237     }
238
239     return ref;
240 }
241
242 static UINT32 WINAPI localizedstrings_GetCount(IDWriteLocalizedStrings *iface)
243 {
244     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
245     TRACE("(%p)\n", This);
246     return This->count;
247 }
248
249 static HRESULT WINAPI localizedstrings_FindLocaleName(IDWriteLocalizedStrings *iface,
250     WCHAR const *locale_name, UINT32 *index, BOOL *exists)
251 {
252     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
253     FIXME("(%p)->(%s %p %p): stub\n", This, debugstr_w(locale_name), index, exists);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI localizedstrings_GetLocaleNameLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
258 {
259     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
260     FIXME("(%p)->(%u %p): stub\n", This, index, length);
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI localizedstrings_GetLocaleName(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *locale_name, UINT32 size)
265 {
266     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
267     FIXME("(%p)->(%u %p %u): stub\n", This, index, locale_name, size);
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI localizedstrings_GetStringLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
272 {
273     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
274
275     TRACE("(%p)->(%u %p)\n", This, index, length);
276
277     if (index >= This->count) {
278         *length = (UINT32)-1;
279         return E_FAIL;
280     }
281
282     *length = strlenW(This->data[index].string);
283     return S_OK;
284 }
285
286 static HRESULT WINAPI localizedstrings_GetString(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
287 {
288     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
289
290     TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
291
292     if (index >= This->count) {
293         if (buffer) *buffer = 0;
294         return E_FAIL;
295     }
296
297     if (size < strlenW(This->data[index].string)+1) {
298         if (buffer) *buffer = 0;
299         return E_NOT_SUFFICIENT_BUFFER;
300     }
301
302     strcpyW(buffer, This->data[index].string);
303     return S_OK;
304 }
305
306 static const IDWriteLocalizedStringsVtbl localizedstringsvtbl = {
307     localizedstrings_QueryInterface,
308     localizedstrings_AddRef,
309     localizedstrings_Release,
310     localizedstrings_GetCount,
311     localizedstrings_FindLocaleName,
312     localizedstrings_GetLocaleNameLength,
313     localizedstrings_GetLocaleName,
314     localizedstrings_GetStringLength,
315     localizedstrings_GetString
316 };
317
318 HRESULT create_localizedstrings(IDWriteLocalizedStrings **strings)
319 {
320     struct localizedstrings *This;
321
322     *strings = NULL;
323
324     This = heap_alloc(sizeof(struct localizedstrings));
325     if (!This) return E_OUTOFMEMORY;
326
327     This->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
328     This->ref = 1;
329     This->count = 0;
330     This->data = heap_alloc_zero(sizeof(struct localizedpair));
331     if (!This->data) {
332         heap_free(This);
333         return E_OUTOFMEMORY;
334     }
335     This->alloc = 1;
336
337     *strings = &This->IDWriteLocalizedStrings_iface;
338
339     return S_OK;
340 }
341
342 HRESULT add_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *locale, const WCHAR *string)
343 {
344     struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
345
346     if (This->count == This->alloc) {
347         This->alloc *= 2;
348         This->data = heap_realloc(This->data, This->alloc*sizeof(struct localizedpair));
349     }
350
351     This->data[This->count].locale = heap_strdupW(locale);
352     This->data[This->count].string = heap_strdupW(string);
353     This->count++;
354
355     return S_OK;
356 }
357
358 static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory *iface, REFIID riid, void **obj)
359 {
360     TRACE("(%s %p)\n", debugstr_guid(riid), obj);
361
362     if (IsEqualIID(riid, &IID_IUnknown) ||
363         IsEqualIID(riid, &IID_IDWriteFactory))
364     {
365         *obj = iface;
366         return S_OK;
367     }
368
369     *obj = NULL;
370
371     return E_NOINTERFACE;
372 }
373
374 static ULONG WINAPI dwritefactory_AddRef(IDWriteFactory *iface)
375 {
376     return 2;
377 }
378
379 static ULONG WINAPI dwritefactory_Release(IDWriteFactory *iface)
380 {
381     return 1;
382 }
383
384 static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory *iface,
385     IDWriteFontCollection **collection, BOOL check_for_updates)
386 {
387     FIXME("(%p %d): semi-stub\n", collection, check_for_updates);
388     return create_fontcollection(collection);
389 }
390
391 static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory *iface,
392     IDWriteFontCollectionLoader *loader, void const *key, UINT32 key_size, IDWriteFontCollection **collection)
393 {
394     FIXME("(%p %p %u %p): stub\n", loader, key, key_size, collection);
395     return E_NOTIMPL;
396 }
397
398 static HRESULT WINAPI dwritefactory_RegisterFontCollectionLoader(IDWriteFactory *iface,
399     IDWriteFontCollectionLoader *loader)
400 {
401     FIXME("(%p): stub\n", loader);
402     return E_NOTIMPL;
403 }
404
405 static HRESULT WINAPI dwritefactory_UnregisterFontCollectionLoader(IDWriteFactory *iface,
406     IDWriteFontCollectionLoader *loader)
407 {
408     FIXME("(%p): stub\n", loader);
409     return E_NOTIMPL;
410 }
411
412 static HRESULT WINAPI dwritefactory_CreateFontFileReference(IDWriteFactory *iface,
413     WCHAR const *path, FILETIME const *writetime, IDWriteFontFile **font_file)
414 {
415     FIXME("(%s %p %p): stub\n", debugstr_w(path), writetime, font_file);
416     return E_NOTIMPL;
417 }
418
419 static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory *iface,
420     void const *reference_key, UINT32 key_size, IDWriteFontFileLoader *loader, IDWriteFontFile **font_file)
421 {
422     FIXME("(%p %u %p %p): stub\n", reference_key, key_size, loader, font_file);
423     return E_NOTIMPL;
424 }
425
426 static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory *iface,
427     DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files,
428     UINT32 index, DWRITE_FONT_SIMULATIONS sim_flags, IDWriteFontFace **font_face)
429 {
430     FIXME("(%d %u %p %u 0x%x %p): stub\n", facetype, files_number, font_files, index, sim_flags, font_face);
431     return E_NOTIMPL;
432 }
433
434 static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory *iface, IDWriteRenderingParams **params)
435 {
436     HMONITOR monitor;
437     POINT pt;
438
439     TRACE("(%p)\n", params);
440
441     pt.x = pt.y = 0;
442     monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
443     return IDWriteFactory_CreateMonitorRenderingParams(iface, monitor, params);
444 }
445
446 static HRESULT WINAPI dwritefactory_CreateMonitorRenderingParams(IDWriteFactory *iface, HMONITOR monitor,
447     IDWriteRenderingParams **params)
448 {
449     static int fixme_once = 0;
450
451     TRACE("(%p %p)\n", monitor, params);
452
453     if (!fixme_once++)
454         FIXME("(%p): monitor setting ignored\n", monitor);
455     return IDWriteFactory_CreateCustomRenderingParams(iface, 0.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT,
456         DWRITE_RENDERING_MODE_DEFAULT, params);
457 }
458
459 static HRESULT WINAPI dwritefactory_CreateCustomRenderingParams(IDWriteFactory *iface, FLOAT gamma, FLOAT enhancedContrast,
460     FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode, IDWriteRenderingParams **params)
461 {
462     TRACE("(%f %f %f %d %d %p)\n", gamma, enhancedContrast, cleartype_level, geometry, mode, params);
463     return create_renderingparams(gamma, enhancedContrast, cleartype_level, geometry, mode, params);
464 }
465
466 static HRESULT WINAPI dwritefactory_RegisterFontFileLoader(IDWriteFactory *iface, IDWriteFontFileLoader *loader)
467 {
468     FIXME("(%p): stub\n", loader);
469     return E_NOTIMPL;
470 }
471
472 static HRESULT WINAPI dwritefactory_UnregisterFontFileLoader(IDWriteFactory *iface, IDWriteFontFileLoader *loader)
473 {
474     FIXME("(%p): stub\n", loader);
475     return E_NOTIMPL;
476 }
477
478 static HRESULT WINAPI dwritefactory_CreateTextFormat(IDWriteFactory *iface, WCHAR const* family_name,
479     IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
480     DWRITE_FONT_STRETCH stretch, FLOAT size, WCHAR const *locale, IDWriteTextFormat **format)
481 {
482     TRACE("(%s %p %d %d %d %f %s %p)\n", debugstr_w(family_name), collection, weight, style, stretch,
483         size, debugstr_w(locale), format);
484
485     if (collection)
486         FIXME("font collection not supported\n");
487
488     return create_textformat(family_name, weight, style, stretch, size, locale, format);
489 }
490
491 static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory *iface, IDWriteTypography **typography)
492 {
493     FIXME("(%p): stub\n", typography);
494     return E_NOTIMPL;
495 }
496
497 static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory *iface, IDWriteGdiInterop **gdi_interop)
498 {
499     TRACE("(%p)\n", gdi_interop);
500     return create_gdiinterop(gdi_interop);
501 }
502
503 static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory *iface, WCHAR const* string,
504     UINT32 len, IDWriteTextFormat *format, FLOAT max_width, FLOAT max_height, IDWriteTextLayout **layout)
505 {
506     FIXME("(%s %u %p %f %f %p): stub\n", debugstr_w(string), len, format, max_width, max_height, layout);
507
508     if (!format) return E_INVALIDARG;
509     return create_textlayout(string, len, layout);
510 }
511
512 static HRESULT WINAPI dwritefactory_CreateGdiCompatibleTextLayout(IDWriteFactory *iface, WCHAR const* string,
513     UINT32 len, IDWriteTextFormat *format, FLOAT layout_width, FLOAT layout_height, FLOAT pixels_per_dip,
514     DWRITE_MATRIX const* transform, BOOL use_gdi_natural, IDWriteTextLayout **layout)
515 {
516     FIXME("(%s:%u %p %f %f %f %p %d %p): semi-stub\n", debugstr_wn(string, len), len, format, layout_width, layout_height,
517         pixels_per_dip, transform, use_gdi_natural, layout);
518
519     if (!format) return E_INVALIDARG;
520     return create_textlayout(string, len, layout);
521 }
522
523 static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory *iface, IDWriteTextFormat *format,
524     IDWriteInlineObject **trimming_sign)
525 {
526     FIXME("(%p %p): stub\n", format, trimming_sign);
527     return E_NOTIMPL;
528 }
529
530 static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory *iface, IDWriteTextAnalyzer **analyzer)
531 {
532     FIXME("(%p): stub\n", analyzer);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI dwritefactory_CreateNumberSubstitution(IDWriteFactory *iface, DWRITE_NUMBER_SUBSTITUTION_METHOD method,
537     WCHAR const* locale, BOOL ignore_user_override, IDWriteNumberSubstitution **substitution)
538 {
539     FIXME("(%d %s %d %p): stub\n", method, debugstr_w(locale), ignore_user_override, substitution);
540     return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI dwritefactory_CreateGlyphRunAnalysis(IDWriteFactory *iface, DWRITE_GLYPH_RUN const *glyph_run,
544     FLOAT pixels_per_dip, DWRITE_MATRIX const* transform, DWRITE_RENDERING_MODE rendering_mode,
545     DWRITE_MEASURING_MODE measuring_mode, FLOAT baseline_x, FLOAT baseline_y, IDWriteGlyphRunAnalysis **analysis)
546 {
547     FIXME("(%p %f %p %d %d %f %f %p): stub\n", glyph_run, pixels_per_dip, transform, rendering_mode,
548         measuring_mode, baseline_x, baseline_y, analysis);
549     return E_NOTIMPL;
550 }
551
552 static const struct IDWriteFactoryVtbl dwritefactoryvtbl = {
553     dwritefactory_QueryInterface,
554     dwritefactory_AddRef,
555     dwritefactory_Release,
556     dwritefactory_GetSystemFontCollection,
557     dwritefactory_CreateCustomFontCollection,
558     dwritefactory_RegisterFontCollectionLoader,
559     dwritefactory_UnregisterFontCollectionLoader,
560     dwritefactory_CreateFontFileReference,
561     dwritefactory_CreateCustomFontFileReference,
562     dwritefactory_CreateFontFace,
563     dwritefactory_CreateRenderingParams,
564     dwritefactory_CreateMonitorRenderingParams,
565     dwritefactory_CreateCustomRenderingParams,
566     dwritefactory_RegisterFontFileLoader,
567     dwritefactory_UnregisterFontFileLoader,
568     dwritefactory_CreateTextFormat,
569     dwritefactory_CreateTypography,
570     dwritefactory_GetGdiInterop,
571     dwritefactory_CreateTextLayout,
572     dwritefactory_CreateGdiCompatibleTextLayout,
573     dwritefactory_CreateEllipsisTrimmingSign,
574     dwritefactory_CreateTextAnalyzer,
575     dwritefactory_CreateNumberSubstitution,
576     dwritefactory_CreateGlyphRunAnalysis
577 };
578
579 static IDWriteFactory dwritefactory = { &dwritefactoryvtbl };
580
581 HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **factory)
582 {
583     TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), factory);
584
585     if (!IsEqualIID(riid, &IID_IDWriteFactory)) return E_FAIL;
586
587     *factory = (IUnknown*)&dwritefactory;
588
589     return S_OK;
590 }