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
28 #include "dwrite_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
35 IDWriteGdiInterop IDWriteGdiInterop_iface
;
36 IDWriteFactory2
*factory
;
40 IDWriteBitmapRenderTarget1 IDWriteBitmapRenderTarget1_iface
;
43 DWRITE_TEXT_ANTIALIAS_MODE antialiasmode
;
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
;
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);
66 hbm
= CreateBitmap(1, 1, 1, 1, NULL
);
68 DeleteObject(SelectObject(hdc
, hbm
));
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
))
93 IDWriteBitmapRenderTarget1_AddRef(iface
);
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
);
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
);
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
,
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
);
137 static HDC WINAPI
rendertarget_GetMemoryDC(IDWriteBitmapRenderTarget1
*iface
)
139 struct rendertarget
*This
= impl_from_IDWriteBitmapRenderTarget1(iface
);
140 TRACE("(%p)\n", This
);
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)
160 This
->pixels_per_dip
= pixels_per_dip
;
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
;
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
;
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
);
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
)
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
)
221 This
->antialiasmode
= mode
;
225 static const IDWriteBitmapRenderTarget1Vtbl rendertargetvtbl
= {
226 rendertarget_QueryInterface
,
228 rendertarget_Release
,
229 rendertarget_DrawGlyphRun
,
230 rendertarget_GetMemoryDC
,
231 rendertarget_GetPixelsPerDip
,
232 rendertarget_SetPixelsPerDip
,
233 rendertarget_GetCurrentTransform
,
234 rendertarget_SetCurrentTransform
,
235 rendertarget_GetSize
,
237 rendertarget_GetTextAntialiasMode
,
238 rendertarget_SetTextAntialiasMode
241 static HRESULT
create_rendertarget(HDC hdc
, UINT32 width
, UINT32 height
, IDWriteBitmapRenderTarget
**ret
)
243 struct rendertarget
*target
;
248 target
= heap_alloc(sizeof(struct rendertarget
));
249 if (!target
) return E_OUTOFMEMORY
;
251 target
->IDWriteBitmapRenderTarget1_iface
.lpVtbl
= &rendertargetvtbl
;
254 target
->size
.cx
= width
;
255 target
->size
.cy
= height
;
257 target
->hdc
= CreateCompatibleDC(hdc
);
258 hr
= create_target_dibsection(target
->hdc
, width
, height
);
260 IDWriteBitmapRenderTarget1_Release(&target
->IDWriteBitmapRenderTarget1_iface
);
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
;
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
))
283 IDWriteGdiInterop_AddRef(iface
);
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
;
316 TRACE("(%p)->(%p %p)\n", This
, logfont
, font
);
320 if (!logfont
) return E_INVALIDARG
;
322 hr
= IDWriteFactory2_GetSystemFontCollection(This
->factory
, &collection
, FALSE
);
324 ERR("failed to get system font collection: 0x%08x.\n", hr
);
328 hr
= IDWriteFontCollection_FindFamilyName(collection
, logfont
->lfFaceName
, &index
, &exists
);
330 IDWriteFontCollection_Release(collection
);
335 hr
= DWRITE_E_NOFONT
;
339 hr
= IDWriteFontCollection_GetFontFamily(collection
, index
, &family
);
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
);
348 IDWriteFontCollection_Release(collection
);
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
;
366 TRACE("(%p)->(%p %p %p)\n", This
, font
, logfont
, is_systemfont
);
368 *is_systemfont
= FALSE
;
373 hr
= IDWriteFont_GetFontFamily(font
, &family
);
377 hr
= IDWriteFontFamily_GetFontCollection(family
, &collection
);
378 IDWriteFontFamily_Release(family
);
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;
395 hr
= IDWriteFont_GetInformationalStrings(font
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &name
, &exists
);
396 if (FAILED(hr
) || !exists
)
399 IDWriteLocalizedStrings_FindLocaleName(name
, enusW
, &index
, &exists
);
400 IDWriteLocalizedStrings_GetString(name
, index
, logfont
->lfFaceName
, sizeof(logfont
->lfFaceName
)/sizeof(WCHAR
));
401 IDWriteLocalizedStrings_Release(name
);
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 IDWriteFontFileStream
*stream
;
415 DWRITE_FONT_STRETCH stretch
;
416 DWRITE_FONT_STYLE style
;
417 DWRITE_FONT_WEIGHT weight
;
418 IDWriteFontFile
*file
= NULL
;
423 TRACE("(%p)->(%p %p)\n", This
, fontface
, logfont
);
425 memset(logfont
, 0, sizeof(*logfont
));
428 hr
= IDWriteFontFace_GetFiles(fontface
, &index
, &file
);
429 if (FAILED(hr
) || !file
)
432 hr
= get_filestream_from_file(file
, &stream
);
434 IDWriteFontFile_Release(file
);
438 index
= IDWriteFontFace_GetIndex(fontface
);
439 face_type
= IDWriteFontFace_GetType(fontface
);
440 opentype_get_font_properties(stream
, face_type
, index
, &stretch
, &weight
, &style
);
441 hr
= get_family_names_from_stream(stream
, index
, face_type
, &familynames
);
442 IDWriteFontFile_Release(file
);
443 IDWriteFontFileStream_Release(stream
);
447 simulations
= IDWriteFontFace_GetSimulations(fontface
);
449 logfont
->lfCharSet
= DEFAULT_CHARSET
;
450 logfont
->lfWeight
= weight
;
451 logfont
->lfItalic
= style
== DWRITE_FONT_STYLE_ITALIC
|| (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
);
452 logfont
->lfOutPrecision
= OUT_OUTLINE_PRECIS
;
453 logfont
->lfFaceName
[0] = 0;
456 hr
= IDWriteLocalizedStrings_FindLocaleName(familynames
, enusW
, &index
, &exists
);
457 if (FAILED(hr
) || !exists
) {
458 /* fallback to 0 index */
459 if (IDWriteLocalizedStrings_GetCount(familynames
) > 0)
462 IDWriteLocalizedStrings_Release(familynames
);
467 hr
= IDWriteLocalizedStrings_GetString(familynames
, index
, logfont
->lfFaceName
, sizeof(logfont
->lfFaceName
)/sizeof(WCHAR
));
468 IDWriteLocalizedStrings_Release(familynames
);
473 static HRESULT WINAPI
gdiinterop_CreateFontFaceFromHdc(IDWriteGdiInterop
*iface
,
474 HDC hdc
, IDWriteFontFace
**fontface
)
476 struct gdiinterop
*This
= impl_from_IDWriteGdiInterop(iface
);
482 TRACE("(%p)->(%p %p)\n", This
, hdc
, fontface
);
486 hfont
= GetCurrentObject(hdc
, OBJ_FONT
);
489 GetObjectW(hfont
, sizeof(logfont
), &logfont
);
491 hr
= IDWriteGdiInterop_CreateFontFromLOGFONT(iface
, &logfont
, &font
);
495 hr
= IDWriteFont_CreateFontFace(font
, fontface
);
496 IDWriteFont_Release(font
);
501 static HRESULT WINAPI
gdiinterop_CreateBitmapRenderTarget(IDWriteGdiInterop
*iface
,
502 HDC hdc
, UINT32 width
, UINT32 height
, IDWriteBitmapRenderTarget
**target
)
504 struct gdiinterop
*This
= impl_from_IDWriteGdiInterop(iface
);
505 TRACE("(%p)->(%p %u %u %p)\n", This
, hdc
, width
, height
, target
);
506 return create_rendertarget(hdc
, width
, height
, target
);
509 static const struct IDWriteGdiInteropVtbl gdiinteropvtbl
= {
510 gdiinterop_QueryInterface
,
513 gdiinterop_CreateFontFromLOGFONT
,
514 gdiinterop_ConvertFontToLOGFONT
,
515 gdiinterop_ConvertFontFaceToLOGFONT
,
516 gdiinterop_CreateFontFaceFromHdc
,
517 gdiinterop_CreateBitmapRenderTarget
520 HRESULT
create_gdiinterop(IDWriteFactory2
*factory
, IDWriteGdiInterop
**ret
)
522 struct gdiinterop
*This
;
526 This
= heap_alloc(sizeof(struct gdiinterop
));
527 if (!This
) return E_OUTOFMEMORY
;
529 This
->IDWriteGdiInterop_iface
.lpVtbl
= &gdiinteropvtbl
;
530 This
->factory
= factory
;
532 *ret
= &This
->IDWriteGdiInterop_iface
;
536 void release_gdiinterop(IDWriteGdiInterop
*iface
)
538 struct gdiinterop
*interop
= impl_from_IDWriteGdiInterop(iface
);