msvcrt: Avoid locking the file in _fclose_nolock.
[wine.git] / dlls / dwrite / gdiinterop.c
blobb099e5262f3cd1be6a2d9a9a0828d1f1087a525b
1 /*
2 * GDI Interop
4 * Copyright 2012 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 IDWriteFactory *factory;
39 struct rendertarget {
40 IDWriteBitmapRenderTarget IDWriteBitmapRenderTarget_iface;
41 LONG ref;
43 FLOAT pixels_per_dip;
44 DWRITE_MATRIX m;
45 SIZE size;
46 HDC hdc;
49 static HRESULT create_target_dibsection(HDC hdc, UINT32 width, UINT32 height)
51 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
52 BITMAPINFO *bmi = (BITMAPINFO*)bmibuf;
53 HBITMAP hbm;
55 memset(bmi, 0, sizeof(bmibuf));
56 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
57 bmi->bmiHeader.biHeight = height;
58 bmi->bmiHeader.biWidth = width;
59 bmi->bmiHeader.biBitCount = 32;
60 bmi->bmiHeader.biPlanes = 1;
61 bmi->bmiHeader.biCompression = BI_RGB;
63 hbm = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
64 if (!hbm)
65 hbm = CreateBitmap(1, 1, 1, 1, NULL);
67 DeleteObject(SelectObject(hdc, hbm));
68 return S_OK;
71 static inline struct rendertarget *impl_from_IDWriteBitmapRenderTarget(IDWriteBitmapRenderTarget *iface)
73 return CONTAINING_RECORD(iface, struct rendertarget, IDWriteBitmapRenderTarget_iface);
76 static inline struct gdiinterop *impl_from_IDWriteGdiInterop(IDWriteGdiInterop *iface)
78 return CONTAINING_RECORD(iface, struct gdiinterop, IDWriteGdiInterop_iface);
81 static HRESULT WINAPI rendertarget_QueryInterface(IDWriteBitmapRenderTarget *iface, REFIID riid, void **obj)
83 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
85 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
87 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteBitmapRenderTarget))
89 *obj = iface;
90 IDWriteBitmapRenderTarget_AddRef(iface);
91 return S_OK;
94 *obj = NULL;
96 return E_NOINTERFACE;
99 static ULONG WINAPI rendertarget_AddRef(IDWriteBitmapRenderTarget *iface)
101 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
102 ULONG ref = InterlockedIncrement(&This->ref);
103 TRACE("(%p)->(%d)\n", This, ref);
104 return ref;
107 static ULONG WINAPI rendertarget_Release(IDWriteBitmapRenderTarget *iface)
109 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
110 ULONG ref = InterlockedDecrement(&This->ref);
112 TRACE("(%p)->(%d)\n", This, ref);
114 if (!ref)
116 DeleteDC(This->hdc);
117 heap_free(This);
120 return ref;
123 static HRESULT WINAPI rendertarget_DrawGlyphRun(IDWriteBitmapRenderTarget *iface,
124 FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuring_mode,
125 DWRITE_GLYPH_RUN const* glyph_run, IDWriteRenderingParams* params, COLORREF textColor,
126 RECT *blackbox_rect)
128 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
129 FIXME("(%p)->(%f %f %d %p %p 0x%08x %p): stub\n", This, baselineOriginX, baselineOriginY,
130 measuring_mode, glyph_run, params, textColor, blackbox_rect);
131 return E_NOTIMPL;
134 static HDC WINAPI rendertarget_GetMemoryDC(IDWriteBitmapRenderTarget *iface)
136 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
137 TRACE("(%p)\n", This);
138 return This->hdc;
141 static FLOAT WINAPI rendertarget_GetPixelsPerDip(IDWriteBitmapRenderTarget *iface)
143 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
144 TRACE("(%p)\n", This);
145 return This->pixels_per_dip;
148 static HRESULT WINAPI rendertarget_SetPixelsPerDip(IDWriteBitmapRenderTarget *iface, FLOAT pixels_per_dip)
150 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
152 TRACE("(%p)->(%.2f)\n", This, pixels_per_dip);
154 if (pixels_per_dip <= 0.0)
155 return E_INVALIDARG;
157 This->pixels_per_dip = pixels_per_dip;
158 return S_OK;
161 static HRESULT WINAPI rendertarget_GetCurrentTransform(IDWriteBitmapRenderTarget *iface, DWRITE_MATRIX *transform)
163 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
165 TRACE("(%p)->(%p)\n", This, transform);
167 *transform = This->m;
168 return S_OK;
171 static HRESULT WINAPI rendertarget_SetCurrentTransform(IDWriteBitmapRenderTarget *iface, DWRITE_MATRIX const *transform)
173 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
174 FIXME("(%p)->(%p): stub\n", This, transform);
175 return E_NOTIMPL;
178 static HRESULT WINAPI rendertarget_GetSize(IDWriteBitmapRenderTarget *iface, SIZE *size)
180 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
182 TRACE("(%p)->(%p)\n", This, size);
183 *size = This->size;
184 return S_OK;
187 static HRESULT WINAPI rendertarget_Resize(IDWriteBitmapRenderTarget *iface, UINT32 width, UINT32 height)
189 struct rendertarget *This = impl_from_IDWriteBitmapRenderTarget(iface);
191 TRACE("(%p)->(%u %u)\n", This, width, height);
193 if (This->size.cx == width && This->size.cy == height)
194 return S_OK;
196 return create_target_dibsection(This->hdc, width, height);
199 static const IDWriteBitmapRenderTargetVtbl rendertargetvtbl = {
200 rendertarget_QueryInterface,
201 rendertarget_AddRef,
202 rendertarget_Release,
203 rendertarget_DrawGlyphRun,
204 rendertarget_GetMemoryDC,
205 rendertarget_GetPixelsPerDip,
206 rendertarget_SetPixelsPerDip,
207 rendertarget_GetCurrentTransform,
208 rendertarget_SetCurrentTransform,
209 rendertarget_GetSize,
210 rendertarget_Resize
213 static HRESULT create_rendertarget(HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **ret)
215 struct rendertarget *target;
216 HRESULT hr;
218 *ret = NULL;
220 target = heap_alloc(sizeof(struct rendertarget));
221 if (!target) return E_OUTOFMEMORY;
223 target->IDWriteBitmapRenderTarget_iface.lpVtbl = &rendertargetvtbl;
224 target->ref = 1;
226 target->size.cx = width;
227 target->size.cy = height;
229 target->hdc = CreateCompatibleDC(hdc);
230 hr = create_target_dibsection(target->hdc, width, height);
231 if (FAILED(hr)) {
232 IDWriteBitmapRenderTarget_Release(&target->IDWriteBitmapRenderTarget_iface);
233 return hr;
236 target->m.m11 = target->m.m22 = 1.0;
237 target->m.m12 = target->m.m21 = 0.0;
238 target->m.dx = target->m.dy = 0.0;
239 target->pixels_per_dip = 1.0;
241 *ret = &target->IDWriteBitmapRenderTarget_iface;
243 return S_OK;
246 static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop *iface, REFIID riid, void **obj)
248 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
250 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
252 if (IsEqualIID(riid, &IID_IDWriteGdiInterop) ||
253 IsEqualIID(riid, &IID_IUnknown))
255 *obj = iface;
256 IDWriteGdiInterop_AddRef(iface);
257 return S_OK;
260 *obj = NULL;
261 return E_NOINTERFACE;
264 static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop *iface)
266 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
267 TRACE("(%p)\n", This);
268 return IDWriteFactory_AddRef(This->factory);
271 static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop *iface)
273 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
274 TRACE("(%p)\n", This);
275 return IDWriteFactory_Release(This->factory);
278 static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop *iface,
279 LOGFONTW const *logfont, IDWriteFont **font)
281 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
282 IDWriteFontCollection *collection;
283 IDWriteFontFamily *family;
284 DWRITE_FONT_STYLE style;
285 BOOL exists = FALSE;
286 UINT32 index;
287 HRESULT hr;
289 TRACE("(%p)->(%p %p)\n", This, logfont, font);
291 *font = NULL;
293 if (!logfont) return E_INVALIDARG;
295 hr = IDWriteFactory_GetSystemFontCollection(This->factory, &collection, FALSE);
296 if (FAILED(hr)) {
297 ERR("failed to get system font collection: 0x%08x.\n", hr);
298 return hr;
301 hr = IDWriteFontCollection_FindFamilyName(collection, logfont->lfFaceName, &index, &exists);
302 if (FAILED(hr)) {
303 IDWriteFontCollection_Release(collection);
304 goto done;
307 if (!exists) {
308 hr = DWRITE_E_NOFONT;
309 goto done;
312 hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
313 if (FAILED(hr))
314 goto done;
316 style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
317 hr = IDWriteFontFamily_GetFirstMatchingFont(family, logfont->lfWeight, DWRITE_FONT_STRETCH_NORMAL, style, font);
318 IDWriteFontFamily_Release(family);
320 done:
321 IDWriteFontCollection_Release(collection);
322 return hr;
325 static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop *iface,
326 IDWriteFont *font, LOGFONTW *logfont, BOOL *is_systemfont)
328 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
329 FIXME("(%p)->(%p %p %p): stub\n", This, font, logfont, is_systemfont);
330 return E_NOTIMPL;
333 static HRESULT WINAPI gdiinterop_ConvertFontFaceToLOGFONT(IDWriteGdiInterop *iface,
334 IDWriteFontFace *fontface, LOGFONTW *logfont)
336 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
337 TRACE("(%p)->(%p %p)\n", This, fontface, logfont);
338 return convert_fontface_to_logfont(fontface, logfont);
341 static HRESULT WINAPI gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop *iface,
342 HDC hdc, IDWriteFontFace **fontface)
344 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
345 IDWriteFont *font;
346 LOGFONTW logfont;
347 HFONT hfont;
348 HRESULT hr;
350 TRACE("(%p)->(%p %p)\n", This, hdc, fontface);
352 *fontface = NULL;
354 hfont = GetCurrentObject(hdc, OBJ_FONT);
355 if (!hfont)
356 return E_INVALIDARG;
357 GetObjectW(hfont, sizeof(logfont), &logfont);
359 hr = IDWriteGdiInterop_CreateFontFromLOGFONT(iface, &logfont, &font);
360 if (FAILED(hr))
361 return hr;
363 hr = IDWriteFont_CreateFontFace(font, fontface);
364 IDWriteFont_Release(font);
366 return hr;
369 static HRESULT WINAPI gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop *iface,
370 HDC hdc, UINT32 width, UINT32 height, IDWriteBitmapRenderTarget **target)
372 struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface);
373 TRACE("(%p)->(%p %u %u %p)\n", This, hdc, width, height, target);
374 return create_rendertarget(hdc, width, height, target);
377 static const struct IDWriteGdiInteropVtbl gdiinteropvtbl = {
378 gdiinterop_QueryInterface,
379 gdiinterop_AddRef,
380 gdiinterop_Release,
381 gdiinterop_CreateFontFromLOGFONT,
382 gdiinterop_ConvertFontToLOGFONT,
383 gdiinterop_ConvertFontFaceToLOGFONT,
384 gdiinterop_CreateFontFaceFromHdc,
385 gdiinterop_CreateBitmapRenderTarget
388 HRESULT create_gdiinterop(IDWriteFactory *factory, IDWriteGdiInterop **ret)
390 struct gdiinterop *This;
392 *ret = NULL;
394 This = heap_alloc(sizeof(struct gdiinterop));
395 if (!This) return E_OUTOFMEMORY;
397 This->IDWriteGdiInterop_iface.lpVtbl = &gdiinteropvtbl;
398 This->factory = factory;
400 *ret= &This->IDWriteGdiInterop_iface;
401 return S_OK;
404 void release_gdiinterop(IDWriteGdiInterop *iface)
406 struct gdiinterop *interop = impl_from_IDWriteGdiInterop(iface);
407 heap_free(interop);