user32/tests: Don't test function directly when reporting GetLastError().
[wine/multimedia.git] / dlls / dwrite / gdiinterop.c
blobbead01d778d86367ca6691cc132497fe3aee5b23
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(HDC hdc, UINT32 width, UINT32 height)
52 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
53 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
54 HBITMAP hbm;
56 memset(bmi, 0, sizeof(bmibuf));
57 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
58 bmi->bmiHeader.biHeight = height;
59 bmi->bmiHeader.biWidth = width;
60 bmi->bmiHeader.biBitCount = 32;
61 bmi->bmiHeader.biPlanes = 1;
62 bmi->bmiHeader.biCompression = BI_RGB;
64 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
65 if (!hbm)
66 hbm = CreateBitmap(1, 1, 1, 1, NULL);
68 DeleteObject(SelectObject(hdc, hbm));
69 return S_OK;
72 static inline struct rendertarget *impl_from_IDWriteBitmapRenderTarget1(IDWriteBitmapRenderTarget1 *iface)
74 return CONTAINING_RECORD(iface, struct rendertarget, IDWriteBitmapRenderTarget1_iface);
77 static inline struct gdiinterop *impl_from_IDWriteGdiInterop(IDWriteGdiInterop *iface)
79 return CONTAINING_RECORD(iface, struct gdiinterop, IDWriteGdiInterop_iface);
82 static HRESULT WINAPI rendertarget_QueryInterface(IDWriteBitmapRenderTarget1 *iface, REFIID riid, void **obj)
84 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
86 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
88 if (IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget1) ||
89 IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget) ||
90 IsEqualIID(riid, &IID_IUnknown))
92 *obj = iface;
93 IDWriteBitmapRenderTarget1_AddRef(iface);
94 return S_OK;
97 *obj = NULL;
99 return E_NOINTERFACE;
102 static ULONG WINAPI rendertarget_AddRef(IDWriteBitmapRenderTarget1 *iface)
104 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
105 ULONG ref = InterlockedIncrement(&This->ref);
106 TRACE("(%p)->(%d)\n", This, ref);
107 return ref;
110 static ULONG WINAPI rendertarget_Release(IDWriteBitmapRenderTarget1 *iface)
112 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
113 ULONG ref = InterlockedDecrement(&This->ref);
115 TRACE("(%p)->(%d)\n", This, ref);
117 if (!ref)
119 DeleteDC(This->hdc);
120 heap_free(This);
123 return ref;
126 static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *iface,
127 FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuring_mode,
128 DWRITE_GLYPH_RUN const* glyph_run, IDWriteRenderingParams* params, COLORREF textColor,
129 RECT *blackbox_rect)
131 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
132 FIXME("(%p)->(%f %f %d %p %p 0x%08x %p): stub\n", This, baselineOriginX, baselineOriginY,
133 measuring_mode, glyph_run, params, textColor, blackbox_rect);
134 return E_NOTIMPL;
137 static HDC WINAPI rendertarget_GetMemoryDC(IDWriteBitmapRenderTarget1 *iface)
139 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
140 TRACE("(%p)\n", This);
141 return This->hdc;
144 static FLOAT WINAPI rendertarget_GetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface)
146 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
147 TRACE("(%p)\n", This);
148 return This->pixels_per_dip;
151 static HRESULT WINAPI rendertarget_SetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface, FLOAT pixels_per_dip)
153 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
155 TRACE("(%p)->(%.2f)\n", This, pixels_per_dip);
157 if (pixels_per_dip <= 0.0)
158 return E_INVALIDARG;
160 This->pixels_per_dip = pixels_per_dip;
161 return S_OK;
164 static HRESULT WINAPI rendertarget_GetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX *transform)
166 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
168 TRACE("(%p)->(%p)\n", This, transform);
170 *transform = This->m;
171 return S_OK;
174 static HRESULT WINAPI rendertarget_SetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX const *transform)
176 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
178 TRACE("(%p)->(%p)\n", This, transform);
180 This->m = transform ? *transform : identity;
181 return S_OK;
184 static HRESULT WINAPI rendertarget_GetSize(IDWriteBitmapRenderTarget1 *iface, SIZE *size)
186 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
188 TRACE("(%p)->(%p)\n", This, size);
189 *size = This->size;
190 return S_OK;
193 static HRESULT WINAPI rendertarget_Resize(IDWriteBitmapRenderTarget1 *iface, UINT32 width, UINT32 height)
195 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
197 TRACE("(%p)->(%u %u)\n", This, width, height);
199 if (This->size.cx == width && This->size.cy == height)
200 return S_OK;
202 return create_target_dibsection(This->hdc, width, height);
205 static DWRITE_TEXT_ANTIALIAS_MODE WINAPI rendertarget_GetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface)
207 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
208 TRACE("(%p)\n", This);
209 return This->antialiasmode;
212 static HRESULT WINAPI rendertarget_SetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface, DWRITE_TEXT_ANTIALIAS_MODE mode)
214 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
216 TRACE("(%p)->(%d)\n", This, mode);
218 if ((DWORD)mode > DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
219 return E_INVALIDARG;
221 This->antialiasmode = mode;
222 return S_OK;
225 static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl = {
226 rendertarget_QueryInterface,
227 rendertarget_AddRef,
228 rendertarget_Release,
229 rendertarget_DrawGlyphRun,
230 rendertarget_GetMemoryDC,
231 rendertarget_GetPixelsPerDip,
232 rendertarget_SetPixelsPerDip,
233 rendertarget_GetCurrentTransform,
234 rendertarget_SetCurrentTransform,
235 rendertarget_GetSize,
236 rendertarget_Resize,
237 rendertarget_GetTextAntialiasMode,
238 rendertarget_SetTextAntialiasMode
241 static HRESULT create_rendertarget(HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
243 struct rendertarget *target;
244 HRESULT hr;
246 *ret = NULL;
248 target = heap_alloc(sizeof(struct rendertarget));
249 if (!target) return E_OUTOFMEMORY;
251 target->IDWriteBitmapRenderTarget1_iface.lpVtbl = &rendertargetvtbl;
252 target->ref = 1;
254 target->size.cx = width;
255 target->size.cy = height;
257 target->hdc = CreateCompatibleDC(hdc);
258 hr = create_target_dibsection(target->hdc, 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 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
410 TRACE("(%p)->(%p %p)\n", This, fontface, logfont);
411 return convert_fontface_to_logfont(fontface, logfont);
414 static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop *iface,
415 HDC hdc, IDWriteFontFace **fontface)
417 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
418 IDWriteFont *font;
419 LOGFONTW logfont;
420 HFONT hfont;
421 HRESULT hr;
423 TRACE("(%p)->(%p %p)\n", This, hdc, fontface);
425 *fontface = NULL;
427 hfont = GetCurrentObject(hdc, OBJ_FONT);
428 if (!hfont)
429 return E_INVALIDARG;
430 GetObjectW(hfont, sizeof(logfont), &logfont);
432 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(iface, &logfont, &font);
433 if (FAILED(hr))
434 return hr;
436 hr = IDWriteFont_CreateFontFace(font, fontface);
437 IDWriteFont_Release(font);
439 return hr;
442 static HRESULT WINAPI gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop *iface,
443 HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **target)
445 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
446 TRACE("(%p)->(%p %u %u %p)\n", This, hdc, width, height, target);
447 return create_rendertarget(hdc, width, height, target);
450 static const struct IDWriteGdiInteropVtbl gdiinteropvtbl = {
451 gdiinterop_QueryInterface,
452 gdiinterop_AddRef,
453 gdiinterop_Release,
454 gdiinterop_CreateFontFromLOGFONT,
455 gdiinterop_ConvertFontToLOGFONT,
456 gdiinterop_ConvertFontFaceToLOGFONT,
457 gdiinterop_CreateFontFaceFromHdc,
458 gdiinterop_CreateBitmapRenderTarget
461 HRESULT create_gdiinterop(IDWriteFactory2 *factory, IDWriteGdiInterop **ret)
463 struct gdiinterop *This;
465 *ret = NULL;
467 This = heap_alloc(sizeof(struct gdiinterop));
468 if (!This) return E_OUTOFMEMORY;
470 This->IDWriteGdiInterop_iface.lpVtbl = &gdiinteropvtbl;
471 This->factory = factory;
473 *ret= &This->IDWriteGdiInterop_iface;
474 return S_OK;
477 void release_gdiinterop(IDWriteGdiInterop *iface)
479 struct gdiinterop *interop = impl_from_IDWriteGdiInterop(iface);
480 heap_free(interop);