4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2017 Nikolay Sivov for CodeWeavers
6 * Copyright 2014 Aric Stewart for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "dwrite_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
31 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
33 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
34 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
35 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
36 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
37 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
38 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
39 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
40 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
42 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
44 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
45 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
46 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
48 static const struct font_backend_funcs
*font_funcs
;
50 void dwrite_fontface_get_glyph_bbox(struct dwrite_glyphbitmap
*bitmap
)
52 font_funcs
->get_glyph_bbox(bitmap
);
55 struct dwrite_font_propvec
{
61 struct dwrite_font_data
65 DWRITE_FONT_STYLE style
;
66 DWRITE_FONT_STRETCH stretch
;
67 DWRITE_FONT_WEIGHT weight
;
69 FONTSIGNATURE fontsig
;
70 UINT32 flags
; /* enum font_flags */
71 struct dwrite_font_propvec propvec
;
72 struct dwrite_cmap cmap
;
73 /* Static axis for weight/width/italic. */
74 DWRITE_FONT_AXIS_VALUE axis
[3];
76 DWRITE_FONT_METRICS1 metrics
;
77 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
78 IDWriteLocalizedStrings
*family_names
;
79 IDWriteLocalizedStrings
*names
;
81 /* data needed to create fontface instance */
82 DWRITE_FONT_FACE_TYPE face_type
;
83 IDWriteFontFile
*file
;
92 /* used to mark font as tested when scanning for simulation candidate */
93 unsigned int bold_sim_tested
: 1;
94 unsigned int oblique_sim_tested
: 1;
97 struct dwrite_fontfamily_data
101 IDWriteLocalizedStrings
*familyname
;
103 struct dwrite_font_data
**fonts
;
107 unsigned int has_normal_face
: 1;
108 unsigned int has_oblique_face
: 1;
109 unsigned int has_italic_face
: 1;
112 struct dwrite_fontcollection
114 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
117 IDWriteFactory7
*factory
;
118 struct dwrite_fontfamily_data
**family_data
;
123 struct dwrite_fontfamily
125 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
126 IDWriteFontList2 IDWriteFontList2_iface
;
129 struct dwrite_fontfamily_data
*data
;
130 struct dwrite_fontcollection
*collection
;
133 struct dwrite_fontlist
135 IDWriteFontList2 IDWriteFontList2_iface
;
138 struct dwrite_font_data
**fonts
;
140 struct dwrite_fontfamily
*family
;
145 IDWriteFont3 IDWriteFont3_iface
;
148 DWRITE_FONT_STYLE style
;
149 struct dwrite_font_data
*data
;
150 struct dwrite_fontfamily
*family
;
153 enum runanalysis_flags
{
154 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
155 RUNANALYSIS_BITMAP_READY
= 1 << 1,
156 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
159 struct dwrite_glyphrunanalysis
161 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
164 DWRITE_RENDERING_MODE1 rendering_mode
;
165 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
166 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
169 D2D_POINT_2F
*origins
;
174 UINT32 max_glyph_bitmap_size
;
177 struct dwrite_colorglyphenum
179 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
182 FLOAT origin_x
; /* original run origin */
185 IDWriteFontFace5
*fontface
; /* for convenience */
186 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
187 DWRITE_GLYPH_RUN run
; /* base run */
188 UINT32 palette
; /* palette index to get layer color from */
189 FLOAT
*advances
; /* original or measured advances for base glyphs */
190 FLOAT
*color_advances
; /* returned color run points to this */
191 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
192 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
193 UINT16
*glyphindices
; /* returned color run points to this */
194 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
195 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
196 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
197 UINT16 max_layer_num
; /* max number of layers for this run */
198 struct dwrite_fonttable colr
; /* used to access layers */
201 #define GLYPH_BLOCK_SHIFT 8
202 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
203 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
204 #define GLYPH_MAX 65536
206 struct dwrite_fontfile
208 IDWriteFontFile IDWriteFontFile_iface
;
211 IDWriteFontFileLoader
*loader
;
214 IDWriteFontFileStream
*stream
;
217 struct dwrite_fontfacereference
219 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
222 IDWriteFontFile
*file
;
225 DWRITE_FONT_AXIS_VALUE
*axis_values
;
226 UINT32 axis_values_count
;
227 IDWriteFactory7
*factory
;
230 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
232 struct dwrite_fontresource
234 IDWriteFontResource IDWriteFontResource_iface
;
237 IDWriteFontFile
*file
;
239 IDWriteFactory7
*factory
;
242 struct dwrite_fontset_entry
245 IDWriteFontFile
*file
;
246 DWRITE_FONT_FACE_TYPE face_type
;
247 unsigned int face_index
;
248 unsigned int simulations
;
249 IDWriteLocalizedStrings
*props
[DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
+ 1];
252 struct dwrite_fontset
254 IDWriteFontSet3 IDWriteFontSet3_iface
;
256 IDWriteFactory7
*factory
;
258 struct dwrite_fontset_entry
**entries
;
262 struct dwrite_fontset_builder
264 IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface
;
266 IDWriteFactory7
*factory
;
268 struct dwrite_fontset_entry
**entries
;
273 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
274 unsigned int count
, IDWriteFontSet1
**ret
);
276 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
278 struct dwrite_fontface
*fontface
= context
;
281 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
282 size
, data_context
, &exists
)) || !exists
)
286 *data_context
= NULL
;
290 static void dwrite_release_font_table(void *context
, void *data_context
)
292 struct dwrite_fontface
*fontface
= context
;
293 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
296 static UINT16
dwrite_get_font_upem(void *context
)
298 struct dwrite_fontface
*fontface
= context
;
299 return fontface
->metrics
.designUnitsPerEm
;
302 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
304 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
305 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
308 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
310 struct dwrite_fontface
*fontface
= context
;
311 return !!dwritefontface_get_glyph(fontface
, codepoint
);
314 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
316 struct dwrite_fontface
*fontface
= context
;
317 return dwritefontface_get_glyph(fontface
, codepoint
);
320 static const struct shaping_font_ops dwrite_font_ops
=
322 dwrite_grab_font_table
,
323 dwrite_release_font_table
,
324 dwrite_get_font_upem
,
329 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
331 if (fontface
->shaping_cache
)
332 return fontface
->shaping_cache
;
334 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
337 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
339 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
342 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
344 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
347 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
349 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
352 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
354 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
356 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
359 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
361 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
364 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
366 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
369 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
371 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
374 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
376 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
379 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
381 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
384 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
386 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
389 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
391 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
394 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
396 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
399 static struct dwrite_fontset_builder
*impl_from_IDWriteFontSetBuilder2(IDWriteFontSetBuilder2
*iface
)
401 return CONTAINING_RECORD(iface
, struct dwrite_fontset_builder
, IDWriteFontSetBuilder2_iface
);
404 static struct dwrite_fontset
*impl_from_IDWriteFontSet3(IDWriteFontSet3
*iface
)
406 return CONTAINING_RECORD(iface
, struct dwrite_fontset
, IDWriteFontSet3_iface
);
409 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
411 static const DWRITE_GLYPH_METRICS nil
;
412 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
414 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
415 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
419 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
421 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
424 /* start new block */
425 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
427 return E_OUTOFMEMORY
;
430 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
434 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
438 if (table
->data
|| !table
->exists
)
441 table
->exists
= FALSE
;
442 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
444 if (FAILED(hr
) || !table
->exists
) {
445 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
452 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
453 struct dwrite_font_propvec
*vec
)
455 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
456 vec
->style
= style
* 7.0f
;
457 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
460 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
462 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
465 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
467 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
470 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
472 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
473 return &fontface
->vdmx
;
476 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
478 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
479 return &fontface
->gasp
;
482 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
484 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
485 return &fontface
->cpal
;
488 static struct dwrite_font_data
* addref_font_data(struct dwrite_font_data
*data
)
490 InterlockedIncrement(&data
->refcount
);
494 static void release_font_data(struct dwrite_font_data
*data
)
498 if (InterlockedDecrement(&data
->refcount
) > 0)
501 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
503 if (data
->info_strings
[i
])
504 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
507 IDWriteLocalizedStrings_Release(data
->names
);
509 if (data
->family_names
)
510 IDWriteLocalizedStrings_Release(data
->family_names
);
512 dwrite_cmap_release(&data
->cmap
);
513 IDWriteFontFile_Release(data
->file
);
514 heap_free(data
->facename
);
518 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
522 if (InterlockedDecrement(&data
->refcount
) > 0)
525 for (i
= 0; i
< data
->count
; ++i
)
526 release_font_data(data
->fonts
[i
]);
527 heap_free(data
->fonts
);
528 IDWriteLocalizedStrings_Release(data
->familyname
);
532 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
534 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
535 fontface
->cached
= NULL
;
538 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
540 UINT32 left_key_size
, right_key_size
;
541 const void *left_key
, *right_key
;
547 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
551 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
555 if (left_key_size
!= right_key_size
)
558 return !memcmp(left_key
, right_key
, left_key_size
);
561 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
563 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
565 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
567 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
568 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
569 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
570 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
571 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
572 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
573 IsEqualIID(riid
, &IID_IUnknown
))
577 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
578 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
584 if (InterlockedIncrement(&fontface
->refcount
) == 1)
586 InterlockedDecrement(&fontface
->refcount
);
593 WARN("%s not implemented.\n", debugstr_guid(riid
));
595 return E_NOINTERFACE
;
598 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
600 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
601 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
603 TRACE("%p, refcount %u.\n", iface
, refcount
);
608 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
610 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
611 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
613 TRACE("%p, refcount %u.\n", iface
, refcount
);
619 if (fontface
->cached
)
621 factory_lock(fontface
->factory
);
622 list_remove(&fontface
->cached
->entry
);
623 factory_unlock(fontface
->factory
);
624 heap_free(fontface
->cached
);
626 release_scriptshaping_cache(fontface
->shaping_cache
);
627 if (fontface
->vdmx
.context
)
628 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
629 if (fontface
->gasp
.context
)
630 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
631 if (fontface
->cpal
.context
)
632 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
633 if (fontface
->colr
.context
)
634 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
635 if (fontface
->kern
.context
)
636 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->kern
.context
);
638 IDWriteFontFile_Release(fontface
->file
);
639 if (fontface
->stream
)
640 IDWriteFontFileStream_Release(fontface
->stream
);
642 IDWriteLocalizedStrings_Release(fontface
->names
);
643 if (fontface
->family_names
)
644 IDWriteLocalizedStrings_Release(fontface
->family_names
);
645 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
647 if (fontface
->info_strings
[i
])
648 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
651 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
652 heap_free(fontface
->glyphs
[i
]);
654 font_funcs
->notify_release(iface
);
656 dwrite_cmap_release(&fontface
->cmap
);
657 IDWriteFactory7_Release(fontface
->factory
);
664 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
666 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
668 TRACE("%p.\n", iface
);
670 return fontface
->type
;
673 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
674 IDWriteFontFile
**fontfiles
)
676 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
678 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
682 *number_of_files
= 1;
686 if (!*number_of_files
)
689 IDWriteFontFile_AddRef(fontface
->file
);
690 *fontfiles
= fontface
->file
;
695 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
697 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
699 TRACE("%p.\n", iface
);
701 return fontface
->index
;
704 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
706 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
708 TRACE("%p.\n", iface
);
710 return fontface
->simulations
;
713 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
715 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
717 TRACE("%p.\n", iface
);
719 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
722 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
724 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
726 TRACE("%p, %p.\n", iface
, metrics
);
728 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
731 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
733 TRACE("%p.\n", iface
);
735 return font_funcs
->get_glyph_count(iface
);
738 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
739 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
741 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
745 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
751 FIXME("sideways metrics are not supported.\n");
753 for (i
= 0; i
< glyph_count
; i
++) {
754 DWRITE_GLYPH_METRICS metrics
;
756 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
759 font_funcs
->get_design_glyph_metrics(iface
, fontface
->metrics
.designUnitsPerEm
,
760 fontface
->typo_metrics
.ascent
, fontface
->simulations
, glyphs
[i
], &metrics
);
761 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
771 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
772 UINT32 count
, UINT16
*glyphs
)
774 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
777 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
784 memset(glyphs
, 0, count
* sizeof(*glyphs
));
788 for (i
= 0; i
< count
; ++i
)
789 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
794 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
795 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
797 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
798 struct file_stream_desc stream_desc
;
800 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
802 stream_desc
.stream
= fontface
->stream
;
803 stream_desc
.face_type
= fontface
->type
;
804 stream_desc
.face_index
= fontface
->index
;
805 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
808 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
810 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
812 TRACE("%p, %p.\n", iface
, table_context
);
814 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
817 static void apply_outline_point_offset(const D2D1_POINT_2F
*src
, const D2D1_POINT_2F
*offset
,
820 dst
->x
= src
->x
+ offset
->x
;
821 dst
->y
= src
->y
+ offset
->y
;
824 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
825 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
826 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
828 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
829 D2D1_POINT_2F
*origins
, baseline_origin
= { 0 };
830 struct dwrite_outline outline
= {{ 0 }};
831 D2D1_BEZIER_SEGMENT segment
;
833 DWRITE_GLYPH_RUN run
;
834 unsigned int i
, j
, p
;
837 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
838 count
, is_sideways
, is_rtl
, sink
);
840 if (!glyphs
|| !sink
)
846 run
.fontFace
= (IDWriteFontFace
*)iface
;
847 run
.fontEmSize
= emSize
;
848 run
.glyphCount
= count
;
849 run
.glyphIndices
= glyphs
;
850 run
.glyphAdvances
= advances
;
851 run
.glyphOffsets
= offsets
;
852 run
.isSideways
= is_sideways
;
853 run
.bidiLevel
= is_rtl
? 1 : 0;
855 if (!(origins
= heap_alloc(sizeof(*origins
) * count
)))
856 return E_OUTOFMEMORY
;
858 if (FAILED(hr
= compute_glyph_origins(&run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
, NULL
, origins
)))
864 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
866 for (i
= 0; i
< count
; ++i
)
868 outline
.tags
.count
= outline
.points
.count
= 0;
869 if (font_funcs
->get_glyph_outline(iface
, emSize
, fontface
->simulations
, glyphs
[i
], &outline
))
871 WARN("Failed to get glyph outline for glyph %u.\n", glyphs
[i
]);
875 for (j
= 0, p
= 0; j
< outline
.tags
.count
; ++j
)
877 switch (outline
.tags
.values
[j
])
879 case OUTLINE_BEGIN_FIGURE
:
880 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
881 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, point
, D2D1_FIGURE_BEGIN_FILLED
);
883 case OUTLINE_END_FIGURE
:
884 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
887 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
888 ID2D1SimplifiedGeometrySink_AddLines(sink
, &point
, 1);
891 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point1
);
892 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point2
);
893 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point3
);
894 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, &segment
, 1);
900 heap_free(outline
.tags
.values
);
901 heap_free(outline
.points
.values
);
907 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
908 float ppem
, unsigned int gasp
)
910 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
914 case DWRITE_MEASURING_MODE_NATURAL
:
916 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
917 mode
= DWRITE_RENDERING_MODE_NATURAL
;
919 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
922 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
923 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
925 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
926 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
935 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
936 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
938 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
942 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
945 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
949 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
950 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
953 ppem
= emSize
* ppdip
;
955 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
956 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
960 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
961 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
965 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
966 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
968 DWRITE_FONT_METRICS1 metrics1
;
969 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
970 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
974 static inline int round_metric(FLOAT metric
)
976 return (int)floorf(metric
+ 0.5f
);
979 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
981 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
984 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
987 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
988 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
989 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
991 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
992 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
993 DWRITE_MEASURING_MODE mode
;
998 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
999 glyph_count
, metrics
, is_sideways
);
1001 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1002 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
1004 size
= emSize
* ppdip
;
1005 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
1006 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1008 for (i
= 0; i
< glyph_count
; i
++) {
1009 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
1010 DWRITE_GLYPH_METRICS design
;
1013 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
1017 ret
->advanceWidth
= font_funcs
->get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
1019 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
1021 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
1023 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
1024 SCALE_METRIC(leftSideBearing
);
1025 SCALE_METRIC(rightSideBearing
);
1026 SCALE_METRIC(topSideBearing
);
1027 SCALE_METRIC(advanceHeight
);
1028 SCALE_METRIC(bottomSideBearing
);
1029 SCALE_METRIC(verticalOriginY
);
1036 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1038 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1040 TRACE("%p, %p.\n", iface
, metrics
);
1042 *metrics
= fontface
->metrics
;
1045 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
1046 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
1048 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1049 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
1050 UINT16 ascent
, descent
;
1053 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
1055 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
1056 memset(metrics
, 0, sizeof(*metrics
));
1057 return E_INVALIDARG
;
1060 em_size
*= pixels_per_dip
;
1061 if (m
&& m
->m22
!= 0.0f
)
1062 em_size
*= fabs(m
->m22
);
1064 scale
= em_size
/ design
->designUnitsPerEm
;
1065 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
1067 ascent
= round_metric(design
->ascent
* scale
);
1068 descent
= round_metric(design
->descent
* scale
);
1071 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
1072 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
1073 metrics
->ascent
= round_metric(ascent
/ scale
);
1074 metrics
->descent
= round_metric(descent
/ scale
);
1076 SCALE_METRIC(lineGap
);
1077 SCALE_METRIC(capHeight
);
1078 SCALE_METRIC(xHeight
);
1079 SCALE_METRIC(underlinePosition
);
1080 SCALE_METRIC(underlineThickness
);
1081 SCALE_METRIC(strikethroughPosition
);
1082 SCALE_METRIC(strikethroughThickness
);
1083 SCALE_METRIC(glyphBoxLeft
);
1084 SCALE_METRIC(glyphBoxTop
);
1085 SCALE_METRIC(glyphBoxRight
);
1086 SCALE_METRIC(glyphBoxBottom
);
1087 SCALE_METRIC(subscriptPositionX
);
1088 SCALE_METRIC(subscriptPositionY
);
1089 SCALE_METRIC(subscriptSizeX
);
1090 SCALE_METRIC(subscriptSizeY
);
1091 SCALE_METRIC(superscriptPositionX
);
1092 SCALE_METRIC(superscriptPositionY
);
1093 SCALE_METRIC(superscriptSizeX
);
1094 SCALE_METRIC(superscriptSizeY
);
1096 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
1102 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1104 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1106 TRACE("%p, %p.\n", iface
, metrics
);
1108 *metrics
= fontface
->caret
;
1111 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1112 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1114 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1116 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1119 if (max_count
&& !ranges
)
1120 return E_INVALIDARG
;
1122 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1123 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1126 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1128 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1130 TRACE("%p.\n", iface
);
1132 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1135 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1136 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1138 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1143 FIXME("Sideways mode is not supported.\n");
1145 switch (measuring_mode
)
1147 case DWRITE_MEASURING_MODE_NATURAL
:
1148 advance
= font_funcs
->get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1149 glyph
, measuring_mode
, &has_contours
);
1151 advance
+= adjustment
;
1154 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1155 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1160 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1161 FIXME("Transform is not supported.\n");
1163 advance
= font_funcs
->get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1166 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1168 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1172 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1177 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1178 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1180 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1183 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1186 FIXME("sideways mode not supported\n");
1188 for (i
= 0; i
< glyph_count
; ++i
)
1190 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1191 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1197 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1198 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1199 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1201 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1202 DWRITE_MEASURING_MODE measuring_mode
;
1205 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1206 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1208 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1209 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1210 return E_INVALIDARG
;
1213 if (em_size
== 0.0f
) {
1214 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1218 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1219 for (i
= 0; i
< glyph_count
; ++i
)
1221 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1222 glyphs
[i
], is_sideways
);
1228 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1229 const UINT16
*glyphs
, INT32
*values
)
1231 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1233 TRACE("%p, %u, %p, %p.\n", iface
, count
, glyphs
, values
);
1235 if (!(glyphs
|| values
) || !count
)
1236 return E_INVALIDARG
;
1238 if (!glyphs
|| count
== 1)
1240 memset(values
, 0, count
* sizeof(*values
));
1241 return E_INVALIDARG
;
1244 return opentype_get_kerning_pairs(fontface
, count
, glyphs
, values
);
1247 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1249 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1251 TRACE("%p.\n", iface
);
1253 return opentype_has_kerning_pairs(fontface
);
1256 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1257 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1258 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1260 DWRITE_GRID_FIT_MODE gridfitmode
;
1261 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1262 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1265 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1266 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1268 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1270 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1272 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1275 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1277 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1279 TRACE("%p.\n", iface
);
1281 return opentype_has_vertical_variants(fontface
);
1284 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1286 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1288 TRACE("%p.\n", iface
);
1290 return !!(fontface
->flags
& FONT_IS_COLORED
);
1293 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1295 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1297 TRACE("%p.\n", iface
);
1299 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1302 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1304 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1306 TRACE("%p.\n", iface
);
1308 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1311 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1312 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1314 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1316 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1318 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1321 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1322 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1323 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1324 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1326 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1330 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1331 measuringmode
, params
, renderingmode
, gridfitmode
);
1333 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1334 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1337 FIXME("sideways mode not supported\n");
1339 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1341 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1342 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1344 IDWriteRenderingParams2
*params2
;
1347 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1349 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1350 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1351 IDWriteRenderingParams2_Release(params2
);
1354 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1357 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1359 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1361 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1362 if (emSize
>= emthreshold
)
1363 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1365 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1368 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1369 if (emSize
>= emthreshold
)
1370 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1371 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1372 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1374 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1375 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1381 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1382 IDWriteFontFaceReference
**reference
)
1384 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1386 TRACE("%p, %p.\n", iface
, reference
);
1388 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1389 IDWriteFontFaceReference_AddRef(*reference
);
1394 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1396 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1398 TRACE("%p, %p.\n", iface
, panose
);
1400 *panose
= fontface
->panose
;
1403 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1405 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1407 TRACE("%p.\n", iface
);
1409 return fontface
->weight
;
1412 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1414 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1416 TRACE("%p.\n", iface
);
1418 return fontface
->stretch
;
1421 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1423 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1425 TRACE("%p.\n", iface
);
1427 return fontface
->style
;
1430 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1432 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1434 TRACE("%p, %p.\n", iface
, names
);
1436 return clone_localizedstrings(fontface
->family_names
, names
);
1439 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1441 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1443 TRACE("%p, %p.\n", iface
, names
);
1445 return clone_localizedstrings(fontface
->names
, names
);
1448 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1449 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1450 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1457 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1458 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1463 if (!strings_cache
[stringid
])
1465 struct file_stream_desc desc
= *stream_desc
;
1468 hr
= get_filestream_from_file(file
, &desc
.stream
);
1470 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1472 if (!stream_desc
->stream
&& desc
.stream
)
1473 IDWriteFontFileStream_Release(desc
.stream
);
1476 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1478 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1486 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1487 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1489 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1490 struct file_stream_desc stream_desc
;
1492 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1494 stream_desc
.stream
= fontface
->stream
;
1495 stream_desc
.face_index
= fontface
->index
;
1496 stream_desc
.face_type
= fontface
->type
;
1497 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1500 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1502 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1504 TRACE("%p, %#x.\n", iface
, ch
);
1506 return !!dwritefontface_get_glyph(fontface
, ch
);
1509 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1510 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1511 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1513 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1517 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1518 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1520 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1521 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1524 FIXME("sideways mode not supported\n");
1526 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1528 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1529 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1531 IDWriteRenderingParams3
*params3
;
1534 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1536 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1537 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1538 IDWriteRenderingParams3_Release(params3
);
1541 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1544 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1546 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1548 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1549 if (emSize
>= emthreshold
)
1550 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1552 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1555 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1556 if (emSize
>= emthreshold
)
1557 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1558 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1559 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1561 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1562 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1568 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1570 FIXME("%p, %#x: stub\n", iface
, ch
);
1575 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1577 FIXME("%p, %u: stub\n", iface
, glyph
);
1582 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1583 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1585 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1590 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1591 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1593 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1598 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1599 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1601 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1606 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1608 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1610 TRACE("%p.\n", iface
);
1612 return fontface
->glyph_image_formats
;
1615 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1616 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1618 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1623 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1625 FIXME("%p, %p: stub\n", iface
, context
);
1628 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1630 FIXME("%p: stub\n", iface
);
1635 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1638 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1643 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1648 FIXME("%p: stub\n", iface
);
1653 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1655 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1657 TRACE("%p, %p.\n", iface
, resource
);
1659 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->file
, fontface
->index
, resource
);
1662 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1664 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1666 TRACE("%p, %p.\n", iface
, other
);
1668 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1671 /* TODO: add variations support */
1673 return fontface
->index
== other_face
->index
&&
1674 fontface
->simulations
== other_face
->simulations
&&
1675 is_same_fontfile(fontface
->file
, other_face
->file
);
1678 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1680 dwritefontface_QueryInterface
,
1681 dwritefontface_AddRef
,
1682 dwritefontface_Release
,
1683 dwritefontface_GetType
,
1684 dwritefontface_GetFiles
,
1685 dwritefontface_GetIndex
,
1686 dwritefontface_GetSimulations
,
1687 dwritefontface_IsSymbolFont
,
1688 dwritefontface_GetMetrics
,
1689 dwritefontface_GetGlyphCount
,
1690 dwritefontface_GetDesignGlyphMetrics
,
1691 dwritefontface_GetGlyphIndices
,
1692 dwritefontface_TryGetFontTable
,
1693 dwritefontface_ReleaseFontTable
,
1694 dwritefontface_GetGlyphRunOutline
,
1695 dwritefontface_GetRecommendedRenderingMode
,
1696 dwritefontface_GetGdiCompatibleMetrics
,
1697 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1698 dwritefontface1_GetMetrics
,
1699 dwritefontface1_GetGdiCompatibleMetrics
,
1700 dwritefontface1_GetCaretMetrics
,
1701 dwritefontface1_GetUnicodeRanges
,
1702 dwritefontface1_IsMonospacedFont
,
1703 dwritefontface1_GetDesignGlyphAdvances
,
1704 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1705 dwritefontface1_GetKerningPairAdjustments
,
1706 dwritefontface1_HasKerningPairs
,
1707 dwritefontface1_GetRecommendedRenderingMode
,
1708 dwritefontface1_GetVerticalGlyphVariants
,
1709 dwritefontface1_HasVerticalGlyphVariants
,
1710 dwritefontface2_IsColorFont
,
1711 dwritefontface2_GetColorPaletteCount
,
1712 dwritefontface2_GetPaletteEntryCount
,
1713 dwritefontface2_GetPaletteEntries
,
1714 dwritefontface2_GetRecommendedRenderingMode
,
1715 dwritefontface3_GetFontFaceReference
,
1716 dwritefontface3_GetPanose
,
1717 dwritefontface3_GetWeight
,
1718 dwritefontface3_GetStretch
,
1719 dwritefontface3_GetStyle
,
1720 dwritefontface3_GetFamilyNames
,
1721 dwritefontface3_GetFaceNames
,
1722 dwritefontface3_GetInformationalStrings
,
1723 dwritefontface3_HasCharacter
,
1724 dwritefontface3_GetRecommendedRenderingMode
,
1725 dwritefontface3_IsCharacterLocal
,
1726 dwritefontface3_IsGlyphLocal
,
1727 dwritefontface3_AreCharactersLocal
,
1728 dwritefontface3_AreGlyphsLocal
,
1729 dwritefontface4_GetGlyphImageFormats_
,
1730 dwritefontface4_GetGlyphImageFormats
,
1731 dwritefontface4_GetGlyphImageData
,
1732 dwritefontface4_ReleaseGlyphImageData
,
1733 dwritefontface5_GetFontAxisValueCount
,
1734 dwritefontface5_GetFontAxisValues
,
1735 dwritefontface5_HasVariations
,
1736 dwritefontface5_GetFontResource
,
1737 dwritefontface5_Equals
,
1740 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1742 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1743 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1746 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1748 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1749 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1752 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1754 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1755 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1758 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1759 IDWriteFontFace3
**ret
)
1761 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1763 TRACE("%p, %p.\n", iface
, ret
);
1765 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1766 IDWriteFontFace3_AddRef(*ret
);
1771 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1772 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1774 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1775 DWRITE_FONT_FILE_TYPE file_type
;
1776 DWRITE_FONT_FACE_TYPE face_type
;
1777 IDWriteFontFace
*face
;
1782 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1784 hr
= IDWriteFontFile_Analyze(fontface
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
1788 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, &fontface
->file
, fontface
->index
,
1789 simulations
, &face
);
1792 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1793 IDWriteFontFace_Release(face
);
1799 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1801 FIXME("%p, %p.\n", iface
, ref
);
1806 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1808 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1810 TRACE("%p.\n", iface
);
1812 return fontface
->index
;
1815 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1817 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1819 TRACE("%p.\n", iface
);
1821 return fontface
->simulations
;
1824 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1826 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1828 TRACE("%p, %p.\n", iface
, file
);
1830 *file
= fontface
->file
;
1831 IDWriteFontFile_AddRef(*file
);
1836 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1838 FIXME("%p.\n", iface
);
1843 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1845 FIXME("%p.\n", iface
);
1850 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1852 FIXME("%p, %p.\n", iface
, writetime
);
1857 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1859 FIXME("%p.\n", iface
);
1861 return DWRITE_LOCALITY_LOCAL
;
1864 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1866 FIXME("%p.\n", iface
);
1871 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1872 WCHAR
const *chars
, UINT32 count
)
1874 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1879 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1880 UINT16
const *glyphs
, UINT32 count
)
1882 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1887 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1888 UINT64 offset
, UINT64 size
)
1890 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1895 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1897 dwritefontface_reference_QueryInterface
,
1898 dwritefontface_reference_AddRef
,
1899 dwritefontface_reference_Release
,
1900 dwritefontface_reference_CreateFontFace
,
1901 dwritefontface_reference_CreateFontFaceWithSimulations
,
1902 dwritefontface_reference_Equals
,
1903 dwritefontface_reference_GetFontFaceIndex
,
1904 dwritefontface_reference_GetSimulations
,
1905 dwritefontface_reference_GetFontFile
,
1906 dwritefontface_reference_GetLocalFileSize
,
1907 dwritefontface_reference_GetFileSize
,
1908 dwritefontface_reference_GetFileTime
,
1909 dwritefontface_reference_GetLocality
,
1910 dwritefontface_reference_EnqueueFontDownloadRequest
,
1911 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1912 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1913 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1916 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1918 struct dwrite_font_data
*data
= font
->data
;
1919 struct fontface_desc desc
;
1920 struct list
*cached_list
;
1925 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1926 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1930 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1933 desc
.factory
= font
->family
->collection
->factory
;
1934 desc
.face_type
= data
->face_type
;
1935 desc
.file
= data
->file
;
1936 desc
.index
= data
->face_index
;
1937 desc
.simulations
= data
->simulations
;
1938 desc
.font_data
= data
;
1939 hr
= create_fontface(&desc
, cached_list
, fontface
);
1941 IDWriteFontFileStream_Release(desc
.stream
);
1945 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1947 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1949 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1950 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1951 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1952 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1953 IsEqualIID(riid
, &IID_IUnknown
))
1956 IDWriteFont3_AddRef(iface
);
1960 WARN("%s not implemented.\n", debugstr_guid(riid
));
1963 return E_NOINTERFACE
;
1966 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1968 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1969 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
1971 TRACE("%p, refcount %d.\n", iface
, refcount
);
1976 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1978 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1979 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
1981 TRACE("%p, refcount %d.\n", iface
, refcount
);
1985 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
1986 release_font_data(font
->data
);
1993 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1995 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1997 TRACE("%p, %p.\n", iface
, family
);
1999 *family
= (IDWriteFontFamily
*)font
->family
;
2000 IDWriteFontFamily_AddRef(*family
);
2004 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
2006 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2008 TRACE("%p.\n", iface
);
2010 return font
->data
->weight
;
2013 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
2015 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2017 TRACE("%p.\n", iface
);
2019 return font
->data
->stretch
;
2022 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
2024 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2026 TRACE("%p.\n", iface
);
2031 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
2033 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2035 TRACE("%p.\n", iface
);
2037 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
2040 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
2042 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2044 TRACE("%p, %p.\n", iface
, names
);
2046 return clone_localizedstrings(font
->data
->names
, names
);
2049 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
2050 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
2052 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2053 struct dwrite_font_data
*data
= font
->data
;
2054 struct file_stream_desc stream_desc
;
2056 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
2058 /* Stream will be created if necessary. */
2059 stream_desc
.stream
= NULL
;
2060 stream_desc
.face_index
= data
->face_index
;
2061 stream_desc
.face_type
= data
->face_type
;
2062 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
2065 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
2067 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2069 TRACE("%p.\n", iface
);
2071 return font
->data
->simulations
;
2074 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
2076 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2078 TRACE("%p, %p.\n", iface
, metrics
);
2080 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
2083 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
2086 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2087 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
2091 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2093 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2095 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2097 *exists
= dwritefont_has_character(font
, ch
);
2102 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2104 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2106 TRACE("%p, %p.\n", iface
, fontface
);
2108 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2111 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2113 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2115 TRACE("%p, %p.\n", iface
, metrics
);
2117 *metrics
= font
->data
->metrics
;
2120 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2122 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2124 TRACE("%p, %p.\n", iface
, panose
);
2126 *panose
= font
->data
->panose
;
2129 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2132 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2134 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2137 if (max_count
&& !ranges
)
2138 return E_INVALIDARG
;
2140 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2141 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2144 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2146 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2148 TRACE("%p.\n", iface
);
2150 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2153 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2155 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2157 TRACE("%p.\n", iface
);
2159 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2162 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2164 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2166 TRACE("%p, %p.\n", iface
, fontface
);
2168 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2171 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2173 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2175 TRACE("%p, %p.\n", iface
, other
);
2177 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2180 return font
->data
->face_index
== other_font
->data
->face_index
2181 && font
->data
->simulations
== other_font
->data
->simulations
2182 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2185 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2187 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2189 TRACE("%p, %p.\n", iface
, reference
);
2191 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2192 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2193 (IDWriteFontFaceReference1
**)reference
);
2196 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2198 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2200 TRACE("%p, %#x.\n", iface
, ch
);
2202 return dwritefont_has_character(font
, ch
);
2205 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2207 FIXME("%p: stub.\n", iface
);
2209 return DWRITE_LOCALITY_LOCAL
;
2212 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2213 dwritefont_QueryInterface
,
2216 dwritefont_GetFontFamily
,
2217 dwritefont_GetWeight
,
2218 dwritefont_GetStretch
,
2219 dwritefont_GetStyle
,
2220 dwritefont_IsSymbolFont
,
2221 dwritefont_GetFaceNames
,
2222 dwritefont_GetInformationalStrings
,
2223 dwritefont_GetSimulations
,
2224 dwritefont_GetMetrics
,
2225 dwritefont_HasCharacter
,
2226 dwritefont_CreateFontFace
,
2227 dwritefont1_GetMetrics
,
2228 dwritefont1_GetPanose
,
2229 dwritefont1_GetUnicodeRanges
,
2230 dwritefont1_IsMonospacedFont
,
2231 dwritefont2_IsColorFont
,
2232 dwritefont3_CreateFontFace
,
2234 dwritefont3_GetFontFaceReference
,
2235 dwritefont3_HasCharacter
,
2236 dwritefont3_GetLocality
2239 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2243 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2244 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2247 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2251 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2252 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2255 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2259 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2261 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2262 IDWriteFontFaceReference1_iface
);
2265 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2267 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2268 *lf
= font
->data
->lf
;
2271 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2273 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2277 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2279 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2280 *fontsig
= font
->data
->fontsig
;
2284 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2286 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2287 *fontsig
= fontface
->fontsig
;
2291 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2293 struct dwrite_font
*object
;
2297 if (!(object
= heap_alloc(sizeof(*object
))))
2298 return E_OUTOFMEMORY
;
2300 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2301 object
->refcount
= 1;
2302 object
->family
= family
;
2303 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2304 object
->data
= family
->data
->fonts
[index
];
2305 object
->style
= object
->data
->style
;
2306 addref_font_data(object
->data
);
2308 *font
= &object
->IDWriteFont3_iface
;
2313 /* IDWriteFontList2 */
2314 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2316 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2318 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2319 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2320 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2321 IsEqualIID(riid
, &IID_IUnknown
))
2324 IDWriteFontList2_AddRef(iface
);
2328 WARN("%s not implemented.\n", debugstr_guid(riid
));
2331 return E_NOINTERFACE
;
2334 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2336 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2337 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2339 TRACE("%p, refcount %u.\n", iface
, refcount
);
2344 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2346 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2347 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2349 TRACE("%p, refcount %u.\n", iface
, refcount
);
2355 for (i
= 0; i
< fontlist
->font_count
; i
++)
2356 release_font_data(fontlist
->fonts
[i
]);
2357 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2358 heap_free(fontlist
->fonts
);
2359 heap_free(fontlist
);
2365 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2367 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2368 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2371 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2373 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2375 TRACE("%p.\n", iface
);
2377 return fontlist
->font_count
;
2380 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2382 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2384 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2388 if (fontlist
->font_count
== 0)
2391 if (index
>= fontlist
->font_count
)
2392 return E_INVALIDARG
;
2394 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2397 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2399 FIXME("%p, %u.\n", iface
, index
);
2401 return DWRITE_LOCALITY_LOCAL
;
2404 static HRESULT
fontlist_get_font(const struct dwrite_fontlist
*fontlist
, unsigned int index
,
2405 IDWriteFont3
**font
)
2409 if (fontlist
->font_count
== 0)
2412 if (index
>= fontlist
->font_count
)
2415 return create_font(fontlist
->family
, index
, font
);
2418 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2420 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2422 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2424 return fontlist_get_font(fontlist
, index
, font
);
2427 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2428 IDWriteFontFaceReference
**reference
)
2430 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2434 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2438 if (SUCCEEDED(hr
= fontlist_get_font(fontlist
, index
, &font
)))
2440 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2441 IDWriteFont3_Release(font
);
2447 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2449 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2451 TRACE("%p, %p.\n", iface
, fontset
);
2453 return fontset_create_from_font_data(fontlist
->family
->collection
->factory
, fontlist
->fonts
,
2454 fontlist
->font_count
, fontset
);
2457 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2459 dwritefontlist_QueryInterface
,
2460 dwritefontlist_AddRef
,
2461 dwritefontlist_Release
,
2462 dwritefontlist_GetFontCollection
,
2463 dwritefontlist_GetFontCount
,
2464 dwritefontlist_GetFont
,
2465 dwritefontlist1_GetFontLocality
,
2466 dwritefontlist1_GetFont
,
2467 dwritefontlist1_GetFontFaceReference
,
2468 dwritefontlist2_GetFontSet
,
2471 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2473 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2475 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2477 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2478 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2479 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2480 IsEqualIID(riid
, &IID_IUnknown
))
2484 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2485 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2486 IsEqualIID(riid
, &IID_IDWriteFontList
))
2488 *obj
= &family
->IDWriteFontList2_iface
;
2492 WARN("%s not implemented.\n", debugstr_guid(riid
));
2494 return E_NOINTERFACE
;
2497 IUnknown_AddRef((IUnknown
*)*obj
);
2501 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2503 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2504 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2506 TRACE("%p, %u.\n", iface
, refcount
);
2511 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2513 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2514 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2516 TRACE("%p, %u.\n", iface
, refcount
);
2520 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2521 release_fontfamily_data(family
->data
);
2528 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2530 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2532 TRACE("%p, %p.\n", iface
, collection
);
2534 *collection
= (IDWriteFontCollection
*)family
->collection
;
2535 IDWriteFontCollection_AddRef(*collection
);
2539 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2541 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2543 TRACE("%p.\n", iface
);
2545 return family
->data
->count
;
2548 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2550 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2552 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2556 if (!family
->data
->count
)
2559 if (index
>= family
->data
->count
)
2560 return E_INVALIDARG
;
2562 return create_font(family
, index
, (IDWriteFont3
**)font
);
2565 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2567 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2569 TRACE("%p, %p.\n", iface
, names
);
2571 return clone_localizedstrings(family
->data
->familyname
, names
);
2574 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2575 const struct dwrite_font_propvec
*req
)
2577 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2578 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2579 FLOAT cur_req_prod
, next_req_prod
;
2581 if (next_to_req
< cur_to_req
)
2584 if (next_to_req
> cur_to_req
)
2587 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2588 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2590 if (next_req_prod
> cur_req_prod
)
2593 if (next_req_prod
< cur_req_prod
)
2596 if (next
->stretch
> cur
->stretch
)
2598 if (next
->stretch
< cur
->stretch
)
2601 if (next
->style
> cur
->style
)
2603 if (next
->style
< cur
->style
)
2606 if (next
->weight
> cur
->weight
)
2608 if (next
->weight
< cur
->weight
)
2611 /* full match, no reason to prefer new variant */
2615 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2616 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2618 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2619 struct dwrite_font_propvec req
;
2622 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2624 if (!family
->data
->count
)
2627 return DWRITE_E_NOFONT
;
2630 init_font_prop_vec(weight
, stretch
, style
, &req
);
2633 for (i
= 1; i
< family
->data
->count
; ++i
)
2635 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2639 return create_font(family
, match
, (IDWriteFont3
**)font
);
2642 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2644 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2646 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2649 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2651 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2654 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2656 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2661 for (j
= 0; j
< b
; j
++) {
2662 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2663 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2664 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2665 fonts
->fonts
[j
+1] = s
;
2676 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2677 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2679 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2680 matching_filter_func func
= NULL
;
2681 struct dwrite_font_propvec req
;
2682 struct dwrite_fontlist
*fonts
;
2685 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2689 fonts
= heap_alloc(sizeof(*fonts
));
2691 return E_OUTOFMEMORY
;
2693 /* Allocate as many as family has, not all of them will be necessary used. */
2694 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2695 if (!fonts
->fonts
) {
2697 return E_OUTOFMEMORY
;
2700 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2701 fonts
->refcount
= 1;
2702 fonts
->family
= family
;
2703 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2704 fonts
->font_count
= 0;
2706 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2707 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2708 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2709 func
= is_font_acceptable_for_normal
;
2711 else /* requested oblique or italic */ {
2712 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2713 func
= is_font_acceptable_for_oblique_italic
;
2716 for (i
= 0; i
< family
->data
->count
; ++i
)
2718 if (!func
|| func(family
->data
->fonts
[i
]))
2720 fonts
->fonts
[fonts
->font_count
++] = addref_font_data(family
->data
->fonts
[i
]);
2724 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2725 init_font_prop_vec(weight
, stretch
, style
, &req
);
2726 matchingfonts_sort(fonts
, &req
);
2728 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2732 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2734 FIXME("%p, %u.\n", iface
, index
);
2736 return DWRITE_LOCALITY_LOCAL
;
2739 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2741 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2743 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2747 if (!family
->data
->count
)
2750 if (index
>= family
->data
->count
)
2753 return create_font(family
, index
, font
);
2756 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2757 IDWriteFontFaceReference
**reference
)
2759 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2760 const struct dwrite_font_data
*font
;
2762 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2766 if (index
>= family
->data
->count
)
2769 font
= family
->data
->fonts
[index
];
2770 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2771 font
->file
, font
->face_index
, font
->simulations
, reference
);
2774 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2775 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2777 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2782 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2784 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2786 TRACE("%p, %p.\n", iface
, fontset
);
2788 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
2789 family
->data
->count
, fontset
);
2792 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2794 dwritefontfamily_QueryInterface
,
2795 dwritefontfamily_AddRef
,
2796 dwritefontfamily_Release
,
2797 dwritefontfamily_GetFontCollection
,
2798 dwritefontfamily_GetFontCount
,
2799 dwritefontfamily_GetFont
,
2800 dwritefontfamily_GetFamilyNames
,
2801 dwritefontfamily_GetFirstMatchingFont
,
2802 dwritefontfamily_GetMatchingFonts
,
2803 dwritefontfamily1_GetFontLocality
,
2804 dwritefontfamily1_GetFont
,
2805 dwritefontfamily1_GetFontFaceReference
,
2806 dwritefontfamily2_GetMatchingFonts
,
2807 dwritefontfamily2_GetFontSet
,
2810 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2812 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2813 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2816 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2818 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2819 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2822 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2824 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2825 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2828 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2829 IDWriteFontCollection
**collection
)
2831 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2832 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2835 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2837 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2838 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2841 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2843 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2844 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2847 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2849 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2850 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2853 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2855 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2856 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2859 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2860 IDWriteFontFaceReference
**reference
)
2862 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2863 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2866 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2868 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2870 TRACE("%p, %p.\n", iface
, fontset
);
2872 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
2873 family
->data
->count
, fontset
);
2876 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2878 dwritefontfamilylist_QueryInterface
,
2879 dwritefontfamilylist_AddRef
,
2880 dwritefontfamilylist_Release
,
2881 dwritefontfamilylist_GetFontCollection
,
2882 dwritefontfamilylist_GetFontCount
,
2883 dwritefontfamilylist_GetFont
,
2884 dwritefontfamilylist1_GetFontLocality
,
2885 dwritefontfamilylist1_GetFont
,
2886 dwritefontfamilylist1_GetFontFaceReference
,
2887 dwritefontfamilylist2_GetFontSet
,
2890 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2891 struct dwrite_fontfamily
**family
)
2893 struct dwrite_fontfamily
*object
;
2897 object
= heap_alloc(sizeof(*object
));
2899 return E_OUTOFMEMORY
;
2901 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2902 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2903 object
->refcount
= 1;
2904 object
->collection
= collection
;
2905 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2906 object
->data
= collection
->family_data
[index
];
2907 InterlockedIncrement(&object
->data
->refcount
);
2914 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2917 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2920 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2922 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2924 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2926 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2927 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2928 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2929 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2930 IsEqualIID(riid
, &IID_IUnknown
))
2933 IDWriteFontCollection3_AddRef(iface
);
2939 if (IsEqualIID(riid
, &IID_issystemcollection
))
2942 WARN("%s not implemented.\n", debugstr_guid(riid
));
2944 return E_NOINTERFACE
;
2947 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2949 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2951 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2952 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2953 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2954 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2955 IsEqualIID(riid
, &IID_IUnknown
))
2958 IDWriteFontCollection3_AddRef(iface
);
2962 WARN("%s not implemented.\n", debugstr_guid(riid
));
2966 return E_NOINTERFACE
;
2969 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2971 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2972 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2974 TRACE("%p, refcount %d.\n", collection
, refcount
);
2979 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2981 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2982 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2985 TRACE("%p, refcount %d.\n", iface
, refcount
);
2989 factory_detach_fontcollection(collection
->factory
, iface
);
2990 for (i
= 0; i
< collection
->count
; ++i
)
2991 release_fontfamily_data(collection
->family_data
[i
]);
2992 heap_free(collection
->family_data
);
2993 heap_free(collection
);
2999 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
3001 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3003 TRACE("%p.\n", iface
);
3005 return collection
->count
;
3008 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3009 IDWriteFontFamily
**ret
)
3011 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3012 struct dwrite_fontfamily
*family
;
3015 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3019 if (index
>= collection
->count
)
3022 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3023 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
3028 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
3032 for (i
= 0; i
< collection
->count
; ++i
)
3034 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
3035 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
3038 for (j
= 0; j
< count
; j
++)
3041 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
3042 if (SUCCEEDED(hr
) && !wcsicmp(buffer
, name
))
3050 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
3051 UINT32
*index
, BOOL
*exists
)
3053 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3055 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
3057 *index
= collection_find_family(collection
, name
);
3058 *exists
= *index
!= ~0u;
3062 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
3065 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3066 struct dwrite_fontfamily
*family
;
3067 BOOL found_font
= FALSE
;
3068 IDWriteFontFile
*file
;
3069 UINT32 face_index
, count
;
3073 TRACE("%p, %p, %p.\n", iface
, face
, font
);
3078 return E_INVALIDARG
;
3081 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
3084 face_index
= IDWriteFontFace_GetIndex(face
);
3087 for (i
= 0; i
< collection
->count
; ++i
)
3089 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
3091 for (j
= 0; j
< family_data
->count
; ++j
)
3093 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
3095 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
3104 IDWriteFontFile_Release(file
);
3107 return DWRITE_E_NOFONT
;
3109 hr
= create_fontfamily(collection
, i
, &family
);
3113 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3114 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3118 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3120 FIXME("%p, %p.\n", iface
, fontset
);
3125 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3126 IDWriteFontFamily1
**ret
)
3128 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3129 struct dwrite_fontfamily
*family
;
3132 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3136 if (index
>= collection
->count
)
3139 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3140 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3145 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3146 UINT32 index
, IDWriteFontFamily2
**ret
)
3148 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3149 struct dwrite_fontfamily
*family
;
3152 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3156 if (index
>= collection
->count
)
3159 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3160 *ret
= &family
->IDWriteFontFamily2_iface
;
3165 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3166 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3167 IDWriteFontList2
**fontlist
)
3169 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3174 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3176 FIXME("%p.\n", iface
);
3178 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3181 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3183 FIXME("%p, %p.\n", iface
, fontset
);
3188 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3190 FIXME("%p.\n", iface
);
3195 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3197 dwritefontcollection_QueryInterface
,
3198 dwritefontcollection_AddRef
,
3199 dwritefontcollection_Release
,
3200 dwritefontcollection_GetFontFamilyCount
,
3201 dwritefontcollection_GetFontFamily
,
3202 dwritefontcollection_FindFamilyName
,
3203 dwritefontcollection_GetFontFromFontFace
,
3204 dwritefontcollection1_GetFontSet
,
3205 dwritefontcollection1_GetFontFamily
,
3206 dwritefontcollection2_GetFontFamily
,
3207 dwritefontcollection2_GetMatchingFonts
,
3208 dwritefontcollection2_GetFontFamilyModel
,
3209 dwritefontcollection2_GetFontSet
,
3210 dwritefontcollection3_GetExpirationEvent
,
3213 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3215 dwritesystemfontcollection_QueryInterface
,
3216 dwritefontcollection_AddRef
,
3217 dwritefontcollection_Release
,
3218 dwritefontcollection_GetFontFamilyCount
,
3219 dwritefontcollection_GetFontFamily
,
3220 dwritefontcollection_FindFamilyName
,
3221 dwritefontcollection_GetFontFromFontFace
,
3222 dwritefontcollection1_GetFontSet
,
3223 dwritefontcollection1_GetFontFamily
,
3224 dwritefontcollection2_GetFontFamily
,
3225 dwritefontcollection2_GetMatchingFonts
,
3226 dwritefontcollection2_GetFontFamilyModel
,
3227 dwritefontcollection2_GetFontSet
,
3228 dwritefontcollection3_GetExpirationEvent
,
3231 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3233 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3234 sizeof(*family_data
->fonts
)))
3236 return E_OUTOFMEMORY
;
3239 family_data
->fonts
[family_data
->count
++] = font_data
;
3240 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3241 family_data
->has_normal_face
= 1;
3242 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3243 family_data
->has_oblique_face
= 1;
3245 family_data
->has_italic_face
= 1;
3249 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3250 struct dwrite_fontfamily_data
*family
)
3252 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3253 sizeof(*collection
->family_data
)))
3255 return E_OUTOFMEMORY
;
3258 collection
->family_data
[collection
->count
++] = family
;
3262 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3264 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3265 collection
->refcount
= 1;
3266 collection
->count
= 0;
3267 collection
->size
= 0;
3268 collection
->family_data
= NULL
;
3273 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3275 IDWriteFontFileLoader
*loader
;
3282 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3286 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3290 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3291 IDWriteFontFileLoader_Release(loader
);
3298 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3300 BOOL exists
= FALSE
;
3305 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-us", &index
, &exists
);
3306 if (FAILED(hr
) || !exists
)
3309 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3312 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3316 while (iswspace(*in
))
3320 if (!(len
= wcslen(in
)))
3323 while (iswspace(in
[len
-1]))
3326 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3335 INT len
; /* token length */
3336 INT fulllen
; /* full length including following separators */
3339 static inline BOOL
is_name_separator_char(WCHAR ch
)
3341 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3344 struct name_pattern
{
3345 const WCHAR
*part1
; /* NULL indicates end of list */
3346 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3349 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3351 const struct name_pattern
*pattern
;
3352 struct name_token
*token
;
3355 while ((pattern
= &patterns
[i
++])->part1
)
3357 int len_part1
= wcslen(pattern
->part1
);
3358 int len_part2
= pattern
->part2
? wcslen(pattern
->part2
) : 0;
3360 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3361 if (len_part2
== 0) {
3362 /* simple case with single part pattern */
3363 if (token
->len
!= len_part1
)
3366 if (!wcsnicmp(token
->ptr
, pattern
->part1
, len_part1
))
3368 if (match
) *match
= *token
;
3369 list_remove(&token
->entry
);
3375 struct name_token
*next_token
;
3376 struct list
*next_entry
;
3378 /* pattern parts are stored in reading order, tokens list is reversed */
3379 if (token
->len
< len_part2
)
3382 /* it's possible to have combined string as a token, like ExtraCondensed */
3383 if (token
->len
== len_part1
+ len_part2
)
3385 if (wcsnicmp(token
->ptr
, pattern
->part1
, len_part1
))
3388 if (wcsnicmp(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3391 /* combined string match */
3392 if (match
) *match
= *token
;
3393 list_remove(&token
->entry
);
3398 /* now it's only possible to have two tokens matched to respective pattern parts */
3399 if (token
->len
!= len_part2
)
3402 next_entry
= list_next(tokens
, &token
->entry
);
3404 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3405 if (next_token
->len
!= len_part1
)
3408 if (wcsnicmp(token
->ptr
, pattern
->part2
, len_part2
))
3411 if (wcsnicmp(next_token
->ptr
, pattern
->part1
, len_part1
))
3414 /* both parts matched, remove tokens */
3416 match
->ptr
= next_token
->ptr
;
3417 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3419 list_remove(&token
->entry
);
3420 list_remove(&next_token
->entry
);
3421 heap_free(next_token
);
3436 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3438 static const struct name_pattern italic_patterns
[] =
3448 static const struct name_pattern oblique_patterns
[] =
3458 /* italic patterns first */
3459 if (match_pattern_list(tokens
, italic_patterns
, match
))
3460 return DWRITE_FONT_STYLE_ITALIC
;
3462 /* oblique patterns */
3463 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3464 return DWRITE_FONT_STYLE_OBLIQUE
;
3469 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3470 struct name_token
*match
)
3472 static const struct name_pattern ultracondensed_patterns
[] =
3474 { L
"extra", L
"compressed" },
3475 { L
"ext", L
"compressed" },
3476 { L
"ultra", L
"compressed" },
3477 { L
"ultra", L
"condensed" },
3478 { L
"ultra", L
"cond" },
3482 static const struct name_pattern extracondensed_patterns
[] =
3485 { L
"extra", L
"condensed" },
3486 { L
"ext", L
"condensed" },
3487 { L
"extra", L
"cond" },
3488 { L
"ext", L
"cond" },
3492 static const struct name_pattern semicondensed_patterns
[] =
3496 { L
"semi", L
"condensed" },
3497 { L
"semi", L
"cond" },
3501 static const struct name_pattern semiexpanded_patterns
[] =
3504 { L
"semi", L
"expanded" },
3505 { L
"semi", L
"extended" },
3509 static const struct name_pattern extraexpanded_patterns
[] =
3511 { L
"extra", L
"expanded" },
3512 { L
"ext", L
"expanded" },
3513 { L
"extra", L
"extended" },
3514 { L
"ext", L
"extended" },
3518 static const struct name_pattern ultraexpanded_patterns
[] =
3520 { L
"ultra", L
"expanded" },
3521 { L
"ultra", L
"extended" },
3525 static const struct name_pattern condensed_patterns
[] =
3532 static const struct name_pattern expanded_patterns
[] =
3539 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3540 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3542 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3543 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3545 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3546 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3548 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3549 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3551 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3552 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3554 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3555 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3557 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3558 return DWRITE_FONT_STRETCH_CONDENSED
;
3560 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3561 return DWRITE_FONT_STRETCH_EXPANDED
;
3566 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3567 struct name_token
*match
)
3569 static const struct name_pattern thin_patterns
[] =
3571 { L
"extra", L
"thin" },
3572 { L
"ext", L
"thin" },
3573 { L
"ultra", L
"thin" },
3577 static const struct name_pattern extralight_patterns
[] =
3579 { L
"extra", L
"light" },
3580 { L
"ext", L
"light" },
3581 { L
"ultra", L
"light" },
3585 static const struct name_pattern semilight_patterns
[] =
3587 { L
"semi", L
"light" },
3591 static const struct name_pattern demibold_patterns
[] =
3593 { L
"semi", L
"bold" },
3594 { L
"demi", L
"bold" },
3598 static const struct name_pattern extrabold_patterns
[] =
3600 { L
"extra", L
"bold" },
3601 { L
"ext", L
"bold" },
3602 { L
"ultra", L
"bold" },
3606 static const struct name_pattern extrablack_patterns
[] =
3608 { L
"extra", L
"black" },
3609 { L
"ext", L
"black" },
3610 { L
"ultra", L
"black" },
3614 static const struct name_pattern bold_patterns
[] =
3620 static const struct name_pattern thin2_patterns
[] =
3626 static const struct name_pattern light_patterns
[] =
3632 static const struct name_pattern medium_patterns
[] =
3638 static const struct name_pattern black_patterns
[] =
3646 static const struct name_pattern demibold2_patterns
[] =
3652 static const struct name_pattern extrabold2_patterns
[] =
3658 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3659 matching pattern. */
3661 if (match_pattern_list(tokens
, thin_patterns
, match
))
3662 return DWRITE_FONT_WEIGHT_THIN
;
3664 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3665 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3667 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3668 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3670 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3671 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3673 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3674 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3676 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3677 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3679 if (match_pattern_list(tokens
, bold_patterns
, match
))
3680 return DWRITE_FONT_WEIGHT_BOLD
;
3682 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3683 return DWRITE_FONT_WEIGHT_THIN
;
3685 if (match_pattern_list(tokens
, light_patterns
, match
))
3686 return DWRITE_FONT_WEIGHT_LIGHT
;
3688 if (match_pattern_list(tokens
, medium_patterns
, match
))
3689 return DWRITE_FONT_WEIGHT_MEDIUM
;
3691 if (match_pattern_list(tokens
, black_patterns
, match
))
3692 return DWRITE_FONT_WEIGHT_BLACK
;
3694 if (match_pattern_list(tokens
, black_patterns
, match
))
3695 return DWRITE_FONT_WEIGHT_BLACK
;
3697 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3698 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3700 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3701 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3703 /* FIXME: use abbreviated names to extract weight */
3708 struct knownweight_entry
3711 DWRITE_FONT_WEIGHT weight
;
3714 static int __cdecl
compare_knownweights(const void *a
, const void* b
)
3716 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3717 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3720 if (target
> entry
->weight
)
3722 else if (target
< entry
->weight
)
3728 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3730 static const struct knownweight_entry knownweights
[] =
3732 { L
"Thin", DWRITE_FONT_WEIGHT_THIN
},
3733 { L
"Extra Light", DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3734 { L
"Light", DWRITE_FONT_WEIGHT_LIGHT
},
3735 { L
"Semi Light", DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3736 { L
"Medium", DWRITE_FONT_WEIGHT_MEDIUM
},
3737 { L
"Demi Bold", DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3738 { L
"Bold", DWRITE_FONT_WEIGHT_BOLD
},
3739 { L
"Extra Bold", DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3740 { L
"Black", DWRITE_FONT_WEIGHT_BLACK
},
3741 { L
"Extra Black", DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3743 const struct knownweight_entry
*ptr
;
3745 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(*knownweights
),
3746 compare_knownweights
);
3752 wcscpy(nameW
, ptr
->nameW
);
3756 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3758 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3759 strW
[name
->len
] = 0;
3762 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3763 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3765 static const WCHAR
*regular_patterns
[] =
3775 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3779 len
= wcslen(facenameW
);
3781 /* remove rightmost regular variant from face name */
3782 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++]))
3784 int pattern_len
= wcslen(ptr
);
3787 if (pattern_len
> len
)
3790 src
= facenameW
+ len
- pattern_len
;
3791 while (src
>= facenameW
)
3793 if (!wcsnicmp(src
, ptr
, pattern_len
))
3795 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3796 len
= wcslen(facenameW
);
3808 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3816 struct name_token
*token
= heap_alloc(sizeof(*token
));
3821 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3827 /* skip separators */
3828 while (is_name_separator_char(*ptr
)) {
3833 list_add_head(tokens
, &token
->entry
);
3837 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3839 struct name_token
*token
, *token2
;
3840 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3843 list_remove(&token
->entry
);
3845 /* don't include last separator */
3846 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3847 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3855 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3857 struct name_token stretch_name
, weight_name
, style_name
;
3858 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3859 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3860 const WCHAR
*regular_ptr
= NULL
;
3861 DWRITE_FONT_STRETCH stretch
;
3862 DWRITE_FONT_WEIGHT weight
;
3866 /* remove leading and trailing spaces from family and face name */
3867 trim_spaces(familyW
, familynameW
);
3868 len
= trim_spaces(faceW
, facenameW
);
3870 /* remove rightmost regular variant from face name */
3871 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3873 /* append face name to family name, FIXME check if face name is a substring of family name */
3876 wcscat(familynameW
, L
" ");
3877 wcscat(familynameW
, facenameW
);
3880 /* tokenize with " .-_" */
3881 fontname_tokenize(&tokens
, familynameW
);
3883 /* extract and resolve style */
3884 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3886 /* extract stretch */
3887 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3889 /* extract weight */
3890 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3892 /* resolve weight */
3893 if (weight
!= font
->weight
)
3895 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3896 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3897 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3898 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3899 !(abs((int)weight
- (int)font
->weight
) <= 150 &&
3900 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3901 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3902 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
))
3904 font
->weight
= weight
;
3908 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3909 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3910 stretch itself is normal (extracted stretch is never normal). */
3911 if (stretch
!= font
->stretch
) {
3912 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3913 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3914 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3916 font
->stretch
= stretch
;
3920 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3922 /* get final combined string from what's left in token list, list is released */
3923 fontname_tokens_to_str(&tokens
, finalW
);
3925 if (!wcscmp(familyW
, finalW
))
3928 /* construct face name */
3929 wcscpy(familyW
, finalW
);
3931 /* resolved weight name */
3932 if (weight_name
.ptr
)
3933 font_name_token_to_str(&weight_name
, weightW
);
3934 /* ignore normal weight */
3935 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3937 /* for known weight values use appropriate names */
3938 else if (is_known_weight_value(font
->weight
, weightW
)) {
3940 /* use Wnnn format as a fallback in case weight is not one of known values */
3942 swprintf(weightW
, ARRAY_SIZE(weightW
), L
"W%d", font
->weight
);
3944 /* resolved stretch name */
3945 if (stretch_name
.ptr
)
3946 font_name_token_to_str(&stretch_name
, stretchW
);
3947 /* ignore normal stretch */
3948 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3950 /* use predefined stretch names */
3953 static const WCHAR
*stretchnamesW
[] =
3955 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3960 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3966 wcscpy(stretchW
, stretchnamesW
[font
->stretch
]);
3969 /* resolved style name */
3971 font_name_token_to_str(&style_name
, styleW
);
3972 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3974 /* use predefined names */
3976 wcscpy(styleW
, font
->style
== DWRITE_FONT_STYLE_ITALIC
? L
"Italic" : L
"Oblique");
3978 /* use Regular match if it was found initially */
3979 if (!*weightW
&& !*stretchW
&& !*styleW
)
3980 wcscpy(faceW
, regular_ptr
? regular_ptr
: L
"Regular");
3985 if (*stretchW
) wcscpy(faceW
, stretchW
);
3989 if (*faceW
) wcscat(faceW
, L
" ");
3990 wcscat(faceW
, weightW
);
3995 if (*faceW
) wcscat(faceW
, L
" ");
3996 wcscat(faceW
, styleW
);
4000 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
4004 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
4006 static const float width_axis_values
[] =
4008 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4009 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
4010 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
4011 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
4012 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
4013 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
4014 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
4015 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
4016 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
4017 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
4020 struct file_stream_desc stream_desc
;
4021 struct dwrite_font_props props
;
4022 struct dwrite_font_data
*data
;
4023 WCHAR familyW
[255], faceW
[255];
4028 data
= heap_alloc_zero(sizeof(*data
));
4030 return E_OUTOFMEMORY
;
4033 data
->file
= desc
->file
;
4034 data
->face_index
= desc
->index
;
4035 data
->face_type
= desc
->face_type
;
4036 IDWriteFontFile_AddRef(data
->file
);
4038 stream_desc
.stream
= desc
->stream
;
4039 stream_desc
.face_type
= desc
->face_type
;
4040 stream_desc
.face_index
= desc
->index
;
4041 opentype_get_font_properties(&stream_desc
, &props
);
4042 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
4043 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
4045 /* get family name from font file */
4046 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
4048 WARN("unable to get family name from font\n");
4049 release_font_data(data
);
4053 data
->style
= props
.style
;
4054 data
->stretch
= props
.stretch
;
4055 data
->weight
= props
.weight
;
4056 data
->panose
= props
.panose
;
4057 data
->fontsig
= props
.fontsig
;
4058 data
->lf
= props
.lf
;
4059 data
->flags
= props
.flags
;
4061 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4062 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
4063 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
4064 set_en_localizedstring(data
->family_names
, familyW
);
4065 set_en_localizedstring(data
->names
, faceW
);
4068 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4070 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
4071 data
->axis
[0].value
= props
.weight
;
4072 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
4073 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
4074 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
4075 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
4081 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS simulations
,
4082 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
4084 struct dwrite_font_data
*data
;
4088 data
= heap_alloc_zero(sizeof(*data
));
4090 return E_OUTOFMEMORY
;
4094 data
->simulations
|= simulations
;
4095 if (simulations
& DWRITE_FONT_SIMULATIONS_BOLD
)
4096 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
4097 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4098 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4099 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4101 IDWriteFontFile_AddRef(data
->file
);
4102 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4104 create_localizedstrings(&data
->names
);
4105 add_localizedstring(data
->names
, L
"en-us", facenameW
);
4107 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4113 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4115 struct dwrite_fontfamily_data
*data
;
4117 data
= heap_alloc_zero(sizeof(*data
));
4119 return E_OUTOFMEMORY
;
4122 data
->familyname
= familyname
;
4123 IDWriteLocalizedStrings_AddRef(familyname
);
4130 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4132 size_t i
, j
, heaviest
;
4134 for (i
= 0; i
< family
->count
; ++i
)
4136 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4139 if (family
->fonts
[i
]->bold_sim_tested
)
4142 family
->fonts
[i
]->bold_sim_tested
= 1;
4143 for (j
= i
; j
< family
->count
; ++j
)
4145 if (family
->fonts
[j
]->bold_sim_tested
)
4148 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4149 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4150 if (family
->fonts
[j
]->weight
> weight
) {
4151 weight
= family
->fonts
[j
]->weight
;
4154 family
->fonts
[j
]->bold_sim_tested
= 1;
4158 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550)
4160 static const struct name_pattern weightsim_patterns
[] =
4162 { L
"extra", L
"light" },
4163 { L
"ext", L
"light" },
4164 { L
"ultra", L
"light" },
4165 { L
"semi", L
"light" },
4166 { L
"semi", L
"bold" },
4167 { L
"demi", L
"bold" },
4176 WCHAR facenameW
[255], initialW
[255];
4177 struct dwrite_font_data
*boldface
;
4180 /* add Bold simulation based on heaviest face data */
4182 /* Simulated face name should only contain Bold as weight term,
4183 so remove existing regular and weight terms. */
4184 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4185 facename_remove_regular_term(initialW
, -1);
4187 /* remove current weight pattern */
4188 fontname_tokenize(&tokens
, initialW
);
4189 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4190 fontname_tokens_to_str(&tokens
, facenameW
);
4192 /* Bold suffix for new name */
4193 if (*facenameW
) wcscat(facenameW
, L
" ");
4194 wcscat(facenameW
, L
"Bold");
4196 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4197 boldface
->bold_sim_tested
= 1;
4198 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4199 fontfamily_add_font(family
, boldface
);
4205 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4209 for (i
= 0; i
< family
->count
; ++i
)
4211 UINT32 regular
= ~0u, oblique
= ~0u;
4212 struct dwrite_font_data
*obliqueface
;
4213 WCHAR facenameW
[255];
4215 if (family
->fonts
[i
]->oblique_sim_tested
)
4218 family
->fonts
[i
]->oblique_sim_tested
= 1;
4219 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4221 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4224 /* find regular style with same weight/stretch values */
4225 for (j
= i
; j
< family
->count
; ++j
)
4227 if (family
->fonts
[j
]->oblique_sim_tested
)
4230 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4231 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4233 family
->fonts
[j
]->oblique_sim_tested
= 1;
4234 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4237 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4241 if (regular
!= ~0u && oblique
!= ~0u)
4245 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4249 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4253 /* add oblique simulation based on this regular face */
4255 /* remove regular term if any, append 'Oblique' */
4256 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4257 facename_remove_regular_term(facenameW
, -1);
4259 if (*facenameW
) wcscat(facenameW
, L
" ");
4260 wcscat(facenameW
, L
"Oblique");
4262 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4263 obliqueface
->oblique_sim_tested
= 1;
4264 obliqueface
->lf
.lfItalic
= 1;
4265 fontfamily_add_font(family
, obliqueface
);
4270 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4271 const WCHAR
*replacement_name
)
4273 UINT32 i
= collection_find_family(collection
, replacement_name
);
4274 struct dwrite_fontfamily_data
*target
;
4275 IDWriteLocalizedStrings
*strings
;
4278 /* replacement does not exist */
4282 hr
= create_localizedstrings(&strings
);
4286 /* add a new family with target name, reuse font data from replacement */
4287 add_localizedstring(strings
, L
"en-us", target_name
);
4288 hr
= init_fontfamily_data(strings
, &target
);
4290 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4293 for (i
= 0; i
< replacement
->count
; ++i
)
4295 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4296 addref_font_data(replacement
->fonts
[i
]);
4299 fontcollection_add_family(collection
, target
);
4300 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4301 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4303 IDWriteLocalizedStrings_Release(strings
);
4307 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4308 system font collections. */
4309 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4311 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4316 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4319 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4324 max_namelen
++; /* returned value doesn't include room for '\0' */
4325 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4326 data
= heap_alloc(max_datalen
);
4328 datalen
= max_datalen
;
4329 namelen
= max_namelen
;
4330 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4331 if (collection_find_family(collection
, name
) == ~0u) {
4332 if (type
== REG_MULTI_SZ
) {
4333 WCHAR
*replacement
= data
;
4334 while (*replacement
) {
4335 if (fontcollection_add_replacement(collection
, name
, replacement
))
4337 replacement
+= wcslen(replacement
) + 1;
4340 else if (type
== REG_SZ
)
4341 fontcollection_add_replacement(collection
, name
, data
);
4344 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4346 datalen
= max_datalen
;
4347 namelen
= max_namelen
;
4355 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4356 IDWriteFontCollection3
**ret
)
4358 struct fontfile_enum
{
4360 IDWriteFontFile
*file
;
4362 struct fontfile_enum
*fileenum
, *fileenum2
;
4363 struct dwrite_fontcollection
*collection
;
4364 struct list scannedfiles
;
4365 BOOL current
= FALSE
;
4371 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4372 if (!collection
) return E_OUTOFMEMORY
;
4374 hr
= init_font_collection(collection
, is_system
);
4376 heap_free(collection
);
4380 *ret
= &collection
->IDWriteFontCollection3_iface
;
4382 TRACE("building font collection:\n");
4384 list_init(&scannedfiles
);
4385 while (hr
== S_OK
) {
4386 DWRITE_FONT_FACE_TYPE face_type
;
4387 DWRITE_FONT_FILE_TYPE file_type
;
4388 BOOL supported
, same
= FALSE
;
4389 IDWriteFontFileStream
*stream
;
4390 IDWriteFontFile
*file
;
4394 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4395 if (FAILED(hr
) || !current
)
4398 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4402 /* check if we've scanned this file already */
4403 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4404 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4409 IDWriteFontFile_Release(file
);
4413 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4414 IDWriteFontFile_Release(file
);
4418 /* Unsupported formats are skipped. */
4419 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4420 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4421 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4422 IDWriteFontFileStream_Release(stream
);
4423 IDWriteFontFile_Release(file
);
4428 /* add to scanned list */
4429 fileenum
= heap_alloc(sizeof(*fileenum
));
4430 fileenum
->file
= file
;
4431 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4433 for (i
= 0; i
< face_count
; ++i
)
4435 struct dwrite_font_data
*font_data
;
4436 struct fontface_desc desc
;
4440 desc
.factory
= factory
;
4441 desc
.face_type
= face_type
;
4443 desc
.stream
= stream
;
4445 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4446 desc
.font_data
= NULL
;
4448 /* Allocate an initialize new font data structure. */
4449 hr
= init_font_data(&desc
, &font_data
);
4452 /* move to next one */
4457 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4459 /* ignore dot named faces */
4460 if (familyW
[0] == '.')
4462 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4463 release_font_data(font_data
);
4467 index
= collection_find_family(collection
, familyW
);
4469 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4471 struct dwrite_fontfamily_data
*family_data
;
4473 /* create and init new family */
4474 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4476 /* add font to family, family - to collection */
4477 hr
= fontfamily_add_font(family_data
, font_data
);
4479 hr
= fontcollection_add_family(collection
, family_data
);
4482 release_fontfamily_data(family_data
);
4490 IDWriteFontFileStream_Release(stream
);
4493 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4494 IDWriteFontFile_Release(fileenum
->file
);
4495 list_remove(&fileenum
->entry
);
4496 heap_free(fileenum
);
4499 for (i
= 0; i
< collection
->count
; ++i
)
4501 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4502 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4506 fontcollection_add_replacements(collection
);
4508 collection
->factory
= factory
;
4509 IDWriteFactory7_AddRef(factory
);
4514 struct system_fontfile_enumerator
4516 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4519 IDWriteFactory7
*factory
;
4524 DWORD filename_size
;
4527 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4529 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4532 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4534 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4535 IDWriteFontFileEnumerator_AddRef(iface
);
4540 WARN("%s not implemented.\n", debugstr_guid(riid
));
4544 return E_NOINTERFACE
;
4547 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4549 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4550 return InterlockedIncrement(&enumerator
->refcount
);
4553 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4555 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4556 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
4560 IDWriteFactory7_Release(enumerator
->factory
);
4561 RegCloseKey(enumerator
->hkey
);
4562 heap_free(enumerator
->filename
);
4563 heap_free(enumerator
);
4569 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4573 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4574 if (!wcschr(filename
, '\\'))
4576 WCHAR fullpathW
[MAX_PATH
];
4578 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4579 wcscat(fullpathW
, L
"\\fonts\\");
4580 wcscat(fullpathW
, filename
);
4582 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4585 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4590 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4592 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4596 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4599 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4602 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4604 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4605 WCHAR name_buf
[256], *name
= name_buf
;
4606 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4611 enumerator
->index
++;
4613 /* iterate until we find next string value */
4616 name_count
= max_name_count
;
4617 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4619 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4620 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4621 if (r
== ERROR_MORE_DATA
) {
4622 if (name_count
>= max_name_count
) {
4623 if (name
!= name_buf
) heap_free(name
);
4624 max_name_count
*= 2;
4625 name
= heap_alloc(max_name_count
* sizeof(*name
));
4626 if (!name
) return E_OUTOFMEMORY
;
4628 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4629 heap_free(enumerator
->filename
);
4630 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4631 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4632 if (!enumerator
->filename
) {
4638 } while (r
== ERROR_MORE_DATA
);
4640 if (r
!= ERROR_SUCCESS
) {
4641 enumerator
->filename
[0] = 0;
4644 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4645 if (type
== REG_SZ
&& *name
!= '@') {
4649 enumerator
->index
++;
4651 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4654 if (name
!= name_buf
) heap_free(name
);
4658 static const IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4660 systemfontfileenumerator_QueryInterface
,
4661 systemfontfileenumerator_AddRef
,
4662 systemfontfileenumerator_Release
,
4663 systemfontfileenumerator_MoveNext
,
4664 systemfontfileenumerator_GetCurrentFontFile
4667 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4669 struct system_fontfile_enumerator
*enumerator
;
4673 enumerator
= heap_alloc(sizeof(*enumerator
));
4675 return E_OUTOFMEMORY
;
4677 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4678 enumerator
->refcount
= 1;
4679 enumerator
->factory
= factory
;
4680 enumerator
->index
= -1;
4681 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4682 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4683 if (!enumerator
->filename
) {
4684 heap_free(enumerator
);
4685 return E_OUTOFMEMORY
;
4688 IDWriteFactory7_AddRef(factory
);
4690 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 0,
4691 GENERIC_READ
, &enumerator
->hkey
))
4693 ERR("failed to open fonts list key\n");
4694 IDWriteFactory7_Release(factory
);
4695 heap_free(enumerator
->filename
);
4696 heap_free(enumerator
);
4700 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4705 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4707 IDWriteFontFileEnumerator
*enumerator
;
4712 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4716 TRACE("building system font collection for factory %p\n", factory
);
4717 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4718 IDWriteFontFileEnumerator_Release(enumerator
);
4722 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4723 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4725 struct dwrite_fontfamily_data
*family_data
;
4726 IDWriteLocalizedStrings
*names
;
4727 DWRITE_FONT_FACE_TYPE face_type
;
4728 DWRITE_FONT_FILE_TYPE file_type
;
4729 IDWriteFontFileStream
*stream
;
4730 IDWriteFontFile
*file
;
4731 UINT32 face_count
, i
;
4735 /* create font file from this path */
4736 hr
= create_local_file_reference(factory
, pathW
, &file
);
4740 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4741 IDWriteFontFile_Release(file
);
4745 /* Unsupported formats are skipped. */
4746 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4747 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4748 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4749 IDWriteFontFileStream_Release(stream
);
4750 IDWriteFontFile_Release(file
);
4754 /* create and init new family */
4756 /* Family names are added for non-specific locale, represented with empty string.
4757 Default family appears with empty family name. */
4758 create_localizedstrings(&names
);
4759 if (!wcsicmp(keynameW
, L
"SystemDefaultEUDCFont"))
4760 add_localizedstring(names
, L
"", L
"");
4762 add_localizedstring(names
, L
"", keynameW
);
4764 hr
= init_fontfamily_data(names
, &family_data
);
4765 IDWriteLocalizedStrings_Release(names
);
4767 IDWriteFontFile_Release(file
);
4771 /* fill with faces */
4772 for (i
= 0; i
< face_count
; i
++) {
4773 struct dwrite_font_data
*font_data
;
4774 struct fontface_desc desc
;
4776 /* Allocate new font data structure. */
4777 desc
.factory
= factory
;
4778 desc
.face_type
= face_type
;
4781 desc
.stream
= stream
;
4782 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4783 desc
.font_data
= NULL
;
4785 hr
= init_font_data(&desc
, &font_data
);
4789 /* add font to family */
4790 hr
= fontfamily_add_font(family_data
, font_data
);
4792 release_font_data(font_data
);
4795 /* add family to collection */
4796 hr
= fontcollection_add_family(collection
, family_data
);
4798 release_fontfamily_data(family_data
);
4799 IDWriteFontFileStream_Release(stream
);
4800 IDWriteFontFile_Release(file
);
4805 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4807 struct dwrite_fontcollection
*collection
;
4808 WCHAR eudckeypathW
[16];
4816 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4820 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4821 if (!collection
) return E_OUTOFMEMORY
;
4823 hr
= init_font_collection(collection
, FALSE
);
4825 heap_free(collection
);
4829 *ret
= &collection
->IDWriteFontCollection3_iface
;
4830 collection
->factory
= factory
;
4831 IDWriteFactory7_AddRef(factory
);
4833 /* return empty collection if EUDC fonts are not configured */
4834 swprintf(eudckeypathW
, ARRAY_SIZE(eudckeypathW
), L
"EUDC\\%u", GetACP());
4835 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4838 retval
= ERROR_SUCCESS
;
4840 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4841 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4842 DWORD type
, path_len
, name_len
;
4844 path_len
= ARRAY_SIZE(pathW
);
4845 name_len
= ARRAY_SIZE(keynameW
);
4846 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4847 if (retval
|| type
!= REG_SZ
)
4850 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4852 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4854 RegCloseKey(eudckey
);
4856 /* try to add global default if not defined for specific codepage */
4858 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, L
"",
4860 if (FAILED(hr
) || !exists
)
4862 hr
= eudc_collection_add_family(factory
, collection
, L
"", L
"EUDC.TTE");
4864 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4867 /* EUDC collection offers simulated faces too */
4868 for (i
= 0; i
< collection
->count
; ++i
)
4870 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4871 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4877 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4879 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
4881 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4884 IDWriteFontFile_AddRef(iface
);
4888 WARN("%s not implemented.\n", debugstr_guid(riid
));
4891 return E_NOINTERFACE
;
4894 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4896 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4897 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
4899 TRACE("%p, refcount %d.\n", iface
, refcount
);
4904 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4906 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4907 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
4909 TRACE("%p, refcount %d.\n", iface
, refcount
);
4913 IDWriteFontFileLoader_Release(file
->loader
);
4915 IDWriteFontFileStream_Release(file
->stream
);
4916 heap_free(file
->reference_key
);
4923 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
4925 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4927 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
4929 *key
= file
->reference_key
;
4930 *key_size
= file
->key_size
;
4935 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
4937 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4939 TRACE("%p, %p.\n", iface
, loader
);
4941 *loader
= file
->loader
;
4942 IDWriteFontFileLoader_AddRef(*loader
);
4947 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4948 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4950 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4951 IDWriteFontFileStream
*stream
;
4954 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
4956 *is_supported
= FALSE
;
4957 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4959 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4962 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
4966 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4968 /* TODO: Further Analysis */
4969 IDWriteFontFileStream_Release(stream
);
4973 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
4975 dwritefontfile_QueryInterface
,
4976 dwritefontfile_AddRef
,
4977 dwritefontfile_Release
,
4978 dwritefontfile_GetReferenceKey
,
4979 dwritefontfile_GetLoader
,
4980 dwritefontfile_Analyze
,
4983 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4984 IDWriteFontFile
**ret
)
4986 struct dwrite_fontfile
*file
;
4991 file
= heap_alloc(sizeof(*file
));
4992 key
= heap_alloc(key_size
);
4993 if (!file
|| !key
) {
4996 return E_OUTOFMEMORY
;
4999 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
5001 IDWriteFontFileLoader_AddRef(loader
);
5002 file
->loader
= loader
;
5003 file
->stream
= NULL
;
5004 file
->reference_key
= key
;
5005 memcpy(file
->reference_key
, reference_key
, key_size
);
5006 file
->key_size
= key_size
;
5008 *ret
= &file
->IDWriteFontFile_iface
;
5013 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
5015 struct file_stream_desc stream_desc
;
5016 struct dwrite_font_data
*font_data
;
5017 struct dwrite_fontface
*fontface
;
5023 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
5025 return E_OUTOFMEMORY
;
5027 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
5028 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
5029 fontface
->refcount
= 1;
5030 fontface
->type
= desc
->face_type
;
5031 fontface
->vdmx
.exists
= TRUE
;
5032 fontface
->gasp
.exists
= TRUE
;
5033 fontface
->cpal
.exists
= TRUE
;
5034 fontface
->colr
.exists
= TRUE
;
5035 fontface
->kern
.exists
= TRUE
;
5036 fontface
->index
= desc
->index
;
5037 fontface
->simulations
= desc
->simulations
;
5038 fontface
->factory
= desc
->factory
;
5039 IDWriteFactory7_AddRef(fontface
->factory
);
5040 fontface
->file
= desc
->file
;
5041 IDWriteFontFile_AddRef(fontface
->file
);
5042 fontface
->stream
= desc
->stream
;
5043 IDWriteFontFileStream_AddRef(fontface
->stream
);
5045 stream_desc
.stream
= fontface
->stream
;
5046 stream_desc
.face_type
= desc
->face_type
;
5047 stream_desc
.face_index
= desc
->index
;
5048 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
5049 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
5050 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
5051 /* TODO: test what happens if caret is already slanted */
5052 if (fontface
->caret
.slopeRise
== 1) {
5053 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
5054 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
5057 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
5059 /* Font properties are reused from font object when 'normal' face creation path is used:
5060 collection -> family -> matching font -> fontface.
5062 If face is created directly from factory we have to go through properties resolution.
5064 if (desc
->font_data
)
5066 font_data
= addref_font_data(desc
->font_data
);
5070 hr
= init_font_data(desc
, &font_data
);
5073 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5078 fontface
->weight
= font_data
->weight
;
5079 fontface
->style
= font_data
->style
;
5080 fontface
->stretch
= font_data
->stretch
;
5081 fontface
->panose
= font_data
->panose
;
5082 fontface
->fontsig
= font_data
->fontsig
;
5083 fontface
->lf
= font_data
->lf
;
5084 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5085 fontface
->names
= font_data
->names
;
5086 if (fontface
->names
)
5087 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5088 fontface
->family_names
= font_data
->family_names
;
5089 if (fontface
->family_names
)
5090 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5091 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5092 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5094 if (fontface
->info_strings
[i
])
5095 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5097 fontface
->cmap
.stream
= fontface
->stream
;
5098 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5099 release_font_data(font_data
);
5101 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5103 *ret
= &fontface
->IDWriteFontFace5_iface
;
5108 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5115 struct local_cached_stream
5118 IDWriteFontFileStream
*stream
;
5119 struct local_refkey
*key
;
5123 struct dwrite_localfontfilestream
5125 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5128 struct local_cached_stream
*entry
;
5129 const void *file_ptr
;
5133 struct dwrite_localfontfileloader
5135 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5138 struct list streams
;
5139 CRITICAL_SECTION cs
;
5142 static struct dwrite_localfontfileloader local_fontfile_loader
;
5144 struct dwrite_inmemory_stream_data
5152 struct dwrite_inmemory_filestream
5154 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5157 struct dwrite_inmemory_stream_data
*data
;
5160 struct dwrite_inmemory_fileloader
5162 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5165 struct dwrite_inmemory_stream_data
**streams
;
5170 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5172 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5175 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5177 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5180 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5182 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5185 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5187 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5190 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5192 if (InterlockedDecrement(&stream
->refcount
) == 0)
5195 IUnknown_Release(stream
->owner
);
5197 heap_free(stream
->data
);
5202 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5204 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5206 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5208 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5209 IsEqualIID(riid
, &IID_IUnknown
))
5212 if (InterlockedIncrement(&stream
->refcount
) == 1)
5214 InterlockedDecrement(&stream
->refcount
);
5221 WARN("%s not implemented.\n", debugstr_guid(riid
));
5224 return E_NOINTERFACE
;
5227 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5229 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5230 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5232 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5237 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5239 list_remove(&stream
->entry
);
5240 heap_free(stream
->key
);
5244 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5246 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5247 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5249 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5253 UnmapViewOfFile(stream
->file_ptr
);
5255 EnterCriticalSection(&local_fontfile_loader
.cs
);
5256 release_cached_stream(stream
->entry
);
5257 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5265 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5266 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5268 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5270 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5271 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5273 *fragment_context
= NULL
;
5275 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5277 *fragment_start
= NULL
;
5281 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5285 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5287 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5290 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5292 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5294 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5296 *size
= stream
->size
;
5300 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5302 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5305 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5307 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5308 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5309 *last_writetime
= li
.QuadPart
;
5314 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5316 localfontfilestream_QueryInterface
,
5317 localfontfilestream_AddRef
,
5318 localfontfilestream_Release
,
5319 localfontfilestream_ReadFileFragment
,
5320 localfontfilestream_ReleaseFileFragment
,
5321 localfontfilestream_GetFileSize
,
5322 localfontfilestream_GetLastWriteTime
5325 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5326 IDWriteFontFileStream
**ret
)
5328 struct dwrite_localfontfilestream
*object
;
5332 if (!(object
= heap_alloc(sizeof(*object
))))
5333 return E_OUTOFMEMORY
;
5335 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5336 object
->refcount
= 1;
5338 object
->file_ptr
= file_ptr
;
5339 object
->size
= size
;
5340 object
->entry
= entry
;
5342 *ret
= &object
->IDWriteFontFileStream_iface
;
5347 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5349 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5351 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5352 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5353 IsEqualIID(riid
, &IID_IUnknown
))
5356 IDWriteLocalFontFileLoader_AddRef(iface
);
5360 WARN("%s not implemented.\n", debugstr_guid(riid
));
5363 return E_NOINTERFACE
;
5366 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5368 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5369 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5371 TRACE("%p, refcount %d.\n", iface
, refcount
);
5376 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5378 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5379 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5381 TRACE("%p, refcount %d.\n", iface
, refcount
);
5386 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5388 const struct local_refkey
*refkey
= key
;
5389 struct local_cached_stream
*stream
;
5390 IDWriteFontFileStream
*filestream
;
5391 HANDLE file
, mapping
;
5398 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5399 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5400 if (file
== INVALID_HANDLE_VALUE
) {
5401 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5405 GetFileSizeEx(file
, &size
);
5406 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5411 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5412 CloseHandle(mapping
);
5414 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5418 stream
= heap_alloc(sizeof(*stream
));
5420 UnmapViewOfFile(file_ptr
);
5421 return E_OUTOFMEMORY
;
5424 stream
->key
= heap_alloc(key_size
);
5426 UnmapViewOfFile(file_ptr
);
5428 return E_OUTOFMEMORY
;
5431 stream
->key_size
= key_size
;
5432 memcpy(stream
->key
, key
, key_size
);
5434 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5436 UnmapViewOfFile(file_ptr
);
5437 heap_free(stream
->key
);
5442 stream
->stream
= filestream
;
5449 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5450 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5452 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5453 struct local_cached_stream
*stream
;
5456 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5458 EnterCriticalSection(&loader
->cs
);
5462 /* search cache first */
5463 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5465 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5466 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5471 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5473 list_add_head(&loader
->streams
, &stream
->entry
);
5474 *ret
= stream
->stream
;
5477 LeaveCriticalSection(&loader
->cs
);
5482 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5483 UINT32 key_size
, UINT32
*length
)
5485 const struct local_refkey
*refkey
= key
;
5487 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5489 *length
= wcslen(refkey
->name
);
5493 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5494 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5496 const struct local_refkey
*refkey
= key
;
5498 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5500 if (length
< wcslen(refkey
->name
))
5501 return E_INVALIDARG
;
5503 wcscpy(path
, refkey
->name
);
5507 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5508 UINT32 key_size
, FILETIME
*writetime
)
5510 const struct local_refkey
*refkey
= key
;
5512 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5514 *writetime
= refkey
->writetime
;
5518 static const IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5520 localfontfileloader_QueryInterface
,
5521 localfontfileloader_AddRef
,
5522 localfontfileloader_Release
,
5523 localfontfileloader_CreateStreamFromKey
,
5524 localfontfileloader_GetFilePathLengthFromKey
,
5525 localfontfileloader_GetFilePathFromKey
,
5526 localfontfileloader_GetLastWriteTimeFromKey
5529 void init_local_fontfile_loader(void)
5531 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5532 local_fontfile_loader
.refcount
= 1;
5533 list_init(&local_fontfile_loader
.streams
);
5534 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5535 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5538 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5540 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5543 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5545 struct local_refkey
*refkey
;
5548 return E_INVALIDARG
;
5550 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (wcslen(path
)+1)*sizeof(WCHAR
);
5553 refkey
= heap_alloc(*size
);
5555 return E_OUTOFMEMORY
;
5558 refkey
->writetime
= *writetime
;
5560 WIN32_FILE_ATTRIBUTE_DATA info
;
5562 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5563 refkey
->writetime
= info
.ftLastWriteTime
;
5565 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5567 wcscpy(refkey
->name
, path
);
5574 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5576 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5578 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5579 IsEqualIID(riid
, &IID_IUnknown
))
5582 IDWriteGlyphRunAnalysis_AddRef(iface
);
5586 WARN("%s not implemented.\n", debugstr_guid(riid
));
5589 return E_NOINTERFACE
;
5592 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5594 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5595 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
5597 TRACE("%p, refcount %d.\n", iface
, refcount
);
5602 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5604 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5605 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
5607 TRACE("%p, refcount %d.\n", iface
, refcount
);
5611 if (analysis
->run
.fontFace
)
5612 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5613 heap_free(analysis
->glyphs
);
5614 heap_free(analysis
->origins
);
5615 heap_free(analysis
->bitmap
);
5616 heap_free(analysis
);
5622 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5626 case DWRITE_RENDERING_MODE1_NATURAL
:
5627 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5628 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5635 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5637 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5640 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5642 struct dwrite_glyphbitmap glyph_bitmap
;
5643 IDWriteFontFace4
*fontface
;
5647 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5648 *bounds
= analysis
->bounds
;
5652 if (analysis
->run
.isSideways
)
5653 FIXME("sideways runs are not supported.\n");
5655 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5657 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5659 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5660 glyph_bitmap
.key
= fontface
;
5661 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5662 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5663 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5664 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5665 glyph_bitmap
.m
= &analysis
->m
;
5667 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5668 RECT
*bbox
= &glyph_bitmap
.bbox
;
5671 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5672 font_funcs
->get_glyph_bbox(&glyph_bitmap
);
5674 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5675 (bbox
->bottom
- bbox
->top
);
5676 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5677 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5679 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5680 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5683 IDWriteFontFace4_Release(fontface
);
5685 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5686 *bounds
= analysis
->bounds
;
5689 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
5690 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5692 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5694 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
5696 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5697 SetRectEmpty(bounds
);
5698 return E_INVALIDARG
;
5701 if (type
!= analysis
->texture_type
)
5703 SetRectEmpty(bounds
);
5707 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
5711 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5713 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5714 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5715 (runbounds
->left
- bounds
->left
) * 3;
5717 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5718 runbounds
->left
- bounds
->left
;
5721 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5723 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5724 struct dwrite_glyphbitmap glyph_bitmap
;
5725 IDWriteFontFace4
*fontface
;
5726 D2D_POINT_2F origin
;
5731 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5733 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5737 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5738 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5740 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5741 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5742 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5743 IDWriteFontFace4_Release(fontface
);
5744 return E_OUTOFMEMORY
;
5747 origin
.x
= origin
.y
= 0.0f
;
5749 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5750 glyph_bitmap
.key
= fontface
;
5751 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5752 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5753 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5754 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5755 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5756 glyph_bitmap
.m
= &analysis
->m
;
5757 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5758 IDWriteFontFace4_Release(fontface
);
5759 return E_OUTOFMEMORY
;
5762 bbox
= &glyph_bitmap
.bbox
;
5764 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5765 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5766 int x
, y
, width
, height
;
5769 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5770 font_funcs
->get_glyph_bbox(&glyph_bitmap
);
5772 if (IsRectEmpty(bbox
))
5775 width
= bbox
->right
- bbox
->left
;
5776 height
= bbox
->bottom
- bbox
->top
;
5778 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5779 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5780 is_1bpp
= font_funcs
->get_glyph_bitmap(&glyph_bitmap
);
5782 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5784 /* blit to analysis bitmap */
5785 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5788 /* convert 1bpp to 8bpp/24bpp */
5789 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5790 for (y
= 0; y
< height
; y
++) {
5791 for (x
= 0; x
< width
; x
++)
5792 if (src
[x
/ 8] & masks
[x
% 8])
5793 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5794 src
+= glyph_bitmap
.pitch
;
5795 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5799 for (y
= 0; y
< height
; y
++) {
5800 for (x
= 0; x
< width
; x
++)
5801 if (src
[x
/ 8] & masks
[x
% 8])
5802 dst
[x
] = DWRITE_ALPHA_MAX
;
5803 src
+= glyph_bitmap
.pitch
;
5804 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5809 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5810 for (y
= 0; y
< height
; y
++) {
5811 for (x
= 0; x
< width
; x
++)
5812 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5813 src
+= glyph_bitmap
.pitch
;
5814 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5818 for (y
= 0; y
< height
; y
++) {
5819 for (x
= 0; x
< width
; x
++)
5821 src
+= glyph_bitmap
.pitch
;
5822 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5827 heap_free(glyph_bitmap
.buf
);
5829 IDWriteFontFace4_Release(fontface
);
5831 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5833 /* we don't need this anymore */
5834 heap_free(analysis
->glyphs
);
5835 heap_free(analysis
->origins
);
5836 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5838 analysis
->glyphs
= NULL
;
5839 analysis
->origins
= NULL
;
5840 analysis
->run
.glyphIndices
= NULL
;
5841 analysis
->run
.fontFace
= NULL
;
5846 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5847 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5849 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5853 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5855 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5856 return E_INVALIDARG
;
5858 /* make sure buffer is large enough for requested texture type */
5859 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5860 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5863 if (size
< required
)
5864 return E_NOT_SUFFICIENT_BUFFER
;
5866 /* validate requested texture type */
5867 if (analysis
->texture_type
!= type
)
5868 return DWRITE_E_UNSUPPORTEDOPERATION
;
5870 memset(bitmap
, 0, size
);
5871 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
5872 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
5874 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5875 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
5876 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5877 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5881 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
5885 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
5889 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
5890 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5892 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5893 memcpy(dst
, src
, draw_width
);
5902 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5903 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5905 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5907 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
5910 return E_INVALIDARG
;
5912 switch (analysis
->rendering_mode
)
5914 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5915 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5918 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5919 *gamma
= (FLOAT
)value
/ 1000.0f
;
5921 *cleartypelevel
= 1.0f
;
5924 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5925 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5927 case DWRITE_RENDERING_MODE1_ALIASED
:
5928 case DWRITE_RENDERING_MODE1_NATURAL
:
5929 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5930 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5931 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5932 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5941 static const IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
5943 glyphrunanalysis_QueryInterface
,
5944 glyphrunanalysis_AddRef
,
5945 glyphrunanalysis_Release
,
5946 glyphrunanalysis_GetAlphaTextureBounds
,
5947 glyphrunanalysis_CreateAlphaTexture
,
5948 glyphrunanalysis_GetAlphaBlendParams
5951 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5954 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5955 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5959 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5960 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5962 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5966 FIXME("Sideways mode is not supported.\n");
5968 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5970 switch (measuring_mode
)
5972 case DWRITE_MEASURING_MODE_NATURAL
:
5973 return (float)advance
* emsize
/ (float)upem
;
5974 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5975 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5976 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5978 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5983 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5985 struct dwrite_glyphrunanalysis
*analysis
;
5990 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5991 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5992 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5993 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5994 return E_INVALIDARG
;
5996 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5997 return E_INVALIDARG
;
5999 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
6000 return E_INVALIDARG
;
6002 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
6003 return E_INVALIDARG
;
6005 analysis
= heap_alloc_zero(sizeof(*analysis
));
6007 return E_OUTOFMEMORY
;
6009 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
6010 analysis
->refcount
= 1;
6011 analysis
->rendering_mode
= desc
->rendering_mode
;
6013 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
6014 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6015 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
6017 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
6019 analysis
->run
= *desc
->run
;
6020 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
6021 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
6022 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
6024 if (!analysis
->glyphs
|| !analysis
->origins
) {
6025 heap_free(analysis
->glyphs
);
6026 heap_free(analysis
->origins
);
6028 analysis
->glyphs
= NULL
;
6029 analysis
->origins
= NULL
;
6031 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
6032 return E_OUTOFMEMORY
;
6035 /* check if transform is usable */
6036 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
6037 analysis
->m
= *desc
->transform
;
6038 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
6041 analysis
->run
.glyphIndices
= analysis
->glyphs
;
6042 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
6044 compute_glyph_origins(desc
->run
, desc
->measuring_mode
, desc
->origin
, desc
->transform
, analysis
->origins
);
6045 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6047 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
6048 transform_point(&analysis
->origins
[i
], &analysis
->m
);
6051 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6055 /* IDWriteColorGlyphRunEnumerator1 */
6056 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6058 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6060 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6061 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6062 IsEqualIID(riid
, &IID_IUnknown
))
6065 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6069 WARN("%s not implemented.\n", debugstr_guid(riid
));
6072 return E_NOINTERFACE
;
6075 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6077 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6078 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6080 TRACE("%p, refcount %u.\n", iface
, refcount
);
6085 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6087 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6088 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6090 TRACE("%p, refcount %u.\n", iface
, refcount
);
6094 heap_free(glyphenum
->advances
);
6095 heap_free(glyphenum
->color_advances
);
6096 heap_free(glyphenum
->offsets
);
6097 heap_free(glyphenum
->color_offsets
);
6098 heap_free(glyphenum
->glyphindices
);
6099 heap_free(glyphenum
->glyphs
);
6100 if (glyphenum
->colr
.context
)
6101 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6102 IDWriteFontFace5_Release(glyphenum
->fontface
);
6103 heap_free(glyphenum
);
6109 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6111 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6112 FLOAT origin
= 0.0f
;
6118 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6122 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6124 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6125 FLOAT advance_adj
= 0.0f
;
6126 BOOL got_palette_index
;
6129 /* start with regular glyphs */
6130 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6131 UINT32 first_glyph
= 0;
6133 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6134 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6135 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6136 first_glyph
= min(first_glyph
, g
);
6139 glyphenum
->glyphindices
[g
] = 1;
6140 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6141 if (glyphenum
->color_offsets
)
6142 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6145 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6146 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6147 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6148 colorrun
->paletteIndex
= 0xffff;
6149 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6150 glyphenum
->has_regular_glyphs
= FALSE
;
6154 colorrun
->glyphRun
.glyphCount
= 0;
6155 got_palette_index
= FALSE
;
6159 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6161 glyphenum
->glyphindices
[g
] = 1;
6163 /* all glyph layers were returned */
6164 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6165 advance_adj
+= glyphenum
->advances
[g
];
6169 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6170 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6171 if (!got_palette_index
) {
6172 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6173 /* use foreground color or request one from the font */
6174 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6175 if (colorrun
->paletteIndex
!= 0xffff)
6177 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6178 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6180 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6181 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6183 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6184 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6185 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6186 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6187 got_palette_index
= TRUE
;
6190 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6191 /* offsets are relative to glyph origin, nothing to fix up */
6192 if (glyphenum
->color_offsets
)
6193 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6194 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6196 glyphenum
->color_advances
[index
-1] += advance_adj
;
6197 colorrun
->glyphRun
.glyphCount
++;
6201 advance_adj
+= glyphenum
->advances
[g
];
6204 /* reset last advance */
6205 if (colorrun
->glyphRun
.glyphCount
)
6206 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6208 return colorrun
->glyphRun
.glyphCount
> 0;
6211 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6213 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6215 TRACE("%p, %p.\n", iface
, has_run
);
6219 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6220 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6222 if (colorglyphenum_build_color_run(glyphenum
))
6225 glyphenum
->current_layer
++;
6228 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6233 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6234 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6236 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6239 return E_NOT_VALID_STATE
;
6242 *run
= &glyphenum
->colorrun
;
6246 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6247 DWRITE_COLOR_GLYPH_RUN
const **run
)
6249 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6251 TRACE("%p, %p.\n", iface
, run
);
6253 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6256 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6257 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6259 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6261 TRACE("%p, %p.\n", iface
, run
);
6263 return colorglyphenum_get_current_run(glyphenum
, run
);
6266 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6268 colorglyphenum_QueryInterface
,
6269 colorglyphenum_AddRef
,
6270 colorglyphenum_Release
,
6271 colorglyphenum_MoveNext
,
6272 colorglyphenum_GetCurrentRun
,
6273 colorglyphenum1_GetCurrentRun
,
6276 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6277 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6278 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6280 struct dwrite_colorglyphenum
*colorglyphenum
;
6281 BOOL colorfont
, has_colored_glyph
;
6282 struct dwrite_fontface
*fontface
;
6287 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6289 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6290 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6292 return DWRITE_E_NOCOLOR
;
6294 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6295 if (!colorglyphenum
)
6296 return E_OUTOFMEMORY
;
6298 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6299 colorglyphenum
->refcount
= 1;
6300 colorglyphenum
->origin_x
= originX
;
6301 colorglyphenum
->origin_y
= originY
;
6302 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6303 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6304 colorglyphenum
->glyphs
= NULL
;
6305 colorglyphenum
->run
= *run
;
6306 colorglyphenum
->run
.glyphIndices
= NULL
;
6307 colorglyphenum
->run
.glyphAdvances
= NULL
;
6308 colorglyphenum
->run
.glyphOffsets
= NULL
;
6309 colorglyphenum
->palette
= palette
;
6310 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6311 colorglyphenum
->colr
.exists
= TRUE
;
6312 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6313 colorglyphenum
->current_layer
= 0;
6314 colorglyphenum
->max_layer_num
= 0;
6316 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6318 has_colored_glyph
= FALSE
;
6319 colorglyphenum
->has_regular_glyphs
= FALSE
;
6320 for (i
= 0; i
< run
->glyphCount
; i
++) {
6321 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6322 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6323 has_colored_glyph
= TRUE
;
6325 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6326 colorglyphenum
->has_regular_glyphs
= TRUE
;
6329 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6330 is supposed to proceed normally, like if font had no color info at all. */
6331 if (!has_colored_glyph
) {
6332 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6333 return DWRITE_E_NOCOLOR
;
6336 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6337 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6338 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6339 if (run
->glyphOffsets
) {
6340 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6341 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6342 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6345 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6346 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6347 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6348 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6349 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6350 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6351 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6352 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6354 if (run
->glyphAdvances
)
6355 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6358 for (i
= 0; i
< run
->glyphCount
; ++i
)
6359 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6360 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6363 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6368 /* IDWriteFontFaceReference */
6369 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6371 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6373 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6374 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6375 IsEqualIID(riid
, &IID_IUnknown
))
6378 IDWriteFontFaceReference1_AddRef(iface
);
6382 WARN("%s not implemented.\n", debugstr_guid(riid
));
6386 return E_NOINTERFACE
;
6389 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6391 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6392 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6394 TRACE("%p, refcount %u.\n", iface
, refcount
);
6399 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6401 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6402 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6404 TRACE("%p, refcount %u.\n", iface
, refcount
);
6408 IDWriteFontFile_Release(reference
->file
);
6409 IDWriteFactory7_Release(reference
->factory
);
6410 heap_free(reference
->axis_values
);
6411 heap_free(reference
);
6417 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6419 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6421 TRACE("%p, %p.\n", iface
, fontface
);
6423 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6426 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6427 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6429 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6430 DWRITE_FONT_FILE_TYPE file_type
;
6431 DWRITE_FONT_FACE_TYPE face_type
;
6432 IDWriteFontFace
*fontface
;
6437 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6439 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6443 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6444 simulations
, &fontface
);
6447 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6448 IDWriteFontFace_Release(fontface
);
6454 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6456 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6457 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6460 TRACE("%p, %p.\n", iface
, ref
);
6462 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6463 reference
->simulations
== other
->simulations
;
6464 if (reference
->axis_values_count
)
6466 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6467 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6473 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6475 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6477 TRACE("%p.\n", iface
);
6479 return reference
->index
;
6482 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6484 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6486 TRACE("%p.\n", iface
);
6488 return reference
->simulations
;
6491 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6493 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6494 IDWriteFontFileLoader
*loader
;
6499 TRACE("%p, %p.\n", iface
, file
);
6501 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6505 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6509 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6510 IDWriteFontFileLoader_Release(loader
);
6515 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6517 FIXME("%p.\n", iface
);
6522 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6524 FIXME("%p.\n", iface
);
6529 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6531 FIXME("%p, %p.\n", iface
, writetime
);
6536 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6538 FIXME("%p.\n", iface
);
6540 return DWRITE_LOCALITY_LOCAL
;
6543 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6545 FIXME("%p.\n", iface
);
6550 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6551 WCHAR
const *chars
, UINT32 count
)
6553 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6558 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6559 UINT16
const *glyphs
, UINT32 count
)
6561 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6566 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6567 UINT64 offset
, UINT64 size
)
6569 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6574 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6576 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6577 IDWriteFontFace3
*fontface3
;
6580 TRACE("%p, %p.\n", iface
, fontface
);
6582 /* FIXME: created instance should likely respect given axis. */
6583 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6586 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6587 IDWriteFontFace3_Release(fontface3
);
6593 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6595 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6597 TRACE("%p.\n", iface
);
6599 return reference
->axis_values_count
;
6602 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6603 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6605 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6607 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6609 if (value_count
< reference
->axis_values_count
)
6610 return E_NOT_SUFFICIENT_BUFFER
;
6612 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6617 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6619 fontfacereference_QueryInterface
,
6620 fontfacereference_AddRef
,
6621 fontfacereference_Release
,
6622 fontfacereference_CreateFontFace
,
6623 fontfacereference_CreateFontFaceWithSimulations
,
6624 fontfacereference_Equals
,
6625 fontfacereference_GetFontFaceIndex
,
6626 fontfacereference_GetSimulations
,
6627 fontfacereference_GetFontFile
,
6628 fontfacereference_GetLocalFileSize
,
6629 fontfacereference_GetFileSize
,
6630 fontfacereference_GetFileTime
,
6631 fontfacereference_GetLocality
,
6632 fontfacereference_EnqueueFontDownloadRequest
,
6633 fontfacereference_EnqueueCharacterDownloadRequest
,
6634 fontfacereference_EnqueueGlyphDownloadRequest
,
6635 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6636 fontfacereference1_CreateFontFace
,
6637 fontfacereference1_GetFontAxisValueCount
,
6638 fontfacereference1_GetFontAxisValues
,
6641 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6642 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6643 IDWriteFontFaceReference1
**ret
)
6645 struct dwrite_fontfacereference
*object
;
6649 if (!is_simulation_valid(simulations
))
6650 return E_INVALIDARG
;
6652 object
= heap_alloc_zero(sizeof(*object
));
6654 return E_OUTOFMEMORY
;
6656 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6657 object
->refcount
= 1;
6659 object
->factory
= factory
;
6660 IDWriteFactory7_AddRef(object
->factory
);
6661 object
->file
= file
;
6662 IDWriteFontFile_AddRef(object
->file
);
6663 object
->index
= index
;
6664 object
->simulations
= simulations
;
6665 if (axis_values_count
)
6667 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6669 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6670 return E_OUTOFMEMORY
;
6672 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6673 object
->axis_values_count
= axis_values_count
;
6676 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6681 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6683 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6685 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6687 IDWriteFontFileStream_AddRef(iface
);
6693 WARN("%s not implemented.\n", debugstr_guid(riid
));
6694 return E_NOINTERFACE
;
6697 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6699 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6700 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
6702 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6707 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6709 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6710 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
6712 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6716 release_inmemory_stream(stream
->data
);
6723 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6724 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6726 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6728 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
6729 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6731 *fragment_context
= NULL
;
6733 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6734 *fragment_start
= NULL
;
6738 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6742 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6744 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
6747 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6749 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6751 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
6753 *size
= stream
->data
->size
;
6758 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6760 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
6762 *last_writetime
= 0;
6767 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6768 inmemoryfilestream_QueryInterface
,
6769 inmemoryfilestream_AddRef
,
6770 inmemoryfilestream_Release
,
6771 inmemoryfilestream_ReadFileFragment
,
6772 inmemoryfilestream_ReleaseFileFragment
,
6773 inmemoryfilestream_GetFileSize
,
6774 inmemoryfilestream_GetLastWriteTime
,
6777 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6778 REFIID riid
, void **obj
)
6780 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6782 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6783 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6784 IsEqualIID(riid
, &IID_IUnknown
))
6787 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6791 WARN("%s not implemented.\n", debugstr_guid(riid
));
6795 return E_NOINTERFACE
;
6798 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6800 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6801 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
6803 TRACE("%p, refcount %u.\n", iface
, refcount
);
6808 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6810 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6811 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
6814 TRACE("%p, refcount %u.\n", iface
, refcount
);
6818 for (i
= 0; i
< loader
->count
; ++i
)
6819 release_inmemory_stream(loader
->streams
[i
]);
6820 heap_free(loader
->streams
);
6827 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6828 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6830 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6831 struct dwrite_inmemory_filestream
*stream
;
6834 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
6838 if (key_size
!= sizeof(DWORD
))
6839 return E_INVALIDARG
;
6841 index
= *(DWORD
*)key
;
6843 if (index
>= loader
->count
)
6844 return E_INVALIDARG
;
6846 if (!(stream
= heap_alloc(sizeof(*stream
))))
6847 return E_OUTOFMEMORY
;
6849 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6850 stream
->refcount
= 1;
6851 stream
->data
= loader
->streams
[index
];
6852 InterlockedIncrement(&stream
->data
->refcount
);
6854 *ret
= &stream
->IDWriteFontFileStream_iface
;
6859 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6860 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6862 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6863 struct dwrite_inmemory_stream_data
*stream
;
6866 TRACE("%p, %p, %p, %u, %p, %p.\n", iface
, factory
, data
, data_size
, owner
, fontfile
);
6870 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6871 return E_OUTOFMEMORY
;
6873 if (!(stream
= heap_alloc(sizeof(*stream
))))
6874 return E_OUTOFMEMORY
;
6876 stream
->refcount
= 1;
6877 stream
->size
= data_size
;
6878 stream
->owner
= owner
;
6879 if (stream
->owner
) {
6880 IUnknown_AddRef(stream
->owner
);
6881 stream
->data
= (void *)data
;
6884 if (!(stream
->data
= heap_alloc(data_size
))) {
6886 return E_OUTOFMEMORY
;
6888 memcpy(stream
->data
, data
, data_size
);
6891 key
= loader
->count
;
6892 loader
->streams
[loader
->count
++] = stream
;
6894 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6895 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6898 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6900 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6902 TRACE("%p.\n", iface
);
6904 return loader
->count
;
6907 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6909 inmemoryfontfileloader_QueryInterface
,
6910 inmemoryfontfileloader_AddRef
,
6911 inmemoryfontfileloader_Release
,
6912 inmemoryfontfileloader_CreateStreamFromKey
,
6913 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6914 inmemoryfontfileloader_GetFileCount
,
6917 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6919 struct dwrite_inmemory_fileloader
*loader
;
6923 loader
= heap_alloc_zero(sizeof(*loader
));
6925 return E_OUTOFMEMORY
;
6927 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6928 loader
->refcount
= 1;
6930 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6935 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6937 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6939 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6940 IsEqualIID(riid
, &IID_IUnknown
))
6943 IDWriteFontResource_AddRef(iface
);
6947 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6949 return E_NOINTERFACE
;
6952 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6954 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6955 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6957 TRACE("%p, refcount %u.\n", iface
, refcount
);
6962 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6964 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6965 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6967 TRACE("%p, refcount %u.\n", iface
, refcount
);
6971 IDWriteFactory7_Release(resource
->factory
);
6972 IDWriteFontFile_Release(resource
->file
);
6973 heap_free(resource
);
6979 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6981 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6983 TRACE("%p, %p.\n", iface
, fontfile
);
6985 *fontfile
= resource
->file
;
6986 IDWriteFontFile_AddRef(*fontfile
);
6991 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6993 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6995 TRACE("%p.\n", iface
);
6997 return resource
->face_index
;
7000 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
7002 FIXME("%p.\n", iface
);
7007 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
7008 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
7010 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
7015 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
7016 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
7018 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
7023 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7026 FIXME("%p, %u.\n", iface
, axis
);
7028 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
7031 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7032 IDWriteLocalizedStrings
**names
)
7034 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7039 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7041 FIXME("%p, %u.\n", iface
, axis
);
7046 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7047 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7049 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7054 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7056 FIXME("%p.\n", iface
);
7061 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7062 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7063 IDWriteFontFace5
**fontface
)
7065 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7066 IDWriteFontFaceReference1
*reference
;
7069 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7071 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7072 simulations
, axis_values
, num_values
, &reference
);
7075 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7076 IDWriteFontFaceReference1_Release(reference
);
7082 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7083 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7084 IDWriteFontFaceReference1
**reference
)
7086 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7088 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7090 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7091 simulations
, axis_values
, num_values
, reference
);
7094 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7096 dwritefontresource_QueryInterface
,
7097 dwritefontresource_AddRef
,
7098 dwritefontresource_Release
,
7099 dwritefontresource_GetFontFile
,
7100 dwritefontresource_GetFontFaceIndex
,
7101 dwritefontresource_GetFontAxisCount
,
7102 dwritefontresource_GetDefaultFontAxisValues
,
7103 dwritefontresource_GetFontAxisRanges
,
7104 dwritefontresource_GetFontAxisAttributes
,
7105 dwritefontresource_GetAxisNames
,
7106 dwritefontresource_GetAxisValueNameCount
,
7107 dwritefontresource_GetAxisValueNames
,
7108 dwritefontresource_HasVariations
,
7109 dwritefontresource_CreateFontFace
,
7110 dwritefontresource_CreateFontFaceReference
,
7113 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7114 IDWriteFontResource
**ret
)
7116 struct dwrite_fontresource
*resource
;
7120 resource
= heap_alloc_zero(sizeof(*resource
));
7122 return E_OUTOFMEMORY
;
7124 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7125 resource
->refcount
= 1;
7126 resource
->face_index
= face_index
;
7127 resource
->file
= file
;
7128 IDWriteFontFile_AddRef(resource
->file
);
7129 resource
->factory
= factory
;
7130 IDWriteFactory7_AddRef(resource
->factory
);
7132 *ret
= &resource
->IDWriteFontResource_iface
;
7137 static HRESULT WINAPI
dwritefontset_QueryInterface(IDWriteFontSet3
*iface
, REFIID riid
, void **obj
)
7139 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7141 if (IsEqualIID(riid
, &IID_IDWriteFontSet3
) ||
7142 IsEqualIID(riid
, &IID_IDWriteFontSet2
) ||
7143 IsEqualIID(riid
, &IID_IDWriteFontSet1
) ||
7144 IsEqualIID(riid
, &IID_IDWriteFontSet
))
7147 IDWriteFontSet3_AddRef(iface
);
7151 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7153 return E_NOINTERFACE
;
7156 static ULONG WINAPI
dwritefontset_AddRef(IDWriteFontSet3
*iface
)
7158 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7159 ULONG refcount
= InterlockedIncrement(&set
->refcount
);
7161 TRACE("%p, refcount %u.\n", iface
, refcount
);
7166 #define MISSING_SET_PROP ((void *)0x1)
7168 static void release_fontset_entry(struct dwrite_fontset_entry
*entry
)
7172 if (InterlockedDecrement(&entry
->refcount
) > 0)
7174 IDWriteFontFile_Release(entry
->file
);
7175 for (i
= 0; i
< ARRAY_SIZE(entry
->props
); ++i
)
7177 if (entry
->props
[i
] && entry
->props
[i
] != MISSING_SET_PROP
)
7178 IDWriteLocalizedStrings_Release(entry
->props
[i
]);
7183 static struct dwrite_fontset_entry
* addref_fontset_entry(struct dwrite_fontset_entry
*entry
)
7185 InterlockedIncrement(&entry
->refcount
);
7189 static IDWriteLocalizedStrings
* fontset_entry_get_property(struct dwrite_fontset_entry
*entry
,
7190 DWRITE_FONT_PROPERTY_ID property
)
7192 struct file_stream_desc stream_desc
= { 0 };
7193 IDWriteLocalizedStrings
*value
;
7195 assert(property
> DWRITE_FONT_PROPERTY_ID_NONE
&& property
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
);
7197 if (entry
->props
[property
] == MISSING_SET_PROP
)
7200 if ((value
= entry
->props
[property
]))
7202 IDWriteLocalizedStrings_AddRef(value
);
7206 get_filestream_from_file(entry
->file
, &stream_desc
.stream
);
7207 stream_desc
.face_type
= entry
->face_type
;
7208 stream_desc
.face_index
= entry
->face_index
;
7210 if (property
== DWRITE_FONT_PROPERTY_ID_FULL_NAME
)
7211 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_FULL_NAME
, &value
);
7212 else if (property
== DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
)
7213 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME
, &value
);
7214 else if (property
== DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
)
7215 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG
, &value
);
7216 else if (property
== DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
)
7217 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
, &value
);
7219 WARN("Unsupported property %u.\n", property
);
7221 if (stream_desc
.stream
)
7222 IDWriteFontFileStream_Release(stream_desc
.stream
);
7226 entry
->props
[property
] = value
;
7227 IDWriteLocalizedStrings_AddRef(value
);
7230 entry
->props
[property
] = MISSING_SET_PROP
;
7235 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7236 struct dwrite_fontset_entry
**entries
, unsigned int count
);
7238 static ULONG WINAPI
dwritefontset_Release(IDWriteFontSet3
*iface
)
7240 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7241 ULONG refcount
= InterlockedDecrement(&set
->refcount
);
7244 TRACE("%p, refcount %u.\n", iface
, refcount
);
7248 IDWriteFactory7_Release(set
->factory
);
7249 for (i
= 0; i
< set
->count
; ++i
)
7250 release_fontset_entry(set
->entries
[i
]);
7251 heap_free(set
->entries
);
7258 static UINT32 WINAPI
dwritefontset_GetFontCount(IDWriteFontSet3
*iface
)
7260 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7262 TRACE("%p.\n", iface
);
7267 static HRESULT WINAPI
dwritefontset_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7268 IDWriteFontFaceReference
**reference
)
7270 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7272 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
7276 if (index
>= set
->count
)
7277 return E_INVALIDARG
;
7279 return IDWriteFactory7_CreateFontFaceReference_(set
->factory
, set
->entries
[index
]->file
,
7280 set
->entries
[index
]->face_index
, set
->entries
[index
]->simulations
, reference
);
7283 static HRESULT WINAPI
dwritefontset_FindFontFaceReference(IDWriteFontSet3
*iface
,
7284 IDWriteFontFaceReference
*reference
, UINT32
*index
, BOOL
*exists
)
7286 FIXME("%p, %p, %p, %p.\n", iface
, reference
, index
, exists
);
7291 static HRESULT WINAPI
dwritefontset_FindFontFace(IDWriteFontSet3
*iface
, IDWriteFontFace
*fontface
,
7292 UINT32
*index
, BOOL
*exists
)
7294 FIXME("%p, %p, %p, %p.\n", iface
, fontface
, index
, exists
);
7299 static HRESULT WINAPI
dwritefontset_GetPropertyValues__(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7300 IDWriteStringList
**values
)
7302 FIXME("%p, %d, %p.\n", iface
, id
, values
);
7307 static HRESULT WINAPI
dwritefontset_GetPropertyValues_(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7308 WCHAR
const *preferred_locales
, IDWriteStringList
**values
)
7310 FIXME("%p, %d, %s, %p.\n", iface
, id
, debugstr_w(preferred_locales
), values
);
7315 static HRESULT WINAPI
dwritefontset_GetPropertyValues(IDWriteFontSet3
*iface
, UINT32 index
, DWRITE_FONT_PROPERTY_ID id
,
7316 BOOL
*exists
, IDWriteLocalizedStrings
**values
)
7318 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7320 TRACE("%p, %u, %d, %p, %p.\n", iface
, index
, id
, exists
, values
);
7322 if (!(id
> DWRITE_FONT_PROPERTY_ID_NONE
&& id
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
) ||
7323 index
>= set
->count
)
7327 return E_INVALIDARG
;
7330 *values
= fontset_entry_get_property(set
->entries
[index
], id
);
7331 *exists
= !!*values
;
7336 static HRESULT WINAPI
dwritefontset_GetPropertyOccurrenceCount(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7339 FIXME("%p, %p, %p.\n", iface
, property
, count
);
7344 static BOOL
fontset_entry_is_matching(struct dwrite_fontset_entry
*entry
, DWRITE_FONT_PROPERTY
const *props
,
7347 IDWriteLocalizedStrings
*value
;
7351 for (i
= 0; i
< count
; ++i
)
7353 switch (props
[i
].propertyId
)
7355 case DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
:
7356 case DWRITE_FONT_PROPERTY_ID_FULL_NAME
:
7357 case DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
:
7358 case DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
:
7359 if (!(value
= fontset_entry_get_property(entry
, props
[i
].propertyId
)))
7362 ret
= localizedstrings_contains(value
, props
[i
].propertyValue
);
7363 IDWriteLocalizedStrings_Release(value
);
7364 if (!ret
) return FALSE
;
7366 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
:
7367 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME
:
7368 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME
:
7369 case DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME
:
7370 case DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG
:
7371 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
7372 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
7373 case DWRITE_FONT_PROPERTY_ID_STYLE
:
7374 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
:
7375 FIXME("Unsupported property %d.\n", props
[i
].propertyId
);
7385 static HRESULT WINAPI
dwritefontset_GetMatchingFonts_(IDWriteFontSet3
*iface
, WCHAR
const *family
, DWRITE_FONT_WEIGHT weight
,
7386 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontSet
**fontset
)
7388 FIXME("%p, %s, %d, %d, %d, %p.\n", iface
, debugstr_w(family
), weight
, stretch
, style
, fontset
);
7393 static HRESULT WINAPI
dwritefontset_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
, UINT32 count
,
7394 IDWriteFontSet
**filtered_set
)
7396 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7397 struct dwrite_fontset_entry
**entries
;
7398 unsigned int i
, matched_count
= 0;
7399 struct dwrite_fontset
*object
;
7401 TRACE("%p, %p, %u, %p.\n", iface
, props
, count
, filtered_set
);
7403 if (!props
&& count
)
7404 return E_INVALIDARG
;
7406 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7407 return E_OUTOFMEMORY
;
7409 if (!(entries
= heap_calloc(set
->count
, sizeof(*entries
))))
7412 return E_OUTOFMEMORY
;
7415 for (i
= 0; i
< set
->count
; ++i
)
7417 if (fontset_entry_is_matching(set
->entries
[i
], props
, count
))
7419 entries
[matched_count
++] = addref_fontset_entry(set
->entries
[i
]);
7429 init_fontset(object
, set
->factory
, entries
, matched_count
);
7431 *filtered_set
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7436 static HRESULT WINAPI
dwritefontset1_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7437 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontSet1
**fontset
)
7439 FIXME("%p, %p, %p, %u, %p.\n", iface
, property
, axis_values
, num_values
, fontset
);
7444 static HRESULT WINAPI
dwritefontset1_GetFirstFontResources(IDWriteFontSet3
*iface
, IDWriteFontSet1
**fontset
)
7446 FIXME("%p, %p.\n", iface
, fontset
);
7451 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts__(IDWriteFontSet3
*iface
, UINT32
const *indices
,
7452 UINT32 num_indices
, IDWriteFontSet1
**fontset
)
7454 FIXME("%p, %p, %u, %p.\n", iface
, indices
, num_indices
, fontset
);
7459 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *axis_ranges
,
7460 UINT32 num_ranges
, BOOL select_any_range
, IDWriteFontSet1
**fontset
)
7462 FIXME("%p, %p, %u, %d, %p.\n", iface
, axis_ranges
, num_ranges
, select_any_range
, fontset
);
7467 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7468 UINT32 num_properties
, BOOL select_any_property
, IDWriteFontSet1
**fontset
)
7470 FIXME("%p, %p, %u, %d, %p.\n", iface
, props
, num_properties
, select_any_property
, fontset
);
7475 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *ranges
,
7476 UINT32 num_ranges
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7478 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, ranges
, num_ranges
, select_any_range
, indices
, num_indices
, actual_num_indices
);
7483 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7484 UINT32 num_properties
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7486 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, props
, num_properties
, select_any_range
, indices
,
7487 num_indices
, actual_num_indices
);
7492 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges_(IDWriteFontSet3
*iface
, UINT32 font_index
,
7493 DWRITE_FONT_AXIS_RANGE
*axis_ranges
, UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7495 FIXME("%p, %u, %p, %u, %p.\n", iface
, font_index
, axis_ranges
, num_ranges
, actual_num_ranges
);
7500 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
*axis_ranges
,
7501 UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7503 FIXME("%p, %p, %u, %p.\n", iface
, axis_ranges
, num_ranges
, actual_num_ranges
);
7508 static HRESULT WINAPI
dwritefontset1_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7509 IDWriteFontFaceReference1
**reference
)
7511 FIXME("%p, %u, %p.\n", iface
, index
, reference
);
7516 static HRESULT WINAPI
dwritefontset1_CreateFontResource(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontResource
**resource
)
7518 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7520 TRACE("%p, %u, %p.\n", iface
, index
, resource
);
7524 if (index
>= set
->count
)
7525 return E_INVALIDARG
;
7527 return IDWriteFactory7_CreateFontResource(set
->factory
, set
->entries
[index
]->file
,
7528 set
->entries
[index
]->face_index
, resource
);
7531 static HRESULT WINAPI
dwritefontset1_CreateFontFace(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontFace5
**fontface
)
7533 FIXME("%p, %u, %p.\n", iface
, index
, fontface
);
7538 static DWRITE_LOCALITY WINAPI
dwritefontset1_GetFontLocality(IDWriteFontSet3
*iface
, UINT32 index
)
7540 FIXME("%p, %u.\n", iface
, index
);
7542 return DWRITE_LOCALITY_LOCAL
;
7545 static HANDLE WINAPI
dwritefontset2_GetExpirationEvent(IDWriteFontSet3
*iface
)
7547 FIXME("%p.\n", iface
);
7552 static DWRITE_FONT_SOURCE_TYPE WINAPI
dwritefontset3_GetFontSourceType(IDWriteFontSet3
*iface
, UINT32 index
)
7554 FIXME("%p, %u.\n", iface
, index
);
7556 return DWRITE_FONT_SOURCE_TYPE_UNKNOWN
;
7559 static UINT32 WINAPI
dwritefontset3_GetFontSourceNameLength(IDWriteFontSet3
*iface
, UINT32 index
)
7561 FIXME("%p, %u.\n", iface
, index
);
7566 static HRESULT WINAPI
dwritefontset3_GetFontSourceName(IDWriteFontSet3
*iface
, UINT32 index
, WCHAR
*buffer
, UINT32 buffer_size
)
7568 FIXME("%p, %u, %p, %u.\n", iface
, index
, buffer
, buffer_size
);
7573 static const IDWriteFontSet3Vtbl fontsetvtbl
=
7575 dwritefontset_QueryInterface
,
7576 dwritefontset_AddRef
,
7577 dwritefontset_Release
,
7578 dwritefontset_GetFontCount
,
7579 dwritefontset_GetFontFaceReference
,
7580 dwritefontset_FindFontFaceReference
,
7581 dwritefontset_FindFontFace
,
7582 dwritefontset_GetPropertyValues__
,
7583 dwritefontset_GetPropertyValues_
,
7584 dwritefontset_GetPropertyValues
,
7585 dwritefontset_GetPropertyOccurrenceCount
,
7586 dwritefontset_GetMatchingFonts_
,
7587 dwritefontset_GetMatchingFonts
,
7588 dwritefontset1_GetMatchingFonts
,
7589 dwritefontset1_GetFirstFontResources
,
7590 dwritefontset1_GetFilteredFonts__
,
7591 dwritefontset1_GetFilteredFonts_
,
7592 dwritefontset1_GetFilteredFonts
,
7593 dwritefontset1_GetFilteredFontIndices_
,
7594 dwritefontset1_GetFilteredFontIndices
,
7595 dwritefontset1_GetFontAxisRanges_
,
7596 dwritefontset1_GetFontAxisRanges
,
7597 dwritefontset1_GetFontFaceReference
,
7598 dwritefontset1_CreateFontResource
,
7599 dwritefontset1_CreateFontFace
,
7600 dwritefontset1_GetFontLocality
,
7601 dwritefontset2_GetExpirationEvent
,
7602 dwritefontset3_GetFontSourceType
,
7603 dwritefontset3_GetFontSourceNameLength
,
7604 dwritefontset3_GetFontSourceName
,
7607 static HRESULT
fontset_create_entry(IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
,
7608 unsigned int face_index
, unsigned int simulations
, struct dwrite_fontset_entry
**ret
)
7610 struct dwrite_fontset_entry
*entry
;
7612 if (!(entry
= heap_alloc_zero(sizeof(*entry
))))
7613 return E_OUTOFMEMORY
;
7615 entry
->refcount
= 1;
7617 IDWriteFontFile_AddRef(entry
->file
);
7618 entry
->face_type
= face_type
;
7619 entry
->face_index
= face_index
;
7620 entry
->simulations
= simulations
;
7627 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7628 struct dwrite_fontset_entry
**entries
, unsigned int count
)
7630 object
->IDWriteFontSet3_iface
.lpVtbl
= &fontsetvtbl
;
7631 object
->refcount
= 1;
7632 object
->factory
= factory
;
7633 IDWriteFactory7_AddRef(object
->factory
);
7634 object
->entries
= entries
;
7635 object
->count
= count
;
7638 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
7639 unsigned int count
, IDWriteFontSet1
**ret
)
7641 struct dwrite_fontset_entry
**entries
= NULL
;
7642 struct dwrite_fontset
*object
;
7645 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7646 return E_OUTOFMEMORY
;
7650 entries
= heap_calloc(count
, sizeof(*entries
));
7652 /* FIXME: set available properties too */
7654 for (i
= 0; i
< count
; ++i
)
7656 fontset_create_entry(fonts
[i
]->file
, fonts
[i
]->face_type
, fonts
[i
]->face_index
,
7657 fonts
[i
]->simulations
, &entries
[i
]);
7660 init_fontset(object
, factory
, entries
, count
);
7662 *ret
= (IDWriteFontSet1
*)&object
->IDWriteFontSet3_iface
;
7667 static HRESULT
fontset_builder_create_fontset(IDWriteFactory7
*factory
, struct dwrite_fontset_entry
**src_entries
,
7668 unsigned int count
, IDWriteFontSet
**ret
)
7670 struct dwrite_fontset_entry
**entries
= NULL
;
7671 struct dwrite_fontset
*object
;
7674 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7675 return E_OUTOFMEMORY
;
7679 entries
= heap_calloc(count
, sizeof(*entries
));
7681 for (i
= 0; i
< count
; ++i
)
7682 entries
[i
] = addref_fontset_entry(src_entries
[i
]);
7684 init_fontset(object
, factory
, entries
, count
);
7686 *ret
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7691 static HRESULT WINAPI
dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2
*iface
,
7692 REFIID riid
, void **obj
)
7694 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7696 if (IsEqualIID(riid
, &IID_IDWriteFontSetBuilder2
) ||
7697 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder1
) ||
7698 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder
) ||
7699 IsEqualIID(riid
, &IID_IUnknown
))
7702 IDWriteFontSetBuilder2_AddRef(iface
);
7706 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7708 return E_NOINTERFACE
;
7711 static ULONG WINAPI
dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2
*iface
)
7713 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7714 ULONG refcount
= InterlockedIncrement(&builder
->refcount
);
7716 TRACE("%p, refcount %u.\n", iface
, refcount
);
7721 static ULONG WINAPI
dwritefontsetbuilder_Release(IDWriteFontSetBuilder2
*iface
)
7723 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7724 ULONG refcount
= InterlockedDecrement(&builder
->refcount
);
7727 TRACE("%p, refcount %u.\n", iface
, refcount
);
7731 IDWriteFactory7_Release(builder
->factory
);
7732 for (i
= 0; i
< builder
->count
; ++i
)
7733 release_fontset_entry(builder
->entries
[i
]);
7734 heap_free(builder
->entries
);
7741 static HRESULT
fontset_builder_add_entry(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
,
7742 DWRITE_FONT_FACE_TYPE face_type
, unsigned int face_index
, unsigned int simulations
)
7744 struct dwrite_fontset_entry
*entry
;
7747 if (!dwrite_array_reserve((void **)&builder
->entries
, &builder
->capacity
, builder
->count
+ 1,
7748 sizeof(*builder
->entries
)))
7750 return E_OUTOFMEMORY
;
7753 if (FAILED(hr
= fontset_create_entry(file
, face_type
, face_index
, simulations
, &entry
)))
7756 builder
->entries
[builder
->count
++] = entry
;
7761 static HRESULT
fontset_builder_add_file(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
)
7763 DWRITE_FONT_FILE_TYPE filetype
;
7764 DWRITE_FONT_FACE_TYPE facetype
;
7765 unsigned int i
, face_count
;
7766 BOOL supported
= FALSE
;
7769 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &filetype
, &facetype
, &face_count
)))
7773 return DWRITE_E_FILEFORMAT
;
7775 for (i
= 0; i
< face_count
; ++i
)
7777 if (FAILED(hr
= fontset_builder_add_entry(builder
, file
, facetype
, i
, DWRITE_FONT_SIMULATIONS_NONE
)))
7784 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2
*iface
,
7785 IDWriteFontFaceReference
*ref
, DWRITE_FONT_PROPERTY
const *props
, UINT32 prop_count
)
7787 FIXME("%p, %p, %p, %u.\n", iface
, ref
, props
, prop_count
);
7792 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2
*iface
,
7793 IDWriteFontFaceReference
*ref
)
7795 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7796 unsigned int face_count
, face_index
, simulations
;
7797 DWRITE_FONT_FILE_TYPE file_type
;
7798 DWRITE_FONT_FACE_TYPE face_type
;
7799 IDWriteFontFile
*file
;
7803 TRACE("%p, %p.\n", iface
, ref
);
7805 if (FAILED(hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
))) return hr
;
7806 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
)))
7811 hr
= DWRITE_E_FILEFORMAT
;
7815 face_index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
7816 simulations
= IDWriteFontFaceReference_GetSimulations(ref
);
7817 hr
= fontset_builder_add_entry(builder
, file
, face_type
, face_index
, simulations
);
7820 IDWriteFontFile_Release(file
);
7825 static HRESULT WINAPI
dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
*fontset
)
7827 FIXME("%p, %p.\n", iface
, fontset
);
7832 static HRESULT WINAPI
dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
**fontset
)
7834 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7836 TRACE("%p, %p.\n", iface
, fontset
);
7838 return fontset_builder_create_fontset(builder
->factory
, builder
->entries
, builder
->count
, fontset
);
7841 static HRESULT WINAPI
dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
)
7843 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7845 TRACE("%p, %p.\n", iface
, file
);
7847 return fontset_builder_add_file(builder
, file
);
7850 static HRESULT WINAPI
dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
,
7851 unsigned int face_index
, DWRITE_FONT_SIMULATIONS simulations
, const DWRITE_FONT_AXIS_VALUE
*axis_values
,
7852 unsigned int num_values
, const DWRITE_FONT_AXIS_RANGE
*axis_ranges
, unsigned int num_ranges
,
7853 const DWRITE_FONT_PROPERTY
*props
, unsigned int num_properties
)
7855 FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface
, file
, face_index
, simulations
, axis_values
, num_values
,
7856 axis_ranges
, num_ranges
, props
, num_properties
);
7861 static HRESULT WINAPI
dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2
*iface
, const WCHAR
*filepath
)
7863 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7864 IDWriteFontFile
*file
;
7867 TRACE("%p, %s.\n", iface
, debugstr_w(filepath
));
7869 if (FAILED(hr
= IDWriteFactory7_CreateFontFileReference(builder
->factory
, filepath
, NULL
, &file
)))
7872 hr
= fontset_builder_add_file(builder
, file
);
7873 IDWriteFontFile_Release(file
);
7877 static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl
=
7879 dwritefontsetbuilder_QueryInterface
,
7880 dwritefontsetbuilder_AddRef
,
7881 dwritefontsetbuilder_Release
,
7882 dwritefontsetbuilder_AddFontFaceReference_
,
7883 dwritefontsetbuilder_AddFontFaceReference
,
7884 dwritefontsetbuilder_AddFontSet
,
7885 dwritefontsetbuilder_CreateFontSet
,
7886 dwritefontsetbuilder1_AddFontFile
,
7887 dwritefontsetbuilder2_AddFont
,
7888 dwritefontsetbuilder2_AddFontFile
,
7891 HRESULT
create_fontset_builder(IDWriteFactory7
*factory
, IDWriteFontSetBuilder2
**ret
)
7893 struct dwrite_fontset_builder
*builder
;
7897 if (!(builder
= heap_alloc_zero(sizeof(*builder
))))
7898 return E_OUTOFMEMORY
;
7900 builder
->IDWriteFontSetBuilder2_iface
.lpVtbl
= &fontsetbuildervtbl
;
7901 builder
->refcount
= 1;
7902 builder
->factory
= factory
;
7903 IDWriteFactory7_AddRef(builder
->factory
);
7905 *ret
= &builder
->IDWriteFontSetBuilder2_iface
;
7910 struct font_data_context
7912 IDWriteFontFileStream
*stream
;
7916 static int CDECL
get_font_data_cb(void *key
, const void **data_ptr
, UINT64
*data_size
,
7917 unsigned int *index
, struct font_data_context
**ret_context
)
7919 IDWriteFontFace
*fontface
= key
;
7920 struct font_data_context
*context
;
7921 IDWriteFontFileStream
*stream
;
7922 IDWriteFontFile
*file
;
7927 *ret_context
= NULL
;
7930 if (FAILED(IDWriteFontFace_GetFiles(fontface
, &count
, &file
))) return 1;
7932 hr
= get_filestream_from_file(file
, &stream
);
7933 IDWriteFontFile_Release(file
);
7934 if (FAILED(hr
)) return 1;
7936 hr
= IDWriteFontFileStream_GetFileSize(stream
, data_size
);
7939 IDWriteFontFileStream_Release(stream
);
7943 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, data_ptr
, 0, *data_size
, &data_context
);
7946 IDWriteFontFileStream_Release(stream
);
7950 if (!(context
= heap_alloc(sizeof(*context
))))
7952 IDWriteFontFileStream_Release(stream
);
7956 context
->stream
= stream
;
7957 context
->context
= data_context
;
7959 *ret_context
= context
;
7960 *index
= IDWriteFontFace_GetIndex(fontface
);
7965 static void CDECL
release_font_data_cb(struct font_data_context
*context
)
7967 if (!context
) return;
7968 IDWriteFontFileStream_ReleaseFileFragment(context
->stream
, context
->context
);
7969 IDWriteFontFileStream_Release(context
->stream
);
7973 struct font_callback_funcs callback_funcs
=
7976 release_font_data_cb
,
7979 void init_font_backend(void)
7981 __wine_init_unix_lib(dwrite_module
, DLL_PROCESS_ATTACH
, &callback_funcs
, &font_funcs
);
7984 void release_font_backend(void)
7986 __wine_init_unix_lib(dwrite_module
, DLL_PROCESS_DETACH
, &callback_funcs
, NULL
);