dsound: Report buffer notifications in offset order.
[wine.git] / dlls / dwrite / gdiinterop.c
blob23da98b958789e007394294040c5d5d08c89df91
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 static const DWRITE_MATRIX identity =
36 1.0f, 0.0f,
37 0.0f, 1.0f,
38 0.0f, 0.0f
41 struct gdiinterop {
42 IDWriteGdiInterop IDWriteGdiInterop_iface;
43 IDWriteFactory *factory;
46 struct rendertarget {
47 IDWriteBitmapRenderTarget1 IDWriteBitmapRenderTarget1_iface;
48 LONG ref;
50 DWRITE_TEXT_ANTIALIAS_MODE antialiasmode;
51 FLOAT pixels_per_dip;
52 DWRITE_MATRIX m;
53 SIZE size;
54 HDC hdc;
57 static HRESULT create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
59 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
60 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
61 HBITMAP hbm;
63 memset(bmi, 0, sizeof(bmibuf));
64 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
65 bmi->bmiHeader.biHeight = height;
66 bmi->bmiHeader.biWidth = width;
67 bmi->bmiHeader.biBitCount = 32;
68 bmi->bmiHeader.biPlanes = 1;
69 bmi->bmiHeader.biCompression = BI_RGB;
71 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
72 if (!hbm)
73 hbm = CreateBitmap(1, 1, 1, 1, NULL);
75 DeleteObject(SelectObject(hdc, hbm));
76 return S_OK;
79 static inline struct rendertarget *impl_from_IDWriteBitmapRenderTarget1(IDWriteBitmapRenderTarget1 *iface)
81 return CONTAINING_RECORD(iface, struct rendertarget, IDWriteBitmapRenderTarget1_iface);
84 static inline struct gdiinterop *impl_from_IDWriteGdiInterop(IDWriteGdiInterop *iface)
86 return CONTAINING_RECORD(iface, struct gdiinterop, IDWriteGdiInterop_iface);
89 static HRESULT WINAPI rendertarget_QueryInterface(IDWriteBitmapRenderTarget1 *iface, REFIID riid, void **obj)
91 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
93 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
95 if (IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget1) ||
96 IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget) ||
97 IsEqualIID(riid, &IID_IUnknown))
99 *obj = iface;
100 IDWriteBitmapRenderTarget1_AddRef(iface);
101 return S_OK;
104 *obj = NULL;
106 return E_NOINTERFACE;
109 static ULONG WINAPI rendertarget_AddRef(IDWriteBitmapRenderTarget1 *iface)
111 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
112 ULONG ref = InterlockedIncrement(&This->ref);
113 TRACE("(%p)->(%d)\n", This, ref);
114 return ref;
117 static ULONG WINAPI rendertarget_Release(IDWriteBitmapRenderTarget1 *iface)
119 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
120 ULONG ref = InterlockedDecrement(&This->ref);
122 TRACE("(%p)->(%d)\n", This, ref);
124 if (!ref)
126 DeleteDC(This->hdc);
127 heap_free(This);
130 return ref;
133 static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget1 *iface,
134 FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuring_mode,
135 DWRITE_GLYPH_RUN const* glyph_run, IDWriteRenderingParams* params, COLORREF textColor,
136 RECT *blackbox_rect)
138 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
139 FIXME("(%p)->(%f %f %d %p %p 0x%08x %p): stub\n", This, baselineOriginX, baselineOriginY,
140 measuring_mode, glyph_run, params, textColor, blackbox_rect);
141 return E_NOTIMPL;
144 static HDC WINAPI rendertarget_GetMemoryDC(IDWriteBitmapRenderTarget1 *iface)
146 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
147 TRACE("(%p)\n", This);
148 return This->hdc;
151 static FLOAT WINAPI rendertarget_GetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface)
153 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
154 TRACE("(%p)\n", This);
155 return This->pixels_per_dip;
158 static HRESULT WINAPI rendertarget_SetPixelsPerDip(IDWriteBitmapRenderTarget1 *iface, FLOAT pixels_per_dip)
160 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
162 TRACE("(%p)->(%.2f)\n", This, pixels_per_dip);
164 if (pixels_per_dip <= 0.0)
165 return E_INVALIDARG;
167 This->pixels_per_dip = pixels_per_dip;
168 return S_OK;
171 static HRESULT WINAPI rendertarget_GetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX *transform)
173 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
175 TRACE("(%p)->(%p)\n", This, transform);
177 *transform = This->m;
178 return S_OK;
181 static HRESULT WINAPI rendertarget_SetCurrentTransform(IDWriteBitmapRenderTarget1 *iface, DWRITE_MATRIX const *transform)
183 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
185 TRACE("(%p)->(%p)\n", This, transform);
187 This->m = transform ? *transform : identity;
188 return S_OK;
191 static HRESULT WINAPI rendertarget_GetSize(IDWriteBitmapRenderTarget1 *iface, SIZE *size)
193 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
195 TRACE("(%p)->(%p)\n", This, size);
196 *size = This->size;
197 return S_OK;
200 static HRESULT WINAPI rendertarget_Resize(IDWriteBitmapRenderTarget1 *iface, UINT32 width, UINT32 height)
202 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
204 TRACE("(%p)->(%u %u)\n", This, width, height);
206 if (This->size.cx == width && This->size.cy == height)
207 return S_OK;
209 return create_target_dibsection(This->hdc, width, height);
212 static DWRITE_TEXT_ANTIALIAS_MODE WINAPI rendertarget_GetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface)
214 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
215 TRACE("(%p)\n", This);
216 return This->antialiasmode;
219 static HRESULT WINAPI rendertarget_SetTextAntialiasMode(IDWriteBitmapRenderTarget1 *iface, DWRITE_TEXT_ANTIALIAS_MODE mode)
221 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget1(iface);
223 TRACE("(%p)->(%d)\n", This, mode);
225 if ((DWORD)mode > DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
226 return E_INVALIDARG;
228 This->antialiasmode = mode;
229 return S_OK;
232 static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl = {
233 rendertarget_QueryInterface,
234 rendertarget_AddRef,
235 rendertarget_Release,
236 rendertarget_DrawGlyphRun,
237 rendertarget_GetMemoryDC,
238 rendertarget_GetPixelsPerDip,
239 rendertarget_SetPixelsPerDip,
240 rendertarget_GetCurrentTransform,
241 rendertarget_SetCurrentTransform,
242 rendertarget_GetSize,
243 rendertarget_Resize,
244 rendertarget_GetTextAntialiasMode,
245 rendertarget_SetTextAntialiasMode
248 static HRESULT create_rendertarget(HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
250 struct rendertarget *target;
251 HRESULT hr;
253 *ret = NULL;
255 target = heap_alloc(sizeof(struct rendertarget));
256 if (!target) return E_OUTOFMEMORY;
258 target->IDWriteBitmapRenderTarget1_iface.lpVtbl = &rendertargetvtbl;
259 target->ref = 1;
261 target->size.cx = width;
262 target->size.cy = height;
264 target->hdc = CreateCompatibleDC(hdc);
265 hr = create_target_dibsection(target->hdc, width, height);
266 if (FAILED(hr)) {
267 IDWriteBitmapRenderTarget1_Release(&target->IDWriteBitmapRenderTarget1_iface);
268 return hr;
271 target->m = identity;
272 target->pixels_per_dip = 1.0;
273 target->antialiasmode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
275 *ret = (IDWriteBitmapRenderTarget*)&target->IDWriteBitmapRenderTarget1_iface;
277 return S_OK;
280 static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop *iface, REFIID riid, void **obj)
282 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
284 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
286 if (IsEqualIID(riid, &IID_IDWriteGdiInterop) ||
287 IsEqualIID(riid, &IID_IUnknown))
289 *obj = iface;
290 IDWriteGdiInterop_AddRef(iface);
291 return S_OK;
294 *obj = NULL;
295 return E_NOINTERFACE;
298 static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop *iface)
300 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
301 TRACE("(%p)\n", This);
302 return IDWriteFactory_AddRef(This->factory);
305 static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop *iface)
307 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
308 TRACE("(%p)\n", This);
309 return IDWriteFactory_Release(This->factory);
312 static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop *iface,
313 LOGFONTW const *logfont, IDWriteFont **font)
315 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
316 IDWriteFontCollection *collection;
317 IDWriteFontFamily *family;
318 DWRITE_FONT_STYLE style;
319 BOOL exists = FALSE;
320 UINT32 index;
321 HRESULT hr;
323 TRACE("(%p)->(%p %p)\n", This, logfont, font);
325 *font = NULL;
327 if (!logfont) return E_INVALIDARG;
329 hr = IDWriteFactory_GetSystemFontCollection(This->factory, &collection, FALSE);
330 if (FAILED(hr)) {
331 ERR("failed to get system font collection: 0x%08x.\n", hr);
332 return hr;
335 hr = IDWriteFontCollection_FindFamilyName(collection, logfont->lfFaceName, &index, &exists);
336 if (FAILED(hr)) {
337 IDWriteFontCollection_Release(collection);
338 goto done;
341 if (!exists) {
342 hr = DWRITE_E_NOFONT;
343 goto done;
346 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
347 if (FAILED(hr))
348 goto done;
350 style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
351 hr = IDWriteFontFamily_GetFirstMatchingFont(family, logfont->lfWeight, DWRITE_FONT_STRETCH_NORMAL, style, font);
352 IDWriteFontFamily_Release(family);
354 done:
355 IDWriteFontCollection_Release(collection);
356 return hr;
359 static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop *iface,
360 IDWriteFont *font, LOGFONTW *logfont, BOOL *is_systemfont)
362 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
363 static const WCHAR enusW[] = {'e','n','-','u','s',0};
364 DWRITE_FONT_SIMULATIONS simulations;
365 IDWriteFontCollection *collection;
366 IDWriteLocalizedStrings *name;
367 IDWriteFontFamily *family;
368 DWRITE_FONT_STYLE style;
369 UINT32 index;
370 BOOL exists;
371 HRESULT hr;
373 TRACE("(%p)->(%p %p %p)\n", This, font, logfont, is_systemfont);
375 *is_systemfont = FALSE;
377 if (!font)
378 return E_INVALIDARG;
380 hr = IDWriteFont_GetFontFamily(font, &family);
381 if (FAILED(hr))
382 return hr;
384 hr = IDWriteFontFamily_GetFontCollection(family, &collection);
385 IDWriteFontFamily_Release(family);
386 if (FAILED(hr))
387 return hr;
389 *is_systemfont = is_system_collection(collection);
390 IDWriteFontCollection_Release(collection);
392 simulations = IDWriteFont_GetSimulations(font);
393 style = IDWriteFont_GetStyle(font);
395 logfont->lfCharSet = DEFAULT_CHARSET;
396 logfont->lfWeight = IDWriteFont_GetWeight(font);
397 logfont->lfItalic = style == DWRITE_FONT_STYLE_ITALIC || (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE);
398 logfont->lfOutPrecision = OUT_OUTLINE_PRECIS;
399 logfont->lfFaceName[0] = 0;
401 exists = FALSE;
402 hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &name, &exists);
403 if (FAILED(hr) || !exists)
404 return hr;
406 IDWriteLocalizedStrings_FindLocaleName(name, enusW, &index, &exists);
407 IDWriteLocalizedStrings_GetString(name, index, logfont->lfFaceName, sizeof(logfont->lfFaceName)/sizeof(WCHAR));
408 IDWriteLocalizedStrings_Release(name);
410 return S_OK;
413 static HRESULT WINAPI gdiinterop_ConvertFontFaceToLOGFONT(IDWriteGdiInterop *iface,
414 IDWriteFontFace *fontface, LOGFONTW *logfont)
416 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
417 TRACE("(%p)->(%p %p)\n", This, fontface, logfont);
418 return convert_fontface_to_logfont(fontface, logfont);
421 static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop *iface,
422 HDC hdc, IDWriteFontFace **fontface)
424 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
425 IDWriteFont *font;
426 LOGFONTW logfont;
427 HFONT hfont;
428 HRESULT hr;
430 TRACE("(%p)->(%p %p)\n", This, hdc, fontface);
432 *fontface = NULL;
434 hfont = GetCurrentObject(hdc, OBJ_FONT);
435 if (!hfont)
436 return E_INVALIDARG;
437 GetObjectW(hfont, sizeof(logfont), &logfont);
439 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(iface, &logfont, &font);
440 if (FAILED(hr))
441 return hr;
443 hr = IDWriteFont_CreateFontFace(font, fontface);
444 IDWriteFont_Release(font);
446 return hr;
449 static HRESULT WINAPI gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop *iface,
450 HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **target)
452 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
453 TRACE("(%p)->(%p %u %u %p)\n", This, hdc, width, height, target);
454 return create_rendertarget(hdc, width, height, target);
457 static const struct IDWriteGdiInteropVtbl gdiinteropvtbl = {
458 gdiinterop_QueryInterface,
459 gdiinterop_AddRef,
460 gdiinterop_Release,
461 gdiinterop_CreateFontFromLOGFONT,
462 gdiinterop_ConvertFontToLOGFONT,
463 gdiinterop_ConvertFontFaceToLOGFONT,
464 gdiinterop_CreateFontFaceFromHdc,
465 gdiinterop_CreateBitmapRenderTarget
468 HRESULT create_gdiinterop(IDWriteFactory *factory, IDWriteGdiInterop **ret)
470 struct gdiinterop *This;
472 *ret = NULL;
474 This = heap_alloc(sizeof(struct gdiinterop));
475 if (!This) return E_OUTOFMEMORY;
477 This->IDWriteGdiInterop_iface.lpVtbl = &gdiinteropvtbl;
478 This->factory = factory;
480 *ret= &This->IDWriteGdiInterop_iface;
481 return S_OK;
484 void release_gdiinterop(IDWriteGdiInterop *iface)
486 struct gdiinterop *interop = impl_from_IDWriteGdiInterop(iface);
487 heap_free(interop);