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
24 #include "dwrite_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
30 /* PANOSE is 10 bytes in size, need to pack the structure properly */
50 SHORT glyphdata_format
;
57 SHORT underlinePosition
;
58 SHORT underlineThickness
;
73 SHORT ySubscriptXSize
;
74 SHORT ySubscriptYSize
;
75 SHORT ySubscriptXOffset
;
76 SHORT ySubscriptYOffset
;
77 SHORT ySuperscriptXSize
;
78 SHORT ySuperscriptYSize
;
79 SHORT ySuperscriptXOffset
;
80 SHORT ySuperscriptYOffset
;
82 SHORT yStrikeoutPosition
;
85 ULONG ulUnicodeRange1
;
86 ULONG ulUnicodeRange2
;
87 ULONG ulUnicodeRange3
;
88 ULONG ulUnicodeRange4
;
91 USHORT usFirstCharIndex
;
92 USHORT usLastCharIndex
;
93 /* According to the Apple spec, original version didn't have the below fields,
94 * version numbers were taken from the OpenType spec.
96 /* version 0 (TrueType 1.5) */
98 USHORT sTypoDescender
;
102 /* version 1 (TrueType 1.66) */
103 ULONG ulCodePageRange1
;
104 ULONG ulCodePageRange2
;
105 /* version 2 (OpenType 1.2) */
108 USHORT usDefaultChar
;
114 #ifdef WORDS_BIGENDIAN
115 #define GET_BE_WORD(x) (x)
116 #define GET_BE_DWORD(x) (x)
118 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
119 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
122 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
123 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
124 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
126 #define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
127 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
128 #define MS_POST_TAG MS_MAKE_TAG('p','o','s','t')
130 struct dwrite_fontcollection
{
131 IDWriteFontCollection IDWriteFontCollection_iface
;
138 static IDWriteFontCollection
*system_collection
;
140 struct dwrite_fontfamily
{
141 IDWriteFontFamily IDWriteFontFamily_iface
;
148 IDWriteFont IDWriteFont_iface
;
151 IDWriteFontFamily
*family
;
152 IDWriteFontFace
*face
;
153 DWRITE_FONT_STYLE style
;
154 DWRITE_FONT_STRETCH stretch
;
155 DWRITE_FONT_WEIGHT weight
;
156 DWRITE_FONT_METRICS metrics
;
160 struct dwrite_fontface
{
161 IDWriteFontFace IDWriteFontFace_iface
;
167 static HRESULT
create_fontfamily(const WCHAR
*familyname
, IDWriteFontFamily
**family
);
169 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
171 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace_iface
);
174 static inline struct dwrite_font
*impl_from_IDWriteFont(IDWriteFont
*iface
)
176 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont_iface
);
179 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily(IDWriteFontFamily
*iface
)
181 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily_iface
);
184 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
186 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
189 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace
*iface
, REFIID riid
, void **obj
)
191 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
193 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
195 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFace
))
198 IDWriteFontFace_AddRef(iface
);
203 return E_NOINTERFACE
;
206 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace
*iface
)
208 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
209 ULONG ref
= InterlockedIncrement(&This
->ref
);
210 TRACE("(%p)->(%d)\n", This
, ref
);
214 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace
*iface
)
216 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
217 ULONG ref
= InterlockedDecrement(&This
->ref
);
219 TRACE("(%p)->(%d)\n", This
, ref
);
227 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace
*iface
)
229 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
230 FIXME("(%p): stub\n", This
);
231 return DWRITE_FONT_FACE_TYPE_UNKNOWN
;
234 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace
*iface
, UINT32
*number_of_files
,
235 IDWriteFontFile
**fontfiles
)
237 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
238 FIXME("(%p)->(%p %p): stub\n", This
, number_of_files
, fontfiles
);
242 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace
*iface
)
244 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
245 FIXME("(%p): stub\n", This
);
249 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace
*iface
)
251 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
252 FIXME("(%p): stub\n", This
);
253 return DWRITE_FONT_SIMULATIONS_NONE
;
256 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace
*iface
)
258 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
259 FIXME("(%p): stub\n", This
);
263 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace
*iface
, DWRITE_FONT_METRICS
*metrics
)
265 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
266 FIXME("(%p)->(%p): stub\n", This
, metrics
);
269 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace
*iface
)
271 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
272 FIXME("(%p): stub\n", This
);
276 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace
*iface
,
277 UINT16
const *glyph_indices
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
279 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
280 FIXME("(%p)->(%p %u %p %d): stub\n", This
, glyph_indices
, glyph_count
, metrics
, is_sideways
);
284 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace
*iface
, UINT32
const *codepoints
,
285 UINT32 count
, UINT16
*glyph_indices
)
287 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
293 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
295 str
= heap_alloc(count
*sizeof(WCHAR
));
296 if (!str
) return E_OUTOFMEMORY
;
298 for (i
= 0; i
< count
; i
++)
299 str
[i
] = codepoints
[i
] < 0x10000 ? codepoints
[i
] : '?';
301 hdc
= CreateCompatibleDC(0);
302 hfont
= CreateFontIndirectW(&This
->logfont
);
303 SelectObject(hdc
, hfont
);
305 GetGlyphIndicesW(hdc
, str
, count
, glyph_indices
, 0);
314 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace
*iface
, UINT32 table_tag
,
315 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
317 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
318 FIXME("(%p)->(%u %p %p %p %p): stub\n", This
, table_tag
, table_data
, table_size
, context
, exists
);
322 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace
*iface
, void *table_context
)
324 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
325 FIXME("(%p)->(%p): stub\n", This
, table_context
);
328 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace
*iface
, FLOAT emSize
,
329 UINT16
const *glyph_indices
, FLOAT
const* glyph_advances
, DWRITE_GLYPH_OFFSET
const *glyph_offsets
,
330 UINT32 glyph_count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*geometrysink
)
332 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
333 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This
, emSize
, glyph_indices
, glyph_advances
, glyph_offsets
,
334 glyph_count
, is_sideways
, is_rtl
, geometrysink
);
338 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace
*iface
, FLOAT emSize
,
339 FLOAT pixels_per_dip
, DWRITE_MEASURING_MODE mode
, IDWriteRenderingParams
* params
, DWRITE_RENDERING_MODE
* rendering_mode
)
341 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
342 FIXME("(%p)->(%f %f %d %p %p): stub\n", This
, emSize
, pixels_per_dip
, mode
, params
, rendering_mode
);
346 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
347 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
349 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
350 FIXME("(%p)->(%f %f %p %p): stub\n", This
, emSize
, pixels_per_dip
, transform
, metrics
);
354 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
355 DWRITE_MATRIX
const *transform
, BOOL use_gdi_natural
, UINT16
const *glyph_indices
, UINT32 glyph_count
,
356 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
358 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace(iface
);
359 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This
, emSize
, pixels_per_dip
, transform
, use_gdi_natural
, glyph_indices
,
360 glyph_count
, metrics
, is_sideways
);
364 static const IDWriteFontFaceVtbl dwritefontfacevtbl
= {
365 dwritefontface_QueryInterface
,
366 dwritefontface_AddRef
,
367 dwritefontface_Release
,
368 dwritefontface_GetType
,
369 dwritefontface_GetFiles
,
370 dwritefontface_GetIndex
,
371 dwritefontface_GetSimulations
,
372 dwritefontface_IsSymbolFont
,
373 dwritefontface_GetMetrics
,
374 dwritefontface_GetGlyphCount
,
375 dwritefontface_GetDesignGlyphMetrics
,
376 dwritefontface_GetGlyphIndices
,
377 dwritefontface_TryGetFontTable
,
378 dwritefontface_ReleaseFontTable
,
379 dwritefontface_GetGlyphRunOutline
,
380 dwritefontface_GetRecommendedRenderingMode
,
381 dwritefontface_GetGdiCompatibleMetrics
,
382 dwritefontface_GetGdiCompatibleGlyphMetrics
385 static HRESULT
create_fontface(struct dwrite_font
*font
, IDWriteFontFace
**face
)
387 struct dwrite_fontface
*This
;
391 This
= heap_alloc(sizeof(struct dwrite_fontface
));
392 if (!This
) return E_OUTOFMEMORY
;
394 This
->IDWriteFontFace_iface
.lpVtbl
= &dwritefontfacevtbl
;
397 memset(&This
->logfont
, 0, sizeof(This
->logfont
));
398 This
->logfont
.lfItalic
= font
->style
== DWRITE_FONT_STYLE_ITALIC
;
399 strcpyW(This
->logfont
.lfFaceName
, font
->facename
);
401 *face
= &This
->IDWriteFontFace_iface
;
406 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont
*iface
, REFIID riid
, void **obj
)
408 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
410 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
412 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFont
))
415 IDWriteFont_AddRef(iface
);
420 return E_NOINTERFACE
;
423 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont
*iface
)
425 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
426 ULONG ref
= InterlockedIncrement(&This
->ref
);
427 TRACE("(%p)->(%d)\n", This
, ref
);
431 static ULONG WINAPI
dwritefont_Release(IDWriteFont
*iface
)
433 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
434 ULONG ref
= InterlockedDecrement(&This
->ref
);
436 TRACE("(%p)->(%d)\n", This
, ref
);
440 if (This
->face
) IDWriteFontFace_Release(This
->face
);
441 IDWriteFontFamily_Release(This
->family
);
442 heap_free(This
->facename
);
449 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont
*iface
, IDWriteFontFamily
**family
)
451 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
452 TRACE("(%p)->(%p)\n", This
, family
);
454 *family
= This
->family
;
455 IDWriteFontFamily_AddRef(*family
);
459 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont
*iface
)
461 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
462 TRACE("(%p)\n", This
);
466 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont
*iface
)
468 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
469 TRACE("(%p)\n", This
);
470 return This
->stretch
;
473 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont
*iface
)
475 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
476 TRACE("(%p)\n", This
);
480 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont
*iface
)
482 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
483 FIXME("(%p): stub\n", This
);
487 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont
*iface
, IDWriteLocalizedStrings
**names
)
489 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
490 FIXME("(%p)->(%p): stub\n", This
, names
);
494 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont
*iface
,
495 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
497 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
498 FIXME("(%p)->(%d %p %p): stub\n", This
, stringid
, strings
, exists
);
502 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont
*iface
)
504 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
505 FIXME("(%p): stub\n", This
);
506 return DWRITE_FONT_SIMULATIONS_NONE
;
509 static void WINAPI
dwritefont_GetMetrics(IDWriteFont
*iface
, DWRITE_FONT_METRICS
*metrics
)
511 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
513 TRACE("(%p)->(%p)\n", This
, metrics
);
514 *metrics
= This
->metrics
;
517 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont
*iface
, UINT32 value
, BOOL
*exists
)
519 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
520 FIXME("(%p)->(0x%08x %p): stub\n", This
, value
, exists
);
524 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont
*iface
, IDWriteFontFace
**face
)
526 struct dwrite_font
*This
= impl_from_IDWriteFont(iface
);
528 TRACE("(%p)->(%p)\n", This
, face
);
532 HRESULT hr
= create_fontface(This
, &This
->face
);
533 if (FAILED(hr
)) return hr
;
537 IDWriteFontFace_AddRef(*face
);
542 static const IDWriteFontVtbl dwritefontvtbl
= {
543 dwritefont_QueryInterface
,
546 dwritefont_GetFontFamily
,
547 dwritefont_GetWeight
,
548 dwritefont_GetStretch
,
550 dwritefont_IsSymbolFont
,
551 dwritefont_GetFaceNames
,
552 dwritefont_GetInformationalStrings
,
553 dwritefont_GetSimulations
,
554 dwritefont_GetMetrics
,
555 dwritefont_HasCharacter
,
556 dwritefont_CreateFontFace
559 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily
*iface
, REFIID riid
, void **obj
)
561 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
562 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
564 if (IsEqualIID(riid
, &IID_IUnknown
) ||
565 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
566 IsEqualIID(riid
, &IID_IDWriteFontFamily
))
569 IDWriteFontFamily_AddRef(iface
);
574 return E_NOINTERFACE
;
577 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily
*iface
)
579 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
580 ULONG ref
= InterlockedIncrement(&This
->ref
);
581 TRACE("(%p)->(%d)\n", This
, ref
);
585 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily
*iface
)
587 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
588 ULONG ref
= InterlockedDecrement(&This
->ref
);
590 TRACE("(%p)->(%d)\n", This
, ref
);
594 heap_free(This
->familyname
);
601 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily
*iface
, IDWriteFontCollection
**collection
)
603 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
604 FIXME("(%p)->(%p): stub\n", This
, collection
);
608 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily
*iface
)
610 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
611 FIXME("(%p): stub\n", This
);
615 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily
*iface
, UINT32 index
, IDWriteFont
**font
)
617 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
618 FIXME("(%p)->(%u %p): stub\n", This
, index
, font
);
622 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily
*iface
, IDWriteLocalizedStrings
**names
)
624 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
625 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
628 TRACE("(%p)->(%p)\n", This
, names
);
630 hr
= create_localizedstrings(names
);
631 if (FAILED(hr
)) return hr
;
633 return add_localizedstring(*names
, enusW
, This
->familyname
);
636 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
637 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
639 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
642 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
644 memset(&lf
, 0, sizeof(lf
));
645 lf
.lfWeight
= weight
;
646 lf
.lfItalic
= style
== DWRITE_FONT_STYLE_ITALIC
;
647 strcpyW(lf
.lfFaceName
, This
->familyname
);
649 return create_font_from_logfont(&lf
, font
);
652 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
653 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**fonts
)
655 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
656 FIXME("(%p)->(%d %d %d %p): stub\n", This
, weight
, stretch
, style
, fonts
);
660 static const IDWriteFontFamilyVtbl fontfamilyvtbl
= {
661 dwritefontfamily_QueryInterface
,
662 dwritefontfamily_AddRef
,
663 dwritefontfamily_Release
,
664 dwritefontfamily_GetFontCollection
,
665 dwritefontfamily_GetFontCount
,
666 dwritefontfamily_GetFont
,
667 dwritefontfamily_GetFamilyNames
,
668 dwritefontfamily_GetFirstMatchingFont
,
669 dwritefontfamily_GetMatchingFonts
672 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
674 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
675 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
677 if (IsEqualIID(riid
, &IID_IUnknown
) ||
678 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
681 IDWriteFontCollection_AddRef(iface
);
686 return E_NOINTERFACE
;
689 static ULONG WINAPI
dwritesysfontcollection_AddRef(IDWriteFontCollection
*iface
)
694 static ULONG WINAPI
dwritesysfontcollection_Release(IDWriteFontCollection
*iface
)
699 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
701 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
702 TRACE("(%p)\n", This
);
706 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
708 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
710 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
712 if (index
>= This
->count
)
718 return create_fontfamily(This
->families
[index
], family
);
721 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
723 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
726 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
728 for (i
= 0; i
< This
->count
; i
++)
729 if (!strcmpW(This
->families
[i
], name
))
742 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
744 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
745 FIXME("(%p)->(%p %p): stub\n", This
, face
, font
);
749 static const IDWriteFontCollectionVtbl systemfontcollectionvtbl
= {
750 dwritefontcollection_QueryInterface
,
751 dwritesysfontcollection_AddRef
,
752 dwritesysfontcollection_Release
,
753 dwritefontcollection_GetFontFamilyCount
,
754 dwritefontcollection_GetFontFamily
,
755 dwritefontcollection_FindFamilyName
,
756 dwritefontcollection_GetFontFromFontFace
759 static HRESULT
add_family_syscollection(struct dwrite_fontcollection
*collection
, const WCHAR
*family
)
761 /* check for duplicate family name */
762 if (collection
->count
&& !strcmpW(collection
->families
[collection
->count
-1], family
)) return S_OK
;
764 /* double array length */
765 if (collection
->count
== collection
->alloc
)
767 collection
->alloc
*= 2;
768 collection
->families
= heap_realloc(collection
->families
, collection
->alloc
*sizeof(WCHAR
*));
771 collection
->families
[collection
->count
++] = heap_strdupW(family
);
772 TRACE("family name %s\n", debugstr_w(family
));
777 static INT CALLBACK
enum_font_families(const LOGFONTW
*lf
, const TEXTMETRICW
*tm
, DWORD type
, LPARAM lParam
)
779 struct dwrite_fontcollection
*collection
= (struct dwrite_fontcollection
*)lParam
;
780 return add_family_syscollection(collection
, lf
->lfFaceName
) == S_OK
;
783 static void release_font_collection(IDWriteFontCollection
*iface
)
785 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
788 for (i
= 0; i
< This
->count
; i
++)
789 heap_free(This
->families
[i
]);
790 heap_free(This
->families
);
794 void release_system_fontcollection(void)
796 release_font_collection(system_collection
);
799 HRESULT
get_system_fontcollection(IDWriteFontCollection
**collection
)
801 if (!system_collection
)
803 struct dwrite_fontcollection
*This
;
809 This
= heap_alloc(sizeof(struct dwrite_fontcollection
));
810 if (!This
) return E_OUTOFMEMORY
;
812 This
->IDWriteFontCollection_iface
.lpVtbl
= &systemfontcollectionvtbl
;
815 This
->families
= heap_alloc(This
->alloc
*sizeof(WCHAR
*));
817 TRACE("building system font collection:\n");
819 hdc
= CreateCompatibleDC(0);
820 memset(&lf
, 0, sizeof(lf
));
821 lf
.lfCharSet
= DEFAULT_CHARSET
;
822 lf
.lfPitchAndFamily
= DEFAULT_PITCH
;
823 lf
.lfFaceName
[0] = 0;
824 EnumFontFamiliesExW(hdc
, &lf
, enum_font_families
, (LPARAM
)This
, 0);
827 if (InterlockedCompareExchangePointer((void**)&system_collection
, &This
->IDWriteFontCollection_iface
, NULL
))
828 release_font_collection(&This
->IDWriteFontCollection_iface
);
831 *collection
= system_collection
;
836 static HRESULT
create_fontfamily(const WCHAR
*familyname
, IDWriteFontFamily
**family
)
838 struct dwrite_fontfamily
*This
;
842 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
843 if (!This
) return E_OUTOFMEMORY
;
845 This
->IDWriteFontFamily_iface
.lpVtbl
= &fontfamilyvtbl
;
847 This
->familyname
= heap_strdupW(familyname
);
849 *family
= &This
->IDWriteFontFamily_iface
;
854 static void get_font_properties(struct dwrite_font
*font
, HDC hdc
)
861 /* default stretch and weight to normal */
862 font
->stretch
= DWRITE_FONT_STRETCH_NORMAL
;
863 font
->weight
= DWRITE_FONT_WEIGHT_NORMAL
;
865 memset(&font
->metrics
, 0, sizeof(font
->metrics
));
867 size
= GetFontData(hdc
, MS_OS2_TAG
, 0, NULL
, 0);
868 if (size
!= GDI_ERROR
)
870 if (size
> sizeof(tt_os2
)) size
= sizeof(tt_os2
);
872 memset(&tt_os2
, 0, sizeof(tt_os2
));
873 if (GetFontData(hdc
, MS_OS2_TAG
, 0, &tt_os2
, size
) != size
) return;
875 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
876 if (GET_BE_WORD(tt_os2
.usWidthClass
) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED
)
877 font
->stretch
= GET_BE_WORD(tt_os2
.usWidthClass
);
879 font
->weight
= GET_BE_WORD(tt_os2
.usWeightClass
);
880 TRACE("stretch=%d, weight=%d\n", font
->stretch
, font
->weight
);
882 font
->metrics
.ascent
= GET_BE_WORD(tt_os2
.sTypoAscender
);
883 font
->metrics
.descent
= GET_BE_WORD(tt_os2
.sTypoDescender
);
884 font
->metrics
.lineGap
= GET_BE_WORD(tt_os2
.sTypoLineGap
);
885 font
->metrics
.capHeight
= GET_BE_WORD(tt_os2
.sCapHeight
);
886 font
->metrics
.xHeight
= GET_BE_WORD(tt_os2
.sxHeight
);
887 font
->metrics
.strikethroughPosition
= GET_BE_WORD(tt_os2
.yStrikeoutPosition
);
888 font
->metrics
.strikethroughThickness
= GET_BE_WORD(tt_os2
.yStrikeoutSize
);
891 memset(&tt_head
, 0, sizeof(tt_head
));
892 if (GetFontData(hdc
, MS_HEAD_TAG
, 0, &tt_head
, sizeof(tt_head
)) != GDI_ERROR
)
894 font
->metrics
.designUnitsPerEm
= GET_BE_WORD(tt_head
.unitsPerEm
);
897 memset(&tt_post
, 0, sizeof(tt_post
));
898 if (GetFontData(hdc
, MS_POST_TAG
, 0, &tt_post
, sizeof(tt_post
)) != GDI_ERROR
)
900 font
->metrics
.underlinePosition
= GET_BE_WORD(tt_post
.underlinePosition
);
901 font
->metrics
.underlineThickness
= GET_BE_WORD(tt_post
.underlineThickness
);
905 HRESULT
create_font_from_logfont(const LOGFONTW
*logfont
, IDWriteFont
**font
)
907 const WCHAR
* facename
, *familyname
;
908 struct dwrite_font
*This
;
909 IDWriteFontFamily
*family
;
910 OUTLINETEXTMETRICW
*otm
;
918 This
= heap_alloc(sizeof(struct dwrite_font
));
919 if (!This
) return E_OUTOFMEMORY
;
921 hfont
= CreateFontIndirectW(logfont
);
925 return DWRITE_E_NOFONT
;
928 hdc
= CreateCompatibleDC(0);
929 SelectObject(hdc
, hfont
);
931 ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
932 otm
= heap_alloc(ret
);
934 ret
= GetOutlineTextMetricsW(hdc
, otm
->otmSize
, otm
);
936 get_font_properties(This
, hdc
);
941 facename
= (WCHAR
*)((char*)otm
+ (ptrdiff_t)otm
->otmpFaceName
);
942 familyname
= (WCHAR
*)((char*)otm
+ (ptrdiff_t)otm
->otmpFamilyName
);
943 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename
), debugstr_w(familyname
));
945 hr
= create_fontfamily(familyname
, &family
);
953 This
->IDWriteFont_iface
.lpVtbl
= &dwritefontvtbl
;
956 This
->family
= family
;
957 This
->style
= logfont
->lfItalic
? DWRITE_FONT_STYLE_ITALIC
: DWRITE_FONT_STYLE_NORMAL
;
958 This
->facename
= heap_strdupW(logfont
->lfFaceName
);
960 *font
= &This
->IDWriteFont_iface
;