vcomp/tests: Add tests for atomic double functions.
[wine.git] / dlls / dwrite / gdiinterop.c
blobaeb61ebe5cd7c1130bd7aafedf827eb4fff885bf
1 /*
2 * GDI Interop
4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "dwrite_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
34 struct gdiinterop {
35 IDWriteGdiInterop IDWriteGdiInterop_iface;
36 IDWriteFactory2 *factory;
39 struct rendertarget {
40 IDWriteBitmapRenderTarget1 IDWriteBitmapRenderTarget1_iface;
41 LONG ref;
43 DWRITE_TEXT_ANTIALIAS_MODE antialiasmode;
44 FLOAT pixels_per_dip;
45 DWRITE_MATRIX m;
46 SIZE size;
47 HDC hdc;
50 static HRESULT create_target_dibsection(struct rendertarget *target, UINT32 width, UINT32 height)
52 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
53 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
54 HBITMAP hbm;
56 target->size.cx = width;
57 target->size.cy = height;
59 memset(bmi, 0, sizeof(bmibuf));
60 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
61 bmi->bmiHeader.biHeight = -height;
62 bmi->bmiHeader.biWidth = width;
63 bmi->bmiHeader.biBitCount = 32;
64 bmi->bmiHeader.biPlanes = 1;
65 bmi->bmiHeader.biCompression = BI_RGB;
67 hbm = CreateDIBSection(target->hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
68 if (!hbm)
69 hbm = CreateBitmap(1, 1, 1, 1, NULL);
71 DeleteObject(SelectObject(target->hdc, hbm));
72 return S_OK;
75 static inline struct rendertarget *impl_from_IDWriteBitmapRenderTarget1(IDWriteBitmapRenderTarget1 *iface)
77 return CONTAINING_RECORD(iface, struct rendertarget, IDWriteBitmapRenderTarget1_iface);
80 static inline struct gdiinterop *impl_from_IDWriteGdiInterop(IDWriteGdiInterop *iface)
82 return CONTAINING_RECORD(iface, struct gdiinterop, IDWriteGdiInterop_iface);
85 static HRESULT WINAPI rendertarget_QueryInterface(IDWriteBitmapRenderTarget1 *iface, REFIID riid, void **obj)
87 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
89 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
91 if (IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget1) ||
92 IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget) ||
93 IsEqualIID(riid, &IID_IUnknown))
95 *obj = iface;
96 IDWriteBitmapRenderTarget1_AddRef(iface);
97 return S_OK;
100 *obj = NULL;
102 return E_NOINTERFACE;
105 static ULONG WINAPI rendertarget_AddRef(IDWriteBitmapRenderTarget1 *iface)
107 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
108 ULONG ref = InterlockedIncrement(&This->ref);
109 TRACE("(%p)->(%d)\n", This, ref);
110 return ref;
113 static ULONG WINAPI rendertarget_Release(IDWriteBitmapRenderTarget1 *iface)
115 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
116 ULONG ref = InterlockedDecrement(&This->ref);
118 TRACE("(%p)->(%d)\n", This, ref);
120 if (!ref)
122 DeleteDC(This->hdc);
123 heap_free(This);
126 return ref;
129 static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *iface,
130 FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuring_mode,
131 DWRITE_GLYPH_RUN const* glyph_run, IDWriteRenderingParams* params, COLORREF textColor,
132 RECT *blackbox_rect)
134 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
135 FIXME("(%p)->(%f %f %d %p %p 0x%08x %p): stub\n", This, baselineOriginX, baselineOriginY,
136 measuring_mode, glyph_run, params, textColor, blackbox_rect);
137 return E_NOTIMPL;
140 static HDC WINAPI rendertarget_GetMemoryDC(IDWriteBitmapRenderTarget1 *iface)
142 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
143 TRACE("(%p)\n", This);
144 return This->hdc;
147 static FLOAT WINAPI rendertarget_GetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface)
149 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
150 TRACE("(%p)\n", This);
151 return This->pixels_per_dip;
154 static HRESULT WINAPI rendertarget_SetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface, FLOAT pixels_per_dip)
156 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
158 TRACE("(%p)->(%.2f)\n", This, pixels_per_dip);
160 if (pixels_per_dip <= 0.0)
161 return E_INVALIDARG;
163 This->pixels_per_dip = pixels_per_dip;
164 return S_OK;
167 static HRESULT WINAPI rendertarget_GetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX *transform)
169 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
171 TRACE("(%p)->(%p)\n", This, transform);
173 *transform = This->m;
174 return S_OK;
177 static HRESULT WINAPI rendertarget_SetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX const *transform)
179 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
181 TRACE("(%p)->(%p)\n", This, transform);
183 This->m = transform ? *transform : identity;
184 return S_OK;
187 static HRESULT WINAPI rendertarget_GetSize(IDWriteBitmapRenderTarget1 *iface, SIZE *size)
189 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
191 TRACE("(%p)->(%p)\n", This, size);
192 *size = This->size;
193 return S_OK;
196 static HRESULT WINAPI rendertarget_Resize(IDWriteBitmapRenderTarget1 *iface, UINT32 width, UINT32 height)
198 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
200 TRACE("(%p)->(%u %u)\n", This, width, height);
202 if (This->size.cx == width && This->size.cy == height)
203 return S_OK;
205 return create_target_dibsection(This, width, height);
208 static DWRITE_TEXT_ANTIALIAS_MODE WINAPI rendertarget_GetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface)
210 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
211 TRACE("(%p)\n", This);
212 return This->antialiasmode;
215 static HRESULT WINAPI rendertarget_SetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface, DWRITE_TEXT_ANTIALIAS_MODE mode)
217 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
219 TRACE("(%p)->(%d)\n", This, mode);
221 if ((DWORD)mode > DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
222 return E_INVALIDARG;
224 This->antialiasmode = mode;
225 return S_OK;
228 static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl = {
229 rendertarget_QueryInterface,
230 rendertarget_AddRef,
231 rendertarget_Release,
232 rendertarget_DrawGlyphRun,
233 rendertarget_GetMemoryDC,
234 rendertarget_GetPixelsPerDip,
235 rendertarget_SetPixelsPerDip,
236 rendertarget_GetCurrentTransform,
237 rendertarget_SetCurrentTransform,
238 rendertarget_GetSize,
239 rendertarget_Resize,
240 rendertarget_GetTextAntialiasMode,
241 rendertarget_SetTextAntialiasMode
244 static HRESULT create_rendertarget(HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
246 struct rendertarget *target;
247 HRESULT hr;
249 *ret = NULL;
251 target = heap_alloc(sizeof(struct rendertarget));
252 if (!target) return E_OUTOFMEMORY;
254 target->IDWriteBitmapRenderTarget1_iface.lpVtbl = &rendertargetvtbl;
255 target->ref = 1;
257 target->hdc = CreateCompatibleDC(hdc);
258 hr = create_target_dibsection(target, width, height);
259 if (FAILED(hr)) {
260 IDWriteBitmapRenderTarget1_Release(&target->IDWriteBitmapRenderTarget1_iface);
261 return hr;
264 target->m = identity;
265 target->pixels_per_dip = 1.0;
266 target->antialiasmode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
268 *ret = (IDWriteBitmapRenderTarget*)&target->IDWriteBitmapRenderTarget1_iface;
270 return S_OK;
273 static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop *iface, REFIID riid, void **obj)
275 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
277 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
279 if (IsEqualIID(riid, &IID_IDWriteGdiInterop) ||
280 IsEqualIID(riid, &IID_IUnknown))
282 *obj = iface;
283 IDWriteGdiInterop_AddRef(iface);
284 return S_OK;
287 *obj = NULL;
288 return E_NOINTERFACE;
291 static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop *iface)
293 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
294 TRACE("(%p)\n", This);
295 return IDWriteFactory2_AddRef(This->factory);
298 static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop *iface)
300 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
301 TRACE("(%p)\n", This);
302 return IDWriteFactory2_Release(This->factory);
305 static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop *iface,
306 LOGFONTW const *logfont, IDWriteFont **font)
308 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
309 IDWriteFontCollection *collection;
310 IDWriteFontFamily *family;
311 DWRITE_FONT_STYLE style;
312 BOOL exists = FALSE;
313 UINT32 index;
314 HRESULT hr;
316 TRACE("(%p)->(%p %p)\n", This, logfont, font);
318 *font = NULL;
320 if (!logfont) return E_INVALIDARG;
322 hr = IDWriteFactory2_GetSystemFontCollection(This->factory, &collection, FALSE);
323 if (FAILED(hr)) {
324 ERR("failed to get system font collection: 0x%08x.\n", hr);
325 return hr;
328 hr = IDWriteFontCollection_FindFamilyName(collection, logfont->lfFaceName, &index, &exists);
329 if (FAILED(hr)) {
330 IDWriteFontCollection_Release(collection);
331 goto done;
334 if (!exists) {
335 hr = DWRITE_E_NOFONT;
336 goto done;
339 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
340 if (FAILED(hr))
341 goto done;
343 style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
344 hr = IDWriteFontFamily_GetFirstMatchingFont(family, logfont->lfWeight, DWRITE_FONT_STRETCH_NORMAL, style, font);
345 IDWriteFontFamily_Release(family);
347 done:
348 IDWriteFontCollection_Release(collection);
349 return hr;
352 static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop *iface,
353 IDWriteFont *font, LOGFONTW *logfont, BOOL *is_systemfont)
355 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
356 static const WCHAR enusW[] = {'e','n','-','u','s',0};
357 DWRITE_FONT_SIMULATIONS simulations;
358 IDWriteFontCollection *collection;
359 IDWriteLocalizedStrings *name;
360 IDWriteFontFamily *family;
361 DWRITE_FONT_STYLE style;
362 UINT32 index;
363 BOOL exists;
364 HRESULT hr;
366 TRACE("(%p)->(%p %p %p)\n", This, font, logfont, is_systemfont);
368 *is_systemfont = FALSE;
370 if (!font)
371 return E_INVALIDARG;
373 hr = IDWriteFont_GetFontFamily(font, &family);
374 if (FAILED(hr))
375 return hr;
377 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
378 IDWriteFontFamily_Release(family);
379 if (FAILED(hr))
380 return hr;
382 *is_systemfont = is_system_collection(collection);
383 IDWriteFontCollection_Release(collection);
385 simulations = IDWriteFont_GetSimulations(font);
386 style = IDWriteFont_GetStyle(font);
388 logfont->lfCharSet = DEFAULT_CHARSET;
389 logfont->lfWeight = IDWriteFont_GetWeight(font);
390 logfont->lfItalic = style == DWRITE_FONT_STYLE_ITALIC || (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE);
391 logfont->lfOutPrecision = OUT_OUTLINE_PRECIS;
392 logfont->lfFaceName[0] = 0;
394 exists = FALSE;
395 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &name, &exists);
396 if (FAILED(hr) || !exists)
397 return hr;
399 IDWriteLocalizedStrings_FindLocaleName(name, enusW, &index, &exists);
400 IDWriteLocalizedStrings_GetString(name, index, logfont->lfFaceName, sizeof(logfont->lfFaceName)/sizeof(WCHAR));
401 IDWriteLocalizedStrings_Release(name);
403 return S_OK;
406 static HRESULT WINAPI gdiinterop_ConvertFontFaceToLOGFONT(IDWriteGdiInterop *iface,
407 IDWriteFontFace *fontface, LOGFONTW *logfont)
409 static const WCHAR enusW[] = {'e','n','-','u','s',0};
410 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
411 IDWriteLocalizedStrings *familynames;
412 DWRITE_FONT_SIMULATIONS simulations;
413 DWRITE_FONT_FACE_TYPE face_type;
414 struct dwrite_font_props props;
415 IDWriteFontFileStream *stream;
416 IDWriteFontFile *file = NULL;
417 UINT32 index;
418 BOOL exists;
419 HRESULT hr;
421 TRACE("(%p)->(%p %p)\n", This, fontface, logfont);
423 memset(logfont, 0, sizeof(*logfont));
425 index = 1;
426 hr = IDWriteFontFace_GetFiles(fontface, &index, &file);
427 if (FAILED(hr) || !file)
428 return hr;
430 hr = get_filestream_from_file(file, &stream);
431 if (FAILED(hr)) {
432 IDWriteFontFile_Release(file);
433 return hr;
436 index = IDWriteFontFace_GetIndex(fontface);
437 face_type = IDWriteFontFace_GetType(fontface);
438 opentype_get_font_properties(stream, face_type, index, &props);
439 hr = get_family_names_from_stream(stream, index, face_type, &familynames);
440 IDWriteFontFile_Release(file);
441 IDWriteFontFileStream_Release(stream);
442 if (FAILED(hr))
443 return hr;
445 simulations = IDWriteFontFace_GetSimulations(fontface);
447 logfont->lfCharSet = DEFAULT_CHARSET;
448 logfont->lfWeight = props.weight;
449 logfont->lfItalic = props.style == DWRITE_FONT_STYLE_ITALIC || (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE);
450 logfont->lfOutPrecision = OUT_OUTLINE_PRECIS;
451 logfont->lfFaceName[0] = 0;
453 exists = FALSE;
454 hr = IDWriteLocalizedStrings_FindLocaleName(familynames, enusW, &index, &exists);
455 if (FAILED(hr) || !exists) {
456 /* fallback to 0 index */
457 if (IDWriteLocalizedStrings_GetCount(familynames) > 0)
458 index = 0;
459 else {
460 IDWriteLocalizedStrings_Release(familynames);
461 return E_FAIL;
465 hr = IDWriteLocalizedStrings_GetString(familynames, index, logfont->lfFaceName, sizeof(logfont->lfFaceName)/sizeof(WCHAR));
466 IDWriteLocalizedStrings_Release(familynames);
468 return hr;
471 static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop *iface,
472 HDC hdc, IDWriteFontFace **fontface)
474 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
475 IDWriteFont *font;
476 LOGFONTW logfont;
477 HFONT hfont;
478 HRESULT hr;
480 TRACE("(%p)->(%p %p)\n", This, hdc, fontface);
482 *fontface = NULL;
484 hfont = GetCurrentObject(hdc, OBJ_FONT);
485 if (!hfont)
486 return E_INVALIDARG;
487 GetObjectW(hfont, sizeof(logfont), &logfont);
489 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(iface, &logfont, &font);
490 if (FAILED(hr))
491 return hr;
493 hr = IDWriteFont_CreateFontFace(font, fontface);
494 IDWriteFont_Release(font);
496 return hr;
499 static HRESULT WINAPI gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop *iface,
500 HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **target)
502 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
503 TRACE("(%p)->(%p %u %u %p)\n", This, hdc, width, height, target);
504 return create_rendertarget(hdc, width, height, target);
507 static const struct IDWriteGdiInteropVtbl gdiinteropvtbl = {
508 gdiinterop_QueryInterface,
509 gdiinterop_AddRef,
510 gdiinterop_Release,
511 gdiinterop_CreateFontFromLOGFONT,
512 gdiinterop_ConvertFontToLOGFONT,
513 gdiinterop_ConvertFontFaceToLOGFONT,
514 gdiinterop_CreateFontFaceFromHdc,
515 gdiinterop_CreateBitmapRenderTarget
518 HRESULT create_gdiinterop(IDWriteFactory2 *factory, IDWriteGdiInterop **ret)
520 struct gdiinterop *This;
522 *ret = NULL;
524 This = heap_alloc(sizeof(struct gdiinterop));
525 if (!This) return E_OUTOFMEMORY;
527 This->IDWriteGdiInterop_iface.lpVtbl = &gdiinteropvtbl;
528 This->factory = factory;
530 *ret= &This->IDWriteGdiInterop_iface;
531 return S_OK;
534 void release_gdiinterop(IDWriteGdiInterop *iface)
536 struct gdiinterop *interop = impl_from_IDWriteGdiInterop(iface);
537 heap_free(interop);