4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
5 * Copyright 2014 Aric Stewart for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/list.h"
25 #include "dwrite_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
29 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
30 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
31 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
32 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
33 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
35 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
37 struct dwrite_font_data
{
40 DWRITE_FONT_STYLE style
;
41 DWRITE_FONT_STRETCH stretch
;
42 DWRITE_FONT_WEIGHT weight
;
43 DWRITE_FONT_METRICS1 metrics
;
44 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
46 /* data needed to create fontface instance */
47 IDWriteFactory
*factory
;
48 DWRITE_FONT_FACE_TYPE face_type
;
49 IDWriteFontFile
*file
;
55 struct dwrite_fontfamily_data
{
58 IDWriteLocalizedStrings
*familyname
;
60 struct dwrite_font_data
**fonts
;
65 struct dwrite_fontcollection
{
66 IDWriteFontCollection IDWriteFontCollection_iface
;
69 struct dwrite_fontfamily_data
**family_data
;
75 struct dwrite_fontfamily
{
76 IDWriteFontFamily IDWriteFontFamily_iface
;
79 struct dwrite_fontfamily_data
*data
;
81 IDWriteFontCollection
* collection
;
85 IDWriteFont2 IDWriteFont2_iface
;
88 IDWriteFontFamily
*family
;
91 struct dwrite_font_data
*data
;
94 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
96 struct dwrite_fonttablecontext
{
102 struct dwrite_fonttable
{
108 struct dwrite_fontface
{
109 IDWriteFontFace2 IDWriteFontFace2_iface
;
112 IDWriteFontFileStream
**streams
;
113 IDWriteFontFile
**files
;
118 DWRITE_FONT_FACE_TYPE type
;
119 DWRITE_FONT_METRICS1 metrics
;
121 struct dwrite_fonttable cmap
;
122 struct ft_fontface
*ft
;
125 struct dwrite_fontfile
{
126 IDWriteFontFile IDWriteFontFile_iface
;
129 IDWriteFontFileLoader
*loader
;
132 IDWriteFontFileStream
*stream
;
135 static HRESULT
get_filestream_from_file(IDWriteFontFile
*,IDWriteFontFileStream
**);
137 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace2(IDWriteFontFace2
*iface
)
139 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace2_iface
);
142 static inline struct dwrite_font
*impl_from_IDWriteFont2(IDWriteFont2
*iface
)
144 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont2_iface
);
147 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
149 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
152 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily(IDWriteFontFamily
*iface
)
154 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily_iface
);
157 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
159 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
162 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
167 if (fontface
->cmap
.data
)
168 return fontface
->cmap
.data
;
170 hr
= IDWriteFontFace2_TryGetFontTable(&fontface
->IDWriteFontFace2_iface
, MS_CMAP_TAG
, (const void**)&fontface
->cmap
.data
,
171 &fontface
->cmap
.size
, &fontface
->cmap
.context
, &exists
);
172 if (FAILED(hr
) || !exists
) {
173 ERR("Font does not have a CMAP table\n");
177 return fontface
->cmap
.data
;
180 static void release_font_data(struct dwrite_font_data
*data
)
184 if (InterlockedDecrement(&data
->ref
) > 0)
187 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
188 if (data
->info_strings
[i
])
189 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
192 IDWriteFontFile_Release(data
->file
);
193 IDWriteFactory_Release(data
->factory
);
194 heap_free(data
->facename
);
198 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
202 if (InterlockedDecrement(&data
->ref
) > 0)
205 for (i
= 0; i
< data
->font_count
; i
++)
206 release_font_data(data
->fonts
[i
]);
207 heap_free(data
->fonts
);
208 IDWriteLocalizedStrings_Release(data
->familyname
);
212 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace2
*iface
, REFIID riid
, void **obj
)
214 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
216 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
218 if (IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
219 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
220 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
221 IsEqualIID(riid
, &IID_IUnknown
))
224 IDWriteFontFace2_AddRef(iface
);
229 return E_NOINTERFACE
;
232 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace2
*iface
)
234 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
235 ULONG ref
= InterlockedIncrement(&This
->ref
);
236 TRACE("(%p)->(%d)\n", This
, ref
);
240 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace2
*iface
)
242 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
243 ULONG ref
= InterlockedDecrement(&This
->ref
);
245 TRACE("(%p)->(%d)\n", This
, ref
);
250 if (This
->cmap
.context
)
251 IDWriteFontFace2_ReleaseFontTable(iface
, This
->cmap
.context
);
252 for (i
= 0; i
< This
->file_count
; i
++) {
253 if (This
->streams
[i
])
254 IDWriteFontFileStream_Release(This
->streams
[i
]);
256 IDWriteFontFile_Release(This
->files
[i
]);
258 release_ft_fontface(This
->ft
);
265 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace2
*iface
)
267 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
268 TRACE("(%p)\n", This
);
272 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace2
*iface
, UINT32
*number_of_files
,
273 IDWriteFontFile
**fontfiles
)
275 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
278 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
279 if (fontfiles
== NULL
)
281 *number_of_files
= This
->file_count
;
284 if (*number_of_files
< This
->file_count
)
287 for (i
= 0; i
< This
->file_count
; i
++)
289 IDWriteFontFile_AddRef(This
->files
[i
]);
290 fontfiles
[i
] = This
->files
[i
];
296 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace2
*iface
)
298 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
299 TRACE("(%p)\n", This
);
303 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace2
*iface
)
305 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
306 TRACE("(%p)\n", This
);
307 return This
->simulations
;
310 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace2
*iface
)
312 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
313 FIXME("(%p): stub\n", This
);
317 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS
*metrics
)
319 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
320 TRACE("(%p)->(%p)\n", This
, metrics
);
321 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
324 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace2
*iface
)
326 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
327 FIXME("(%p): stub\n", This
);
331 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2
*iface
,
332 UINT16
const *glyph_indices
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
334 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
335 FIXME("(%p)->(%p %u %p %d): stub\n", This
, glyph_indices
, glyph_count
, metrics
, is_sideways
);
339 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace2
*iface
, UINT32
const *codepoints
,
340 UINT32 count
, UINT16
*glyph_indices
)
342 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
346 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
348 data
= get_fontface_cmap(This
);
352 for (i
= 0; i
< count
; i
++)
353 opentype_cmap_get_glyphindex(data
, codepoints
[i
], &glyph_indices
[i
]);
358 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace2
*iface
, UINT32 table_tag
,
359 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
361 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
362 struct dwrite_fonttablecontext
*tablecontext
;
366 TRACE("(%p)->(%u %p %p %p %p)\n", This
, table_tag
, table_data
, table_size
, context
, exists
);
368 tablecontext
= heap_alloc(sizeof(struct dwrite_fonttablecontext
));
370 return E_OUTOFMEMORY
;
371 tablecontext
->magic
= DWRITE_FONTTABLE_MAGIC
;
374 for (i
= 0; i
< This
->file_count
&& !(*exists
); i
++) {
375 hr
= opentype_get_font_table(This
->streams
[i
], This
->type
, This
->index
, table_tag
, table_data
, &tablecontext
->context
, table_size
, exists
);
376 tablecontext
->file_index
= i
;
378 if (FAILED(hr
) && !*exists
)
379 heap_free(tablecontext
);
381 *context
= (void*)tablecontext
;
386 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace2
*iface
, void *table_context
)
388 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
389 struct dwrite_fonttablecontext
*tablecontext
= (struct dwrite_fonttablecontext
*)table_context
;
391 TRACE("(%p)->(%p)\n", This
, table_context
);
393 if (tablecontext
->magic
!= DWRITE_FONTTABLE_MAGIC
)
395 TRACE("Invalid table magic\n");
399 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[tablecontext
->file_index
], tablecontext
->context
);
400 heap_free(tablecontext
);
403 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace2
*iface
, FLOAT emSize
,
404 UINT16
const *glyph_indices
, FLOAT
const* glyph_advances
, DWRITE_GLYPH_OFFSET
const *glyph_offsets
,
405 UINT32 glyph_count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*geometrysink
)
407 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
408 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This
, emSize
, glyph_indices
, glyph_advances
, glyph_offsets
,
409 glyph_count
, is_sideways
, is_rtl
, geometrysink
);
413 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
414 FLOAT pixels_per_dip
, DWRITE_MEASURING_MODE mode
, IDWriteRenderingParams
* params
, DWRITE_RENDERING_MODE
* rendering_mode
)
416 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
417 FIXME("(%p)->(%f %f %d %p %p): stub\n", This
, emSize
, pixels_per_dip
, mode
, params
, rendering_mode
);
421 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
422 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
424 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
425 FIXME("(%p)->(%f %f %p %p): stub\n", This
, emSize
, pixels_per_dip
, transform
, metrics
);
429 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
430 DWRITE_MATRIX
const *transform
, BOOL use_gdi_natural
, UINT16
const *glyph_indices
, UINT32 glyph_count
,
431 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
433 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
434 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This
, emSize
, pixels_per_dip
, transform
, use_gdi_natural
, glyph_indices
,
435 glyph_count
, metrics
, is_sideways
);
439 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
441 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
442 TRACE("(%p)->(%p)\n", This
, metrics
);
443 *metrics
= This
->metrics
;
446 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
447 const DWRITE_MATRIX
*transform
, DWRITE_FONT_METRICS1
*metrics
)
449 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
450 FIXME("(%p)->(%f %f %p %p): stub\n", This
, em_size
, pixels_per_dip
, transform
, metrics
);
454 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace2
*iface
, DWRITE_CARET_METRICS
*metrics
)
456 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
457 FIXME("(%p)->(%p): stub\n", This
, metrics
);
460 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace2
*iface
, UINT32 max_count
,
461 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
463 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
465 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
468 if (max_count
&& !ranges
)
471 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
474 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace2
*iface
)
476 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
477 FIXME("(%p): stub\n", This
);
481 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2
*iface
,
482 UINT32 glyph_count
, UINT16
const *indices
, INT32
*advances
, BOOL is_sideways
)
484 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
485 FIXME("(%p)->(%u %p %p %d): stub\n", This
, glyph_count
, indices
, advances
, is_sideways
);
489 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2
*iface
,
490 FLOAT em_size
, FLOAT pixels_per_dip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
491 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *indices
, INT32
*advances
)
493 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
494 FIXME("(%p)->(%f %f %p %d %d %u %p %p): stub\n", This
, em_size
, pixels_per_dip
, transform
,
495 use_gdi_natural
, is_sideways
, glyph_count
, indices
, advances
);
499 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2
*iface
, UINT32 glyph_count
,
500 const UINT16
*indices
, INT32
*adjustments
)
502 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
503 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, indices
, adjustments
);
507 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace2
*iface
)
509 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
510 FIXME("(%p): stub\n", This
);
514 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
,
515 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
516 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
518 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
519 FIXME("(%p)->(%f %f %f %p %d %d %d %p): stub\n", This
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
520 threshold
, measuring_mode
, rendering_mode
);
524 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2
*iface
, UINT32 glyph_count
,
525 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
527 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
528 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
532 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2
*iface
)
534 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
535 FIXME("(%p): stub\n", This
);
539 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace2
*iface
)
541 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
542 FIXME("(%p): stub\n", This
);
546 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace2
*iface
)
548 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
549 FIXME("(%p): stub\n", This
);
553 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2
*iface
)
555 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
556 FIXME("(%p): stub\n", This
);
560 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace2
*iface
, UINT32 palette_index
,
561 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
563 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
564 FIXME("(%p)->(%u %u %u %p): stub\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
568 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT fontEmSize
,
569 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
570 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
571 DWRITE_GRID_FIT_MODE
*gridfitmode
)
573 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
574 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This
, fontEmSize
, dpiX
, dpiY
, transform
, is_sideways
, threshold
,
575 measuringmode
, params
, renderingmode
, gridfitmode
);
579 static const IDWriteFontFace2Vtbl dwritefontfacevtbl
= {
580 dwritefontface_QueryInterface
,
581 dwritefontface_AddRef
,
582 dwritefontface_Release
,
583 dwritefontface_GetType
,
584 dwritefontface_GetFiles
,
585 dwritefontface_GetIndex
,
586 dwritefontface_GetSimulations
,
587 dwritefontface_IsSymbolFont
,
588 dwritefontface_GetMetrics
,
589 dwritefontface_GetGlyphCount
,
590 dwritefontface_GetDesignGlyphMetrics
,
591 dwritefontface_GetGlyphIndices
,
592 dwritefontface_TryGetFontTable
,
593 dwritefontface_ReleaseFontTable
,
594 dwritefontface_GetGlyphRunOutline
,
595 dwritefontface_GetRecommendedRenderingMode
,
596 dwritefontface_GetGdiCompatibleMetrics
,
597 dwritefontface_GetGdiCompatibleGlyphMetrics
,
598 dwritefontface1_GetMetrics
,
599 dwritefontface1_GetGdiCompatibleMetrics
,
600 dwritefontface1_GetCaretMetrics
,
601 dwritefontface1_GetUnicodeRanges
,
602 dwritefontface1_IsMonospacedFont
,
603 dwritefontface1_GetDesignGlyphAdvances
,
604 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
605 dwritefontface1_GetKerningPairAdjustments
,
606 dwritefontface1_HasKerningPairs
,
607 dwritefontface1_GetRecommendedRenderingMode
,
608 dwritefontface1_GetVerticalGlyphVariants
,
609 dwritefontface1_HasVerticalGlyphVariants
,
610 dwritefontface2_IsColorFont
,
611 dwritefontface2_GetColorPaletteCount
,
612 dwritefontface2_GetPaletteEntryCount
,
613 dwritefontface2_GetPaletteEntries
,
614 dwritefontface2_GetRecommendedRenderingMode
617 static void get_font_properties_from_stream(IDWriteFontFileStream
*stream
, DWRITE_FONT_FACE_TYPE face_type
,
618 UINT32 face_index
, DWRITE_FONT_METRICS1
*metrics
, DWRITE_FONT_STRETCH
*stretch
, DWRITE_FONT_WEIGHT
*weight
,
619 DWRITE_FONT_STYLE
*style
)
621 const void *tt_os2
= NULL
, *tt_head
= NULL
, *tt_post
= NULL
;
622 void *os2_context
, *head_context
, *post_context
;
623 DWRITE_FONT_STRETCH fontstretch
;
624 DWRITE_FONT_WEIGHT fontweight
;
625 DWRITE_FONT_STYLE fontstyle
;
627 opentype_get_font_table(stream
, face_type
, face_index
, MS_OS2_TAG
, &tt_os2
, &os2_context
, NULL
, NULL
);
628 opentype_get_font_table(stream
, face_type
, face_index
, MS_HEAD_TAG
, &tt_head
, &head_context
, NULL
, NULL
);
629 opentype_get_font_table(stream
, face_type
, face_index
, MS_POST_TAG
, &tt_post
, &post_context
, NULL
, NULL
);
631 if (!stretch
) stretch
= &fontstretch
;
632 if (!weight
) weight
= &fontweight
;
633 if (!style
) style
= &fontstyle
;
635 opentype_get_font_properties(tt_os2
, tt_head
, stretch
, weight
, style
);
636 opentype_get_font_metrics(tt_os2
, tt_head
, tt_post
, metrics
);
639 IDWriteFontFileStream_ReleaseFileFragment(stream
, os2_context
);
641 IDWriteFontFileStream_ReleaseFileFragment(stream
, head_context
);
643 IDWriteFontFileStream_ReleaseFileFragment(stream
, post_context
);
646 HRESULT
convert_fontface_to_logfont(IDWriteFontFace
*face
, LOGFONTW
*logfont
)
648 DWRITE_FONT_SIMULATIONS simulations
;
649 DWRITE_FONT_FACE_TYPE face_type
;
650 IDWriteFontFileStream
*stream
;
651 DWRITE_FONT_METRICS1 metrics
;
652 DWRITE_FONT_STRETCH stretch
;
653 DWRITE_FONT_STYLE style
;
654 DWRITE_FONT_WEIGHT weight
;
655 IDWriteFontFile
*file
= NULL
;
659 memset(logfont
, 0, sizeof(*logfont
));
662 hr
= IDWriteFontFace_GetFiles(face
, &index
, &file
);
663 if (FAILED(hr
) || !file
)
666 hr
= get_filestream_from_file(file
, &stream
);
668 IDWriteFontFile_Release(file
);
672 index
= IDWriteFontFace_GetIndex(face
);
673 face_type
= IDWriteFontFace_GetType(face
);
674 get_font_properties_from_stream(stream
, face_type
, index
, &metrics
, &stretch
, &weight
, &style
);
675 IDWriteFontFileStream_Release(stream
);
677 simulations
= IDWriteFontFace_GetSimulations(face
);
679 logfont
->lfCharSet
= DEFAULT_CHARSET
;
680 logfont
->lfWeight
= weight
;
681 logfont
->lfItalic
= style
== DWRITE_FONT_STYLE_ITALIC
|| (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
);
682 logfont
->lfOutPrecision
= OUT_OUTLINE_PRECIS
;
683 /* TODO: set facename */
688 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace2
**fontface
)
690 struct dwrite_font_data
*data
= font
->data
;
691 IDWriteFontFace
*face
;
696 hr
= IDWriteFactory_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
697 data
->face_index
, font
->simulations
, &face
);
701 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace2
, (void**)fontface
);
702 IDWriteFontFace_Release(face
);
707 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont2
*iface
, REFIID riid
, void **obj
)
709 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
711 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
713 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
714 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
715 IsEqualIID(riid
, &IID_IDWriteFont
) ||
716 IsEqualIID(riid
, &IID_IUnknown
))
719 IDWriteFont2_AddRef(iface
);
724 return E_NOINTERFACE
;
727 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont2
*iface
)
729 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
730 ULONG ref
= InterlockedIncrement(&This
->ref
);
731 TRACE("(%p)->(%d)\n", This
, ref
);
735 static ULONG WINAPI
dwritefont_Release(IDWriteFont2
*iface
)
737 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
738 ULONG ref
= InterlockedDecrement(&This
->ref
);
740 TRACE("(%p)->(%d)\n", This
, ref
);
743 IDWriteFontFamily_Release(This
->family
);
744 release_font_data(This
->data
);
751 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont2
*iface
, IDWriteFontFamily
**family
)
753 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
754 TRACE("(%p)->(%p)\n", This
, family
);
756 *family
= This
->family
;
757 IDWriteFontFamily_AddRef(*family
);
761 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont2
*iface
)
763 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
764 TRACE("(%p)\n", This
);
765 return This
->data
->weight
;
768 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont2
*iface
)
770 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
771 TRACE("(%p)\n", This
);
772 return This
->data
->stretch
;
775 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont2
*iface
)
777 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
778 TRACE("(%p)\n", This
);
779 return This
->data
->style
;
782 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont2
*iface
)
784 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
785 IDWriteFontFace2
*fontface
;
788 TRACE("(%p)\n", This
);
790 hr
= get_fontface_from_font(This
, &fontface
);
794 return IDWriteFontFace2_IsSymbolFont(fontface
);
797 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont2
*iface
, IDWriteLocalizedStrings
**names
)
799 static const WCHAR boldobliqueW
[] = {'B','o','l','d',' ','O','b','l','i','q','u','e',0};
800 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
801 static const WCHAR boldW
[] = {'B','o','l','d',0};
802 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
804 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
805 IDWriteLocalizedStrings
*strings
;
809 TRACE("(%p)->(%p)\n", This
, names
);
813 if (This
->simulations
== DWRITE_FONT_SIMULATIONS_NONE
) {
815 return IDWriteFont2_GetInformationalStrings(iface
, DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES
,
819 switch (This
->simulations
) {
820 case DWRITE_FONT_SIMULATIONS_BOLD
|DWRITE_FONT_SIMULATIONS_OBLIQUE
:
823 case DWRITE_FONT_SIMULATIONS_BOLD
:
826 case DWRITE_FONT_SIMULATIONS_OBLIQUE
:
830 ERR("unknown simulations %d\n", This
->simulations
);
834 hr
= create_localizedstrings(&strings
);
835 if (FAILED(hr
)) return hr
;
837 hr
= add_localizedstring(strings
, enusW
, name
);
839 IDWriteLocalizedStrings_Release(strings
);
848 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont2
*iface
,
849 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
851 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
852 struct dwrite_font_data
*data
= This
->data
;
855 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
860 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
863 if (!data
->info_strings
[stringid
]) {
864 IDWriteFontFace2
*fontface
;
865 const void *table_data
;
870 hr
= get_fontface_from_font(This
, &fontface
);
874 table_exists
= FALSE
;
875 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
876 if (FAILED(hr
) || !table_exists
)
877 WARN("no NAME table found.\n");
880 hr
= opentype_get_font_strings_from_id(table_data
, stringid
, &data
->info_strings
[stringid
]);
881 if (FAILED(hr
) || !data
->info_strings
[stringid
])
883 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
887 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
895 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont2
*iface
)
897 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
898 TRACE("(%p)\n", This
);
899 return This
->simulations
;
902 static void WINAPI
dwritefont_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS
*metrics
)
904 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
906 TRACE("(%p)->(%p)\n", This
, metrics
);
907 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
910 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont2
*iface
, UINT32 value
, BOOL
*exists
)
912 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
913 IDWriteFontFace2
*fontface
;
917 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
921 hr
= get_fontface_from_font(This
, &fontface
);
926 hr
= IDWriteFontFace2_GetGlyphIndices(fontface
, &value
, 1, &index
);
930 *exists
= index
!= 0;
934 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont2
*iface
, IDWriteFontFace
**face
)
936 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
939 TRACE("(%p)->(%p)\n", This
, face
);
941 hr
= get_fontface_from_font(This
, (IDWriteFontFace2
**)face
);
943 IDWriteFontFace_AddRef(*face
);
948 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
950 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
951 TRACE("(%p)->(%p)\n", This
, metrics
);
952 *metrics
= This
->data
->metrics
;
955 static void WINAPI
dwritefont1_GetPanose(IDWriteFont2
*iface
, DWRITE_PANOSE
*panose
)
957 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
958 FIXME("(%p)->(%p): stub\n", This
, panose
);
961 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont2
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
963 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
964 IDWriteFontFace2
*fontface
;
967 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
969 hr
= get_fontface_from_font(This
, &fontface
);
973 return IDWriteFontFace2_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
976 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont2
*iface
)
978 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
979 IDWriteFontFace2
*fontface
;
982 TRACE("(%p)\n", This
);
984 hr
= get_fontface_from_font(This
, &fontface
);
988 return IDWriteFontFace2_IsMonospacedFont(fontface
);
991 static HRESULT WINAPI
dwritefont2_IsColorFont(IDWriteFont2
*iface
)
993 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
994 IDWriteFontFace2
*fontface
;
997 TRACE("(%p)\n", This
);
999 hr
= get_fontface_from_font(This
, &fontface
);
1003 return IDWriteFontFace2_IsColorFont(fontface
);
1006 static const IDWriteFont2Vtbl dwritefontvtbl
= {
1007 dwritefont_QueryInterface
,
1010 dwritefont_GetFontFamily
,
1011 dwritefont_GetWeight
,
1012 dwritefont_GetStretch
,
1013 dwritefont_GetStyle
,
1014 dwritefont_IsSymbolFont
,
1015 dwritefont_GetFaceNames
,
1016 dwritefont_GetInformationalStrings
,
1017 dwritefont_GetSimulations
,
1018 dwritefont_GetMetrics
,
1019 dwritefont_HasCharacter
,
1020 dwritefont_CreateFontFace
,
1021 dwritefont1_GetMetrics
,
1022 dwritefont1_GetPanose
,
1023 dwritefont1_GetUnicodeRanges
,
1024 dwritefont1_IsMonospacedFont
,
1025 dwritefont2_IsColorFont
1028 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily
*family
, DWRITE_FONT_SIMULATIONS simulations
,
1031 struct dwrite_font
*This
;
1034 This
= heap_alloc(sizeof(struct dwrite_font
));
1035 if (!This
) return E_OUTOFMEMORY
;
1037 This
->IDWriteFont2_iface
.lpVtbl
= &dwritefontvtbl
;
1039 This
->family
= family
;
1040 IDWriteFontFamily_AddRef(family
);
1041 This
->simulations
= simulations
;
1043 InterlockedIncrement(&This
->data
->ref
);
1045 *font
= (IDWriteFont
*)&This
->IDWriteFont2_iface
;
1050 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily
*iface
, REFIID riid
, void **obj
)
1052 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1053 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1055 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1056 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1057 IsEqualIID(riid
, &IID_IDWriteFontFamily
))
1060 IDWriteFontFamily_AddRef(iface
);
1065 return E_NOINTERFACE
;
1068 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily
*iface
)
1070 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1071 ULONG ref
= InterlockedIncrement(&This
->ref
);
1072 TRACE("(%p)->(%d)\n", This
, ref
);
1076 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily
*iface
)
1078 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1079 ULONG ref
= InterlockedDecrement(&This
->ref
);
1081 TRACE("(%p)->(%d)\n", This
, ref
);
1085 IDWriteFontCollection_Release(This
->collection
);
1086 release_fontfamily_data(This
->data
);
1093 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily
*iface
, IDWriteFontCollection
**collection
)
1095 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1096 TRACE("(%p)->(%p)\n", This
, collection
);
1098 *collection
= This
->collection
;
1099 IDWriteFontCollection_AddRef(This
->collection
);
1103 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily
*iface
)
1105 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1106 TRACE("(%p)\n", This
);
1107 return This
->data
->font_count
;
1110 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily
*iface
, UINT32 index
, IDWriteFont
**font
)
1112 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1114 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1118 if (This
->data
->font_count
== 0)
1121 if (index
>= This
->data
->font_count
)
1122 return E_INVALIDARG
;
1124 return create_font(This
->data
->fonts
[index
], iface
, DWRITE_FONT_SIMULATIONS_NONE
, font
);
1127 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily
*iface
, IDWriteLocalizedStrings
**names
)
1129 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1130 return clone_localizedstring(This
->data
->familyname
, names
);
1133 static inline BOOL
is_matching_font_style(DWRITE_FONT_STYLE style
, DWRITE_FONT_STYLE font_style
)
1135 if (style
== font_style
)
1138 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) && font_style
== DWRITE_FONT_STYLE_NORMAL
)
1144 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1145 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1147 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1148 UINT32 min_weight_diff
= ~0u;
1151 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1153 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1154 if (is_matching_font_style(style
, This
->data
->fonts
[i
]->style
) && stretch
== This
->data
->fonts
[i
]->stretch
) {
1155 DWRITE_FONT_WEIGHT font_weight
= This
->data
->fonts
[i
]->weight
;
1156 UINT32 weight_diff
= abs(font_weight
- weight
);
1157 if (weight_diff
< min_weight_diff
) {
1158 min_weight_diff
= weight_diff
;
1165 DWRITE_FONT_SIMULATIONS simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
1167 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) &&
1168 This
->data
->fonts
[found
]->style
== DWRITE_FONT_STYLE_NORMAL
) {
1169 simulations
= DWRITE_FONT_SIMULATIONS_OBLIQUE
;
1171 return create_font(This
->data
->fonts
[found
], iface
, simulations
, font
);
1175 return DWRITE_E_NOFONT
;
1179 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1180 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**fonts
)
1182 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1183 FIXME("(%p)->(%d %d %d %p): stub\n", This
, weight
, stretch
, style
, fonts
);
1187 static const IDWriteFontFamilyVtbl fontfamilyvtbl
= {
1188 dwritefontfamily_QueryInterface
,
1189 dwritefontfamily_AddRef
,
1190 dwritefontfamily_Release
,
1191 dwritefontfamily_GetFontCollection
,
1192 dwritefontfamily_GetFontCount
,
1193 dwritefontfamily_GetFont
,
1194 dwritefontfamily_GetFamilyNames
,
1195 dwritefontfamily_GetFirstMatchingFont
,
1196 dwritefontfamily_GetMatchingFonts
1199 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily
**family
)
1201 struct dwrite_fontfamily
*This
;
1205 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1206 if (!This
) return E_OUTOFMEMORY
;
1208 This
->IDWriteFontFamily_iface
.lpVtbl
= &fontfamilyvtbl
;
1210 This
->collection
= collection
;
1211 IDWriteFontCollection_AddRef(collection
);
1213 InterlockedIncrement(&This
->data
->ref
);
1215 *family
= &This
->IDWriteFontFamily_iface
;
1220 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1223 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1226 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
1228 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1229 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1231 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1232 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
1235 IDWriteFontCollection_AddRef(iface
);
1241 if (This
->is_system
&& IsEqualIID(riid
, &IID_issystemcollection
))
1244 return E_NOINTERFACE
;
1247 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection
*iface
)
1249 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1250 ULONG ref
= InterlockedIncrement(&This
->ref
);
1251 TRACE("(%p)->(%d)\n", This
, ref
);
1255 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection
*iface
)
1258 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1259 ULONG ref
= InterlockedDecrement(&This
->ref
);
1260 TRACE("(%p)->(%d)\n", This
, ref
);
1263 for (i
= 0; i
< This
->family_count
; i
++)
1264 release_fontfamily_data(This
->family_data
[i
]);
1265 heap_free(This
->family_data
);
1272 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
1274 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1275 TRACE("(%p)\n", This
);
1276 return This
->family_count
;
1279 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
1281 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1283 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
1285 if (index
>= This
->family_count
) {
1290 return create_fontfamily(This
->family_data
[index
], iface
, family
);
1293 static HRESULT
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
1297 if (collection
->family_count
) {
1298 for (i
= 0; i
< collection
->family_count
; i
++) {
1299 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
1303 for (j
= 0; j
< IDWriteLocalizedStrings_GetCount(family_name
); j
++) {
1305 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
1306 if (SUCCEEDED(hr
)) {
1307 if (!strcmpW(buffer
, name
)) {
1315 *index
= (UINT32
)-1;
1322 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
1324 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1325 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
1326 return collection_find_family(This
, name
, index
, exists
);
1329 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
1331 UINT32 left_key_size
, right_key_size
;
1332 const void *left_key
, *right_key
;
1338 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
1342 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
1346 if (left_key_size
!= right_key_size
)
1349 return !memcmp(left_key
, right_key
, left_key_size
);
1352 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
1354 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1355 struct dwrite_fontfamily_data
*found_family
= NULL
;
1356 struct dwrite_font_data
*found_font
= NULL
;
1357 DWRITE_FONT_SIMULATIONS simulations
;
1358 IDWriteFontFamily
*family
;
1359 UINT32 i
, j
, face_index
;
1360 IDWriteFontFile
*file
;
1363 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
1368 return E_INVALIDARG
;
1371 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
1374 face_index
= IDWriteFontFace_GetIndex(face
);
1376 for (i
= 0; i
< This
->family_count
; i
++) {
1377 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
1378 for (j
= 0; j
< family_data
->font_count
; j
++) {
1379 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
1381 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
1382 found_font
= font_data
;
1383 found_family
= family_data
;
1390 return E_INVALIDARG
;
1392 hr
= create_fontfamily(found_family
, iface
, &family
);
1396 simulations
= IDWriteFontFace_GetSimulations(face
);
1397 hr
= create_font(found_font
, family
, simulations
, font
);
1398 IDWriteFontFamily_Release(family
);
1402 static const IDWriteFontCollectionVtbl fontcollectionvtbl
= {
1403 dwritefontcollection_QueryInterface
,
1404 dwritefontcollection_AddRef
,
1405 dwritefontcollection_Release
,
1406 dwritefontcollection_GetFontFamilyCount
,
1407 dwritefontcollection_GetFontFamily
,
1408 dwritefontcollection_FindFamilyName
,
1409 dwritefontcollection_GetFontFromFontFace
1412 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
1414 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
1415 struct dwrite_font_data
**new_list
;
1418 new_alloc
= family_data
->font_alloc
* 2;
1419 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
1421 return E_OUTOFMEMORY
;
1422 family_data
->fonts
= new_list
;
1423 family_data
->font_alloc
= new_alloc
;
1426 family_data
->fonts
[family_data
->font_count
] = font_data
;
1427 InterlockedIncrement(&font_data
->ref
);
1428 family_data
->font_count
++;
1432 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
1434 if (collection
->family_alloc
< collection
->family_count
+ 1) {
1435 struct dwrite_fontfamily_data
**new_list
;
1438 new_alloc
= collection
->family_alloc
* 2;
1439 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
1441 return E_OUTOFMEMORY
;
1443 collection
->family_alloc
= new_alloc
;
1444 collection
->family_data
= new_list
;
1447 collection
->family_data
[collection
->family_count
] = family
;
1448 collection
->family_count
++;
1453 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
1455 collection
->IDWriteFontCollection_iface
.lpVtbl
= &fontcollectionvtbl
;
1456 collection
->ref
= 1;
1457 collection
->family_count
= 0;
1458 collection
->family_alloc
= 2;
1459 collection
->is_system
= is_system
;
1461 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
)*2);
1462 if (!collection
->family_data
)
1463 return E_OUTOFMEMORY
;
1468 static HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
1470 IDWriteFontFileLoader
*loader
;
1477 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
1481 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
1485 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
1486 IDWriteFontFileLoader_Release(loader
);
1493 static HRESULT
init_font_data(IDWriteFactory
*factory
, IDWriteFontFile
*file
, UINT32 face_index
, DWRITE_FONT_FACE_TYPE face_type
, struct dwrite_font_data
*data
)
1495 void *os2_context
, *head_context
, *post_context
;
1496 const void *tt_os2
= NULL
, *tt_head
= NULL
, *tt_post
= NULL
;
1497 IDWriteFontFileStream
*stream
;
1500 hr
= get_filestream_from_file(file
, &stream
);
1504 data
->factory
= factory
;
1506 data
->face_index
= face_index
;
1507 data
->face_type
= face_type
;
1508 IDWriteFontFile_AddRef(file
);
1509 IDWriteFactory_AddRef(factory
);
1511 opentype_get_font_table(stream
, face_type
, face_index
, MS_OS2_TAG
, &tt_os2
, &os2_context
, NULL
, NULL
);
1512 opentype_get_font_table(stream
, face_type
, face_index
, MS_HEAD_TAG
, &tt_head
, &head_context
, NULL
, NULL
);
1513 opentype_get_font_table(stream
, face_type
, face_index
, MS_POST_TAG
, &tt_post
, &post_context
, NULL
, NULL
);
1515 opentype_get_font_properties(tt_os2
, tt_head
, &data
->stretch
, &data
->weight
, &data
->style
);
1516 opentype_get_font_metrics(tt_os2
, tt_head
, tt_post
, &data
->metrics
);
1519 IDWriteFontFileStream_ReleaseFileFragment(stream
, os2_context
);
1521 IDWriteFontFileStream_ReleaseFileFragment(stream
, head_context
);
1523 IDWriteFontFileStream_ReleaseFileFragment(stream
, post_context
);
1524 IDWriteFontFileStream_Release(stream
);
1529 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
*data
)
1532 data
->font_count
= 0;
1533 data
->font_alloc
= 2;
1535 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
1538 return E_OUTOFMEMORY
;
1541 data
->familyname
= familyname
;
1542 IDWriteLocalizedStrings_AddRef(familyname
);
1547 HRESULT
create_font_collection(IDWriteFactory
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
1549 struct dwrite_fontcollection
*collection
;
1550 BOOL current
= FALSE
;
1555 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
1556 if (!collection
) return E_OUTOFMEMORY
;
1558 hr
= init_font_collection(collection
, is_system
);
1560 heap_free(collection
);
1564 *ret
= &collection
->IDWriteFontCollection_iface
;
1566 TRACE("building font collection:\n");
1569 DWRITE_FONT_FACE_TYPE face_type
;
1570 DWRITE_FONT_FILE_TYPE file_type
;
1571 IDWriteFontFile
*file
;
1577 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
1578 if (FAILED(hr
) || !current
)
1581 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
1585 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
1586 if (FAILED(hr
) || !supported
|| face_count
== 0) {
1587 TRACE("unsupported font (0x%08x, %d, %u)\n", hr
, supported
, face_count
);
1588 IDWriteFontFile_Release(file
);
1592 for (i
= 0; i
< face_count
; i
++) {
1593 IDWriteLocalizedStrings
*family_name
= NULL
;
1594 struct dwrite_font_data
*font_data
;
1595 const void *name_table
;
1597 IDWriteFontFileStream
*stream
;
1602 /* alloc and init new font data structure */
1603 font_data
= heap_alloc_zero(sizeof(struct dwrite_font_data
));
1604 init_font_data(factory
, file
, i
, face_type
, font_data
);
1606 hr
= get_filestream_from_file(file
, &stream
);
1608 heap_free (font_data
);
1612 /* get family name from font file */
1614 opentype_get_font_table(stream
, face_type
, i
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
1616 hr
= opentype_get_font_strings_from_id(name_table
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &family_name
);
1617 IDWriteFontFileStream_Release(stream
);
1619 if (FAILED(hr
) || !family_name
) {
1620 WARN("unable to get family name from font\n");
1625 IDWriteLocalizedStrings_GetString(family_name
, 0, buffer
, sizeof(buffer
)/sizeof(WCHAR
));
1628 hr
= collection_find_family(collection
, buffer
, &index
, &exists
);
1630 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
1632 struct dwrite_fontfamily_data
*family_data
;
1634 /* create and init new family */
1635 family_data
= heap_alloc(sizeof(*family_data
));
1636 init_fontfamily_data(family_name
, family_data
);
1638 /* add font to family, family - to collection */
1639 fontfamily_add_font(family_data
, font_data
);
1640 fontcollection_add_family(collection
, family_data
);
1643 IDWriteLocalizedStrings_Release(family_name
);
1646 IDWriteFontFile_Release(file
);
1652 struct system_fontfile_enumerator
1654 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
1657 IDWriteFactory
*factory
;
1662 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
1664 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
1667 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
1671 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
1672 IDWriteFontFileEnumerator_AddRef(iface
);
1677 return E_NOINTERFACE
;
1680 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
1682 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1683 return InterlockedIncrement(&enumerator
->ref
);
1686 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
1688 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1689 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
1692 IDWriteFactory_Release(enumerator
->factory
);
1693 RegCloseKey(enumerator
->hkey
);
1694 heap_free(enumerator
);
1700 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
1702 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1703 DWORD ret
, type
, count
;
1709 if (enumerator
->index
< 0)
1712 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, NULL
, NULL
, NULL
, &type
, NULL
, &count
))
1715 if (!(data
= heap_alloc(count
)))
1716 return E_OUTOFMEMORY
;
1718 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, NULL
, NULL
, NULL
, &type
, data
, &count
);
1724 hr
= IDWriteFactory_CreateFontFileReference(enumerator
->factory
, (WCHAR
*)data
, NULL
, file
);
1729 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
1731 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1734 enumerator
->index
++;
1736 /* iterate until we find next string value */
1738 DWORD type
= 0, count
;
1739 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, NULL
, NULL
, NULL
, &type
, NULL
, &count
))
1741 if (type
== REG_SZ
) {
1745 enumerator
->index
++;
1748 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
1752 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
1754 systemfontfileenumerator_QueryInterface
,
1755 systemfontfileenumerator_AddRef
,
1756 systemfontfileenumerator_Release
,
1757 systemfontfileenumerator_MoveNext
,
1758 systemfontfileenumerator_GetCurrentFontFile
1761 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory
*factory
, IDWriteFontFileEnumerator
**ret
)
1763 struct system_fontfile_enumerator
*enumerator
;
1764 static const WCHAR fontslistW
[] = {
1765 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
1766 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1767 'F','o','n','t','s',0
1772 enumerator
= heap_alloc(sizeof(*enumerator
));
1774 return E_OUTOFMEMORY
;
1776 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
1777 enumerator
->ref
= 1;
1778 enumerator
->factory
= factory
;
1779 enumerator
->index
= -1;
1780 IDWriteFactory_AddRef(factory
);
1782 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
1783 ERR("failed to open fonts list key\n");
1784 IDWriteFactory_Release(factory
);
1785 heap_free(enumerator
);
1789 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
1794 HRESULT
get_system_fontcollection(IDWriteFactory
*factory
, IDWriteFontCollection
**collection
)
1796 IDWriteFontFileEnumerator
*enumerator
;
1801 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
1805 TRACE("building system font collection for factory %p\n", factory
);
1806 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
1807 IDWriteFontFileEnumerator_Release(enumerator
);
1811 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
1813 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
1815 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1817 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
1820 IDWriteFontFile_AddRef(iface
);
1825 return E_NOINTERFACE
;
1828 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
1830 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
1831 ULONG ref
= InterlockedIncrement(&This
->ref
);
1832 TRACE("(%p)->(%d)\n", This
, ref
);
1836 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
1838 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
1839 ULONG ref
= InterlockedDecrement(&This
->ref
);
1841 TRACE("(%p)->(%d)\n", This
, ref
);
1845 IDWriteFontFileLoader_Release(This
->loader
);
1846 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
1847 heap_free(This
->reference_key
);
1854 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
1856 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
1857 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
1858 *fontFileReferenceKey
= This
->reference_key
;
1859 *fontFileReferenceKeySize
= This
->key_size
;
1864 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
1866 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
1867 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
1868 *fontFileLoader
= This
->loader
;
1869 IDWriteFontFileLoader_AddRef(This
->loader
);
1874 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
, DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
1876 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
1877 IDWriteFontFileStream
*stream
;
1880 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
1882 *isSupportedFontType
= FALSE
;
1883 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
1885 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
1888 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
1892 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
1894 /* TODO: Further Analysis */
1895 IDWriteFontFileStream_Release(stream
);
1899 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
1900 dwritefontfile_QueryInterface
,
1901 dwritefontfile_AddRef
,
1902 dwritefontfile_Release
,
1903 dwritefontfile_GetReferenceKey
,
1904 dwritefontfile_GetLoader
,
1905 dwritefontfile_Analyze
,
1908 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
1910 struct dwrite_fontfile
*This
;
1912 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
1913 if (!This
) return E_OUTOFMEMORY
;
1915 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
1917 IDWriteFontFileLoader_AddRef(loader
);
1918 This
->loader
= loader
;
1919 This
->stream
= NULL
;
1920 This
->reference_key
= heap_alloc(key_size
);
1921 memcpy(This
->reference_key
, reference_key
, key_size
);
1922 This
->key_size
= key_size
;
1924 *font_file
= &This
->IDWriteFontFile_iface
;
1929 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
1931 IDWriteFontFileLoader
*loader
;
1937 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
1941 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
1943 IDWriteFontFileLoader_Release(loader
);
1947 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
1948 IDWriteFontFileLoader_Release(loader
);
1953 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
1954 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace2
**ret
)
1956 struct dwrite_fontface
*fontface
;
1957 const void *data_ptr
;
1965 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
1967 return E_OUTOFMEMORY
;
1969 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
1970 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
1972 if (!fontface
->files
|| !fontface
->streams
) {
1973 heap_free(fontface
->files
);
1974 heap_free(fontface
->streams
);
1975 heap_free(fontface
);
1976 return E_OUTOFMEMORY
;
1979 fontface
->IDWriteFontFace2_iface
.lpVtbl
= &dwritefontfacevtbl
;
1981 fontface
->type
= facetype
;
1982 fontface
->file_count
= files_number
;
1983 fontface
->cmap
.data
= NULL
;
1984 fontface
->cmap
.context
= NULL
;
1985 fontface
->cmap
.size
= 0;
1986 fontface
->index
= index
;
1987 fontface
->simulations
= simulations
;
1988 fontface
->ft
= NULL
;
1990 for (i
= 0; i
< fontface
->file_count
; i
++) {
1991 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
1993 IDWriteFontFace2_Release(&fontface
->IDWriteFontFace2_iface
);
1997 fontface
->files
[i
] = font_files
[i
];
1998 IDWriteFontFile_AddRef(font_files
[i
]);
2001 get_font_properties_from_stream(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, NULL
, NULL
, NULL
);
2003 hr
= IDWriteFontFileStream_GetFileSize(fontface
->streams
[0], &size
);
2007 hr
= IDWriteFontFileStream_ReadFileFragment(fontface
->streams
[0], &data_ptr
, 0, size
, &context
);
2011 hr
= alloc_ft_fontface(data_ptr
, size
, fontface
->index
, &fontface
->ft
);
2012 IDWriteFontFileStream_ReleaseFileFragment(fontface
->streams
[0], context
);
2016 *ret
= &fontface
->IDWriteFontFace2_iface
;
2020 IDWriteFontFace2_Release(&fontface
->IDWriteFontFace2_iface
);
2024 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
2031 struct local_cached_stream
2034 IDWriteFontFileStream
*stream
;
2035 struct local_refkey
*key
;
2039 struct dwrite_localfontfilestream
2041 IDWriteFontFileStream IDWriteFontFileStream_iface
;
2044 struct local_cached_stream
*entry
;
2048 struct dwrite_localfontfileloader
{
2049 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
2052 struct list streams
;
2055 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
2057 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
2060 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
2062 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
2065 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
2067 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2068 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2069 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
2072 IDWriteFontFileStream_AddRef(iface
);
2077 return E_NOINTERFACE
;
2080 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
2082 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2083 ULONG ref
= InterlockedIncrement(&This
->ref
);
2084 TRACE("(%p)->(%d)\n", This
, ref
);
2088 static inline void release_cached_stream(struct local_cached_stream
*stream
)
2090 list_remove(&stream
->entry
);
2091 heap_free(stream
->key
);
2095 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
2097 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2098 ULONG ref
= InterlockedDecrement(&This
->ref
);
2100 TRACE("(%p)->(%d)\n", This
, ref
);
2103 if (This
->handle
!= INVALID_HANDLE_VALUE
)
2104 CloseHandle(This
->handle
);
2105 release_cached_stream(This
->entry
);
2112 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
2114 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2115 LARGE_INTEGER distance
;
2116 DWORD bytes
= fragment_size
;
2119 TRACE("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
2120 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
2122 *fragment_context
= NULL
;
2123 distance
.QuadPart
= offset
;
2124 if (!SetFilePointerEx(This
->handle
, distance
, NULL
, FILE_BEGIN
))
2126 *fragment_start
= *fragment_context
= heap_alloc(bytes
);
2127 if (!*fragment_context
)
2129 if (!ReadFile(This
->handle
, *fragment_context
, bytes
, &read
, NULL
))
2131 heap_free(*fragment_context
);
2138 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
2140 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2141 TRACE("(%p)->(%p)\n", This
, fragment_context
);
2142 heap_free(fragment_context
);
2145 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
2147 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2149 TRACE("(%p)->(%p)\n",This
, size
);
2150 GetFileSizeEx(This
->handle
, &li
);
2151 *size
= li
.QuadPart
;
2155 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
2157 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2160 TRACE("(%p)->(%p)\n", This
, last_writetime
);
2162 li
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
2163 li
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
2164 *last_writetime
= li
.QuadPart
;
2169 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
2171 localfontfilestream_QueryInterface
,
2172 localfontfilestream_AddRef
,
2173 localfontfilestream_Release
,
2174 localfontfilestream_ReadFileFragment
,
2175 localfontfilestream_ReleaseFileFragment
,
2176 localfontfilestream_GetFileSize
,
2177 localfontfilestream_GetLastWriteTime
2180 static HRESULT
create_localfontfilestream(HANDLE handle
, struct local_cached_stream
*entry
, IDWriteFontFileStream
** iface
)
2182 struct dwrite_localfontfilestream
*This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
2184 return E_OUTOFMEMORY
;
2187 This
->handle
= handle
;
2188 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
2189 This
->entry
= entry
;
2191 *iface
= &This
->IDWriteFontFileStream_iface
;
2195 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
2197 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2199 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2201 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
2204 IDWriteLocalFontFileLoader_AddRef(iface
);
2209 return E_NOINTERFACE
;
2212 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
2214 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2215 ULONG ref
= InterlockedIncrement(&This
->ref
);
2216 TRACE("(%p)->(%d)\n", This
, ref
);
2220 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
2222 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2223 ULONG ref
= InterlockedDecrement(&This
->ref
);
2225 TRACE("(%p)->(%d)\n", This
, ref
);
2228 struct local_cached_stream
*stream
, *stream2
;
2230 /* This will detach all entries from cache. Entries are released together with streams,
2231 so stream controls its lifetime. */
2232 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
2233 list_init(&stream
->entry
);
2241 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
2243 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2244 const struct local_refkey
*refkey
= key
;
2245 struct local_cached_stream
*stream
;
2246 IDWriteFontFileStream
*filestream
;
2250 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
2252 TRACE("name: %s\n", debugstr_w(refkey
->name
));
2254 /* search cache first */
2255 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
2256 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
2257 *ret
= stream
->stream
;
2258 IDWriteFontFileStream_AddRef(*ret
);
2265 handle
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2266 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2268 if (handle
== INVALID_HANDLE_VALUE
)
2271 stream
= heap_alloc(sizeof(*stream
));
2273 return E_OUTOFMEMORY
;
2275 stream
->key
= heap_alloc(key_size
);
2278 return E_OUTOFMEMORY
;
2281 stream
->key_size
= key_size
;
2282 memcpy(stream
->key
, key
, key_size
);
2284 hr
= create_localfontfilestream(handle
, stream
, &filestream
);
2286 heap_free(stream
->key
);
2291 stream
->stream
= filestream
;
2292 list_add_head(&This
->streams
, &stream
->entry
);
2294 *ret
= stream
->stream
;
2299 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
2301 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2302 const struct local_refkey
*refkey
= key
;
2304 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
2306 *length
= strlenW(refkey
->name
);
2310 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
2312 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2313 const struct local_refkey
*refkey
= key
;
2315 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
2317 if (length
< strlenW(refkey
->name
))
2318 return E_INVALIDARG
;
2320 strcpyW(path
, refkey
->name
);
2324 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
2326 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2327 const struct local_refkey
*refkey
= key
;
2329 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
2331 *writetime
= refkey
->writetime
;
2335 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
2336 localfontfileloader_QueryInterface
,
2337 localfontfileloader_AddRef
,
2338 localfontfileloader_Release
,
2339 localfontfileloader_CreateStreamFromKey
,
2340 localfontfileloader_GetFilePathLengthFromKey
,
2341 localfontfileloader_GetFilePathFromKey
,
2342 localfontfileloader_GetLastWriteTimeFromKey
2345 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
** iface
)
2347 struct dwrite_localfontfileloader
*This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
2349 return E_OUTOFMEMORY
;
2351 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
2353 list_init(&This
->streams
);
2355 *iface
= &This
->IDWriteLocalFontFileLoader_iface
;
2359 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
2361 struct local_refkey
*refkey
;
2363 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
2366 refkey
= heap_alloc(*size
);
2368 return E_OUTOFMEMORY
;
2371 refkey
->writetime
= *writetime
;
2373 WIN32_FILE_ATTRIBUTE_DATA info
;
2375 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
2376 refkey
->writetime
= info
.ftLastWriteTime
;
2378 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
2380 strcpyW(refkey
->name
, path
);