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 WCHAR extraW
[] = {'e','x','t','r','a',0};
49 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
50 static const WCHAR semiW
[] = {'s','e','m','i',0};
51 static const WCHAR extW
[] = {'e','x','t',0};
52 static const WCHAR thinW
[] = {'t','h','i','n',0};
53 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
54 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
55 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
56 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
57 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
58 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
59 static const WCHAR boldW
[] = {'B','o','l','d',0};
60 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
61 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
62 static const WCHAR demiW
[] = {'d','e','m','i',0};
63 static const WCHAR spaceW
[] = {' ',0};
64 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
66 struct dwrite_font_propvec
{
72 struct dwrite_font_data
76 DWRITE_FONT_STYLE style
;
77 DWRITE_FONT_STRETCH stretch
;
78 DWRITE_FONT_WEIGHT weight
;
80 FONTSIGNATURE fontsig
;
81 UINT32 flags
; /* enum font_flags */
82 struct dwrite_font_propvec propvec
;
83 struct dwrite_cmap cmap
;
84 /* Static axis for weight/width/italic. */
85 DWRITE_FONT_AXIS_VALUE axis
[3];
87 DWRITE_FONT_METRICS1 metrics
;
88 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
89 IDWriteLocalizedStrings
*family_names
;
90 IDWriteLocalizedStrings
*names
;
92 /* data needed to create fontface instance */
93 DWRITE_FONT_FACE_TYPE face_type
;
94 IDWriteFontFile
*file
;
103 /* used to mark font as tested when scanning for simulation candidate */
104 unsigned int bold_sim_tested
: 1;
105 unsigned int oblique_sim_tested
: 1;
108 struct dwrite_fontfamily_data
112 IDWriteLocalizedStrings
*familyname
;
114 struct dwrite_font_data
**fonts
;
118 unsigned int has_normal_face
: 1;
119 unsigned int has_oblique_face
: 1;
120 unsigned int has_italic_face
: 1;
123 struct dwrite_fontcollection
125 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
128 IDWriteFactory7
*factory
;
129 struct dwrite_fontfamily_data
**family_data
;
134 struct dwrite_fontfamily
136 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
137 IDWriteFontList2 IDWriteFontList2_iface
;
140 struct dwrite_fontfamily_data
*data
;
141 struct dwrite_fontcollection
*collection
;
144 struct dwrite_fontlist
146 IDWriteFontList2 IDWriteFontList2_iface
;
149 struct dwrite_font_data
**fonts
;
151 struct dwrite_fontfamily
*family
;
156 IDWriteFont3 IDWriteFont3_iface
;
159 DWRITE_FONT_STYLE style
;
160 struct dwrite_font_data
*data
;
161 struct dwrite_fontfamily
*family
;
164 enum runanalysis_flags
{
165 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
166 RUNANALYSIS_BITMAP_READY
= 1 << 1,
167 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
170 struct dwrite_glyphrunanalysis
{
171 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
174 DWRITE_RENDERING_MODE1 rendering_mode
;
175 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
176 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
179 D2D_POINT_2F
*origins
;
184 UINT32 max_glyph_bitmap_size
;
187 struct dwrite_colorglyphenum
189 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
192 FLOAT origin_x
; /* original run origin */
195 IDWriteFontFace5
*fontface
; /* for convenience */
196 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
197 DWRITE_GLYPH_RUN run
; /* base run */
198 UINT32 palette
; /* palette index to get layer color from */
199 FLOAT
*advances
; /* original or measured advances for base glyphs */
200 FLOAT
*color_advances
; /* returned color run points to this */
201 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
202 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
203 UINT16
*glyphindices
; /* returned color run points to this */
204 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
205 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
206 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
207 UINT16 max_layer_num
; /* max number of layers for this run */
208 struct dwrite_fonttable colr
; /* used to access layers */
211 #define GLYPH_BLOCK_SHIFT 8
212 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
213 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
214 #define GLYPH_MAX 65536
216 struct dwrite_fontfile
{
217 IDWriteFontFile IDWriteFontFile_iface
;
220 IDWriteFontFileLoader
*loader
;
223 IDWriteFontFileStream
*stream
;
226 struct dwrite_fontfacereference
228 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
231 IDWriteFontFile
*file
;
234 DWRITE_FONT_AXIS_VALUE
*axis_values
;
235 UINT32 axis_values_count
;
236 IDWriteFactory7
*factory
;
239 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
241 struct dwrite_fontresource
243 IDWriteFontResource IDWriteFontResource_iface
;
246 IDWriteFontFile
*file
;
248 IDWriteFactory7
*factory
;
251 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
253 struct dwrite_fontface
*fontface
= context
;
256 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
257 size
, data_context
, &exists
)) || !exists
)
261 *data_context
= NULL
;
265 static void dwrite_release_font_table(void *context
, void *data_context
)
267 struct dwrite_fontface
*fontface
= context
;
268 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
271 static UINT16
dwrite_get_font_upem(void *context
)
273 struct dwrite_fontface
*fontface
= context
;
274 return fontface
->metrics
.designUnitsPerEm
;
277 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
279 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
280 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
283 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
285 struct dwrite_fontface
*fontface
= context
;
286 return !!dwritefontface_get_glyph(fontface
, codepoint
);
289 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
291 struct dwrite_fontface
*fontface
= context
;
292 return dwritefontface_get_glyph(fontface
, codepoint
);
295 static const struct shaping_font_ops dwrite_font_ops
=
297 dwrite_grab_font_table
,
298 dwrite_release_font_table
,
299 dwrite_get_font_upem
,
304 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
306 if (fontface
->shaping_cache
)
307 return fontface
->shaping_cache
;
309 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
312 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
314 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
317 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
319 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
322 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
324 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
327 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
329 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
331 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
334 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
336 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
339 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
341 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
344 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
346 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
349 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
351 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
354 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
356 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
359 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
361 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
364 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
366 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
369 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
371 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
374 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
376 static const DWRITE_GLYPH_METRICS nil
;
377 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
379 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
380 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
384 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
386 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
389 /* start new block */
390 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
392 return E_OUTOFMEMORY
;
395 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
399 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
403 if (table
->data
|| !table
->exists
)
406 table
->exists
= FALSE
;
407 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
409 if (FAILED(hr
) || !table
->exists
) {
410 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
417 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
418 struct dwrite_font_propvec
*vec
)
420 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
421 vec
->style
= style
* 7.0f
;
422 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
425 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
427 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
430 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
432 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
435 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
437 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
438 return &fontface
->vdmx
;
441 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
443 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
444 return &fontface
->gasp
;
447 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
449 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
450 return &fontface
->cpal
;
453 static void addref_font_data(struct dwrite_font_data
*data
)
455 InterlockedIncrement(&data
->ref
);
458 static void release_font_data(struct dwrite_font_data
*data
)
462 if (InterlockedDecrement(&data
->ref
) > 0)
465 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
467 if (data
->info_strings
[i
])
468 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
471 IDWriteLocalizedStrings_Release(data
->names
);
473 if (data
->family_names
)
474 IDWriteLocalizedStrings_Release(data
->family_names
);
476 dwrite_cmap_release(&data
->cmap
);
477 IDWriteFontFile_Release(data
->file
);
478 heap_free(data
->facename
);
482 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
486 if (InterlockedDecrement(&data
->refcount
) > 0)
489 for (i
= 0; i
< data
->count
; ++i
)
490 release_font_data(data
->fonts
[i
]);
491 heap_free(data
->fonts
);
492 IDWriteLocalizedStrings_Release(data
->familyname
);
496 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
498 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
499 fontface
->cached
= NULL
;
502 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
504 UINT32 left_key_size
, right_key_size
;
505 const void *left_key
, *right_key
;
511 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
515 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
519 if (left_key_size
!= right_key_size
)
522 return !memcmp(left_key
, right_key
, left_key_size
);
525 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
527 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
529 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
531 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
532 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
533 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
534 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
535 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
536 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
537 IsEqualIID(riid
, &IID_IUnknown
))
541 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
542 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
548 if (InterlockedIncrement(&fontface
->refcount
) == 1)
550 InterlockedDecrement(&fontface
->refcount
);
557 WARN("%s not implemented.\n", debugstr_guid(riid
));
559 return E_NOINTERFACE
;
562 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
564 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
565 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
567 TRACE("%p, refcount %u.\n", iface
, refcount
);
572 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
574 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
575 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
577 TRACE("%p, refcount %u.\n", iface
, refcount
);
583 if (fontface
->cached
)
585 factory_lock(fontface
->factory
);
586 list_remove(&fontface
->cached
->entry
);
587 factory_unlock(fontface
->factory
);
588 heap_free(fontface
->cached
);
590 release_scriptshaping_cache(fontface
->shaping_cache
);
591 if (fontface
->vdmx
.context
)
592 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
593 if (fontface
->gasp
.context
)
594 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
595 if (fontface
->cpal
.context
)
596 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
597 if (fontface
->colr
.context
)
598 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
599 for (i
= 0; i
< fontface
->file_count
; i
++)
601 if (fontface
->files
[i
])
602 IDWriteFontFile_Release(fontface
->files
[i
]);
604 if (fontface
->stream
)
605 IDWriteFontFileStream_Release(fontface
->stream
);
606 heap_free(fontface
->files
);
608 IDWriteLocalizedStrings_Release(fontface
->names
);
609 if (fontface
->family_names
)
610 IDWriteLocalizedStrings_Release(fontface
->family_names
);
611 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
613 if (fontface
->info_strings
[i
])
614 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
617 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
618 heap_free(fontface
->glyphs
[i
]);
620 freetype_notify_cacheremove(iface
);
622 dwrite_cmap_release(&fontface
->cmap
);
623 IDWriteFactory7_Release(fontface
->factory
);
630 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
632 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
634 TRACE("%p.\n", iface
);
636 return fontface
->type
;
639 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
640 IDWriteFontFile
**fontfiles
)
642 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
645 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
647 if (fontfiles
== NULL
)
649 *number_of_files
= fontface
->file_count
;
653 if (*number_of_files
< fontface
->file_count
)
656 for (i
= 0; i
< fontface
->file_count
; i
++)
658 IDWriteFontFile_AddRef(fontface
->files
[i
]);
659 fontfiles
[i
] = fontface
->files
[i
];
665 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
667 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
669 TRACE("%p.\n", iface
);
671 return fontface
->index
;
674 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
676 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
678 TRACE("%p.\n", iface
);
680 return fontface
->simulations
;
683 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
685 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
687 TRACE("%p.\n", iface
);
689 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
692 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
694 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
696 TRACE("%p, %p.\n", iface
, metrics
);
698 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
701 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
703 TRACE("%p.\n", iface
);
705 return freetype_get_glyphcount(iface
);
708 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
709 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
711 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
715 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
721 FIXME("sideways metrics are not supported.\n");
723 for (i
= 0; i
< glyph_count
; i
++) {
724 DWRITE_GLYPH_METRICS metrics
;
726 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
728 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
729 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
739 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
740 UINT32 count
, UINT16
*glyphs
)
742 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
745 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
752 memset(glyphs
, 0, count
* sizeof(*glyphs
));
756 for (i
= 0; i
< count
; ++i
)
757 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
762 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
763 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
765 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
766 struct file_stream_desc stream_desc
;
768 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
770 stream_desc
.stream
= fontface
->stream
;
771 stream_desc
.face_type
= fontface
->type
;
772 stream_desc
.face_index
= fontface
->index
;
773 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
776 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
778 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
780 TRACE("%p, %p.\n", iface
, table_context
);
782 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
785 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
786 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
787 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
789 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
790 count
, is_sideways
, is_rtl
, sink
);
792 if (!glyphs
|| !sink
)
796 FIXME("sideways mode is not supported.\n");
798 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
801 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
802 float ppem
, unsigned int gasp
)
804 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
808 case DWRITE_MEASURING_MODE_NATURAL
:
810 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
811 mode
= DWRITE_RENDERING_MODE_NATURAL
;
813 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
816 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
817 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
819 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
820 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
829 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
830 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
832 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
836 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
839 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
843 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
844 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
847 ppem
= emSize
* ppdip
;
849 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
850 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
854 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
855 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
859 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
860 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
862 DWRITE_FONT_METRICS1 metrics1
;
863 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
864 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
868 static inline int round_metric(FLOAT metric
)
870 return (int)floorf(metric
+ 0.5f
);
873 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
875 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
878 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
881 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
882 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
883 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
885 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
886 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
887 DWRITE_MEASURING_MODE mode
;
892 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
893 glyph_count
, metrics
, is_sideways
);
895 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
896 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
898 size
= emSize
* ppdip
;
899 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
900 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
902 for (i
= 0; i
< glyph_count
; i
++) {
903 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
904 DWRITE_GLYPH_METRICS design
;
907 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
911 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
913 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
915 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
917 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
918 SCALE_METRIC(leftSideBearing
);
919 SCALE_METRIC(rightSideBearing
);
920 SCALE_METRIC(topSideBearing
);
921 SCALE_METRIC(advanceHeight
);
922 SCALE_METRIC(bottomSideBearing
);
923 SCALE_METRIC(verticalOriginY
);
930 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
932 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
934 TRACE("%p, %p.\n", iface
, metrics
);
936 *metrics
= fontface
->metrics
;
939 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
940 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
942 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
943 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
944 UINT16 ascent
, descent
;
947 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
949 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
950 memset(metrics
, 0, sizeof(*metrics
));
954 em_size
*= pixels_per_dip
;
955 if (m
&& m
->m22
!= 0.0f
)
956 em_size
*= fabs(m
->m22
);
958 scale
= em_size
/ design
->designUnitsPerEm
;
959 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
961 ascent
= round_metric(design
->ascent
* scale
);
962 descent
= round_metric(design
->descent
* scale
);
965 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
966 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
967 metrics
->ascent
= round_metric(ascent
/ scale
);
968 metrics
->descent
= round_metric(descent
/ scale
);
970 SCALE_METRIC(lineGap
);
971 SCALE_METRIC(capHeight
);
972 SCALE_METRIC(xHeight
);
973 SCALE_METRIC(underlinePosition
);
974 SCALE_METRIC(underlineThickness
);
975 SCALE_METRIC(strikethroughPosition
);
976 SCALE_METRIC(strikethroughThickness
);
977 SCALE_METRIC(glyphBoxLeft
);
978 SCALE_METRIC(glyphBoxTop
);
979 SCALE_METRIC(glyphBoxRight
);
980 SCALE_METRIC(glyphBoxBottom
);
981 SCALE_METRIC(subscriptPositionX
);
982 SCALE_METRIC(subscriptPositionY
);
983 SCALE_METRIC(subscriptSizeX
);
984 SCALE_METRIC(subscriptSizeY
);
985 SCALE_METRIC(superscriptPositionX
);
986 SCALE_METRIC(superscriptPositionY
);
987 SCALE_METRIC(superscriptSizeX
);
988 SCALE_METRIC(superscriptSizeY
);
990 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
996 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
998 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1000 TRACE("%p, %p.\n", iface
, metrics
);
1002 *metrics
= fontface
->caret
;
1005 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1006 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1008 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1010 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1013 if (max_count
&& !ranges
)
1014 return E_INVALIDARG
;
1016 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1017 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1020 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1022 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1024 TRACE("%p.\n", iface
);
1026 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1029 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1030 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1032 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1037 FIXME("Sideways mode is not supported.\n");
1039 switch (measuring_mode
)
1041 case DWRITE_MEASURING_MODE_NATURAL
:
1042 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1043 glyph
, measuring_mode
, &has_contours
);
1045 advance
+= adjustment
;
1048 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1049 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1054 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1055 FIXME("Transform is not supported.\n");
1057 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1060 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1062 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1066 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1071 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1072 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1074 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1077 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1080 FIXME("sideways mode not supported\n");
1082 for (i
= 0; i
< glyph_count
; ++i
)
1084 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1085 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1091 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1092 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1093 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1095 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1096 DWRITE_MEASURING_MODE measuring_mode
;
1099 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1100 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1102 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1103 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1104 return E_INVALIDARG
;
1107 if (em_size
== 0.0f
) {
1108 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1112 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1113 for (i
= 0; i
< glyph_count
; ++i
)
1115 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1116 glyphs
[i
], is_sideways
);
1122 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1123 const UINT16
*indices
, INT32
*adjustments
)
1125 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1128 TRACE("%p, %u, %p, %p.\n", iface
, count
, indices
, adjustments
);
1130 if (!(indices
|| adjustments
) || !count
)
1131 return E_INVALIDARG
;
1133 if (!indices
|| count
== 1) {
1134 memset(adjustments
, 0, count
*sizeof(INT32
));
1135 return E_INVALIDARG
;
1138 if (!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
))
1140 memset(adjustments
, 0, count
*sizeof(INT32
));
1144 for (i
= 0; i
< count
-1; i
++)
1145 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1146 adjustments
[count
-1] = 0;
1151 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1153 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1155 TRACE("%p.\n", iface
);
1157 return !!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1160 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1161 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1162 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1164 DWRITE_GRID_FIT_MODE gridfitmode
;
1165 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1166 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1169 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1170 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1172 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1174 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1176 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1179 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1181 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1183 TRACE("%p.\n", iface
);
1185 return !!(fontface
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1188 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1190 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1192 TRACE("%p.\n", iface
);
1194 return !!(fontface
->flags
& FONT_IS_COLORED
);
1197 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1199 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1201 TRACE("%p.\n", iface
);
1203 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1206 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1208 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1210 TRACE("%p.\n", iface
);
1212 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1215 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1216 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1218 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1220 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1222 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1225 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1226 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1227 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1228 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1230 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1234 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1235 measuringmode
, params
, renderingmode
, gridfitmode
);
1238 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1241 FIXME("sideways mode not supported\n");
1243 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1245 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1246 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1248 IDWriteRenderingParams2
*params2
;
1251 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1253 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1254 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1255 IDWriteRenderingParams2_Release(params2
);
1258 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1261 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1263 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1265 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1266 if (emSize
>= emthreshold
)
1267 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1269 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1272 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1273 if (emSize
>= emthreshold
)
1274 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1275 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1276 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1278 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1279 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1285 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1286 IDWriteFontFaceReference
**reference
)
1288 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1290 TRACE("%p, %p.\n", iface
, reference
);
1292 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1293 IDWriteFontFaceReference_AddRef(*reference
);
1298 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1300 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1302 TRACE("%p, %p.\n", iface
, panose
);
1304 *panose
= fontface
->panose
;
1307 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1309 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1311 TRACE("%p.\n", iface
);
1313 return fontface
->weight
;
1316 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1318 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1320 TRACE("%p.\n", iface
);
1322 return fontface
->stretch
;
1325 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1327 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1329 TRACE("%p.\n", iface
);
1331 return fontface
->style
;
1334 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1336 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1338 TRACE("%p, %p.\n", iface
, names
);
1340 return clone_localizedstrings(fontface
->family_names
, names
);
1343 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1345 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1347 TRACE("%p, %p.\n", iface
, names
);
1349 return clone_localizedstrings(fontface
->names
, names
);
1352 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1353 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1354 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1361 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1362 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1367 if (!strings_cache
[stringid
])
1369 struct file_stream_desc desc
= *stream_desc
;
1372 hr
= get_filestream_from_file(file
, &desc
.stream
);
1374 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1376 if (!stream_desc
->stream
&& desc
.stream
)
1377 IDWriteFontFileStream_Release(desc
.stream
);
1380 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1382 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1390 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1391 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1393 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1394 struct file_stream_desc stream_desc
;
1396 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1398 stream_desc
.stream
= fontface
->stream
;
1399 stream_desc
.face_index
= fontface
->index
;
1400 stream_desc
.face_type
= fontface
->type
;
1401 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1404 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1406 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1408 TRACE("%p, %#x.\n", iface
, ch
);
1410 return !!dwritefontface_get_glyph(fontface
, ch
);
1413 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1414 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1415 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1417 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1421 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1422 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1425 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1428 FIXME("sideways mode not supported\n");
1430 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1432 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1433 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1435 IDWriteRenderingParams3
*params3
;
1438 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1440 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1441 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1442 IDWriteRenderingParams3_Release(params3
);
1445 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1448 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1450 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1452 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1453 if (emSize
>= emthreshold
)
1454 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1456 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1459 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1460 if (emSize
>= emthreshold
)
1461 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1462 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1463 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1465 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1466 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1472 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1474 FIXME("%p, %#x: stub\n", iface
, ch
);
1479 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1481 FIXME("%p, %u: stub\n", iface
, glyph
);
1486 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1487 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1489 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1494 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1495 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1497 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1502 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1503 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1505 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1510 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1512 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1514 TRACE("%p.\n", iface
);
1516 return fontface
->glyph_image_formats
;
1519 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1520 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1522 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1527 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1529 FIXME("%p, %p: stub\n", iface
, context
);
1532 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1534 FIXME("%p: stub\n", iface
);
1539 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1542 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1547 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1552 FIXME("%p: stub\n", iface
);
1557 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1559 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1561 TRACE("%p, %p.\n", iface
, resource
);
1563 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->files
[0], fontface
->index
, resource
);
1566 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1568 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1570 TRACE("%p, %p.\n", iface
, other
);
1572 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1575 /* TODO: add variations support */
1577 return fontface
->index
== other_face
->index
&&
1578 fontface
->simulations
== other_face
->simulations
&&
1579 is_same_fontfile(fontface
->files
[0], other_face
->files
[0]);
1582 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1584 dwritefontface_QueryInterface
,
1585 dwritefontface_AddRef
,
1586 dwritefontface_Release
,
1587 dwritefontface_GetType
,
1588 dwritefontface_GetFiles
,
1589 dwritefontface_GetIndex
,
1590 dwritefontface_GetSimulations
,
1591 dwritefontface_IsSymbolFont
,
1592 dwritefontface_GetMetrics
,
1593 dwritefontface_GetGlyphCount
,
1594 dwritefontface_GetDesignGlyphMetrics
,
1595 dwritefontface_GetGlyphIndices
,
1596 dwritefontface_TryGetFontTable
,
1597 dwritefontface_ReleaseFontTable
,
1598 dwritefontface_GetGlyphRunOutline
,
1599 dwritefontface_GetRecommendedRenderingMode
,
1600 dwritefontface_GetGdiCompatibleMetrics
,
1601 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1602 dwritefontface1_GetMetrics
,
1603 dwritefontface1_GetGdiCompatibleMetrics
,
1604 dwritefontface1_GetCaretMetrics
,
1605 dwritefontface1_GetUnicodeRanges
,
1606 dwritefontface1_IsMonospacedFont
,
1607 dwritefontface1_GetDesignGlyphAdvances
,
1608 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1609 dwritefontface1_GetKerningPairAdjustments
,
1610 dwritefontface1_HasKerningPairs
,
1611 dwritefontface1_GetRecommendedRenderingMode
,
1612 dwritefontface1_GetVerticalGlyphVariants
,
1613 dwritefontface1_HasVerticalGlyphVariants
,
1614 dwritefontface2_IsColorFont
,
1615 dwritefontface2_GetColorPaletteCount
,
1616 dwritefontface2_GetPaletteEntryCount
,
1617 dwritefontface2_GetPaletteEntries
,
1618 dwritefontface2_GetRecommendedRenderingMode
,
1619 dwritefontface3_GetFontFaceReference
,
1620 dwritefontface3_GetPanose
,
1621 dwritefontface3_GetWeight
,
1622 dwritefontface3_GetStretch
,
1623 dwritefontface3_GetStyle
,
1624 dwritefontface3_GetFamilyNames
,
1625 dwritefontface3_GetFaceNames
,
1626 dwritefontface3_GetInformationalStrings
,
1627 dwritefontface3_HasCharacter
,
1628 dwritefontface3_GetRecommendedRenderingMode
,
1629 dwritefontface3_IsCharacterLocal
,
1630 dwritefontface3_IsGlyphLocal
,
1631 dwritefontface3_AreCharactersLocal
,
1632 dwritefontface3_AreGlyphsLocal
,
1633 dwritefontface4_GetGlyphImageFormats_
,
1634 dwritefontface4_GetGlyphImageFormats
,
1635 dwritefontface4_GetGlyphImageData
,
1636 dwritefontface4_ReleaseGlyphImageData
,
1637 dwritefontface5_GetFontAxisValueCount
,
1638 dwritefontface5_GetFontAxisValues
,
1639 dwritefontface5_HasVariations
,
1640 dwritefontface5_GetFontResource
,
1641 dwritefontface5_Equals
,
1644 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1646 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1647 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1650 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1652 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1653 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1656 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1658 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1659 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1662 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1663 IDWriteFontFace3
**ret
)
1665 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1667 TRACE("%p, %p.\n", iface
, ret
);
1669 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1670 IDWriteFontFace3_AddRef(*ret
);
1675 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1676 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1678 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1679 DWRITE_FONT_FILE_TYPE file_type
;
1680 DWRITE_FONT_FACE_TYPE face_type
;
1681 IDWriteFontFace
*face
;
1686 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1688 hr
= IDWriteFontFile_Analyze(fontface
->files
[0], &is_supported
, &file_type
, &face_type
, &face_num
);
1692 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, fontface
->files
, fontface
->index
,
1693 simulations
, &face
);
1696 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1697 IDWriteFontFace_Release(face
);
1703 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1705 FIXME("%p, %p.\n", iface
, ref
);
1710 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1712 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1714 TRACE("%p.\n", iface
);
1716 return fontface
->index
;
1719 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1721 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1723 TRACE("%p.\n", iface
);
1725 return fontface
->simulations
;
1728 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1730 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1732 TRACE("%p, %p.\n", iface
, file
);
1734 *file
= fontface
->files
[0];
1735 IDWriteFontFile_AddRef(*file
);
1740 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1742 FIXME("%p.\n", iface
);
1747 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1749 FIXME("%p.\n", iface
);
1754 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1756 FIXME("%p, %p.\n", iface
, writetime
);
1761 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1763 FIXME("%p.\n", iface
);
1765 return DWRITE_LOCALITY_LOCAL
;
1768 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1770 FIXME("%p.\n", iface
);
1775 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1776 WCHAR
const *chars
, UINT32 count
)
1778 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1783 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1784 UINT16
const *glyphs
, UINT32 count
)
1786 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1791 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1792 UINT64 offset
, UINT64 size
)
1794 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1799 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1801 dwritefontface_reference_QueryInterface
,
1802 dwritefontface_reference_AddRef
,
1803 dwritefontface_reference_Release
,
1804 dwritefontface_reference_CreateFontFace
,
1805 dwritefontface_reference_CreateFontFaceWithSimulations
,
1806 dwritefontface_reference_Equals
,
1807 dwritefontface_reference_GetFontFaceIndex
,
1808 dwritefontface_reference_GetSimulations
,
1809 dwritefontface_reference_GetFontFile
,
1810 dwritefontface_reference_GetLocalFileSize
,
1811 dwritefontface_reference_GetFileSize
,
1812 dwritefontface_reference_GetFileTime
,
1813 dwritefontface_reference_GetLocality
,
1814 dwritefontface_reference_EnqueueFontDownloadRequest
,
1815 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1816 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1817 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1820 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1822 struct dwrite_font_data
*data
= font
->data
;
1823 struct fontface_desc desc
;
1824 struct list
*cached_list
;
1829 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1830 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1834 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1837 desc
.factory
= font
->family
->collection
->factory
;
1838 desc
.face_type
= data
->face_type
;
1839 desc
.files
= &data
->file
;
1840 desc
.files_number
= 1;
1841 desc
.index
= data
->face_index
;
1842 desc
.simulations
= data
->simulations
;
1843 desc
.font_data
= data
;
1844 hr
= create_fontface(&desc
, cached_list
, fontface
);
1846 IDWriteFontFileStream_Release(desc
.stream
);
1850 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1852 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1854 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1855 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1856 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1857 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1858 IsEqualIID(riid
, &IID_IUnknown
))
1861 IDWriteFont3_AddRef(iface
);
1865 WARN("%s not implemented.\n", debugstr_guid(riid
));
1868 return E_NOINTERFACE
;
1871 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1873 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1874 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
1876 TRACE("%p, refcount %d.\n", iface
, refcount
);
1881 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1883 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1884 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
1886 TRACE("%p, refcount %d.\n", iface
, refcount
);
1890 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
1891 release_font_data(font
->data
);
1898 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1900 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1902 TRACE("%p, %p.\n", iface
, family
);
1904 *family
= (IDWriteFontFamily
*)font
->family
;
1905 IDWriteFontFamily_AddRef(*family
);
1909 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1911 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1913 TRACE("%p.\n", iface
);
1915 return font
->data
->weight
;
1918 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1920 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1922 TRACE("%p.\n", iface
);
1924 return font
->data
->stretch
;
1927 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1929 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1931 TRACE("%p.\n", iface
);
1936 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1938 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1940 TRACE("%p.\n", iface
);
1942 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
1945 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1947 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1949 TRACE("%p, %p.\n", iface
, names
);
1951 return clone_localizedstrings(font
->data
->names
, names
);
1954 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1955 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1957 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1958 struct dwrite_font_data
*data
= font
->data
;
1959 struct file_stream_desc stream_desc
;
1961 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
1963 /* Stream will be created if necessary. */
1964 stream_desc
.stream
= NULL
;
1965 stream_desc
.face_index
= data
->face_index
;
1966 stream_desc
.face_type
= data
->face_type
;
1967 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
1970 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1972 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1974 TRACE("%p.\n", iface
);
1976 return font
->data
->simulations
;
1979 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1981 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1983 TRACE("%p, %p.\n", iface
, metrics
);
1985 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
1988 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
1991 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
1992 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
1996 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
1998 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2000 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2002 *exists
= dwritefont_has_character(font
, ch
);
2007 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2009 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2011 TRACE("%p, %p.\n", iface
, fontface
);
2013 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2016 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2018 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2020 TRACE("%p, %p.\n", iface
, metrics
);
2022 *metrics
= font
->data
->metrics
;
2025 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2027 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2029 TRACE("%p, %p.\n", iface
, panose
);
2031 *panose
= font
->data
->panose
;
2034 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2037 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2039 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2042 if (max_count
&& !ranges
)
2043 return E_INVALIDARG
;
2045 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2046 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2049 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2051 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2053 TRACE("%p.\n", iface
);
2055 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2058 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2060 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2062 TRACE("%p.\n", iface
);
2064 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2067 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2069 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2071 TRACE("%p, %p.\n", iface
, fontface
);
2073 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2076 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2078 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2080 TRACE("%p, %p.\n", iface
, other
);
2082 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2085 return font
->data
->face_index
== other_font
->data
->face_index
2086 && font
->data
->simulations
== other_font
->data
->simulations
2087 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2090 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2092 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2094 TRACE("%p, %p.\n", iface
, reference
);
2096 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2097 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2098 (IDWriteFontFaceReference1
**)reference
);
2101 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2103 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2105 TRACE("%p, %#x.\n", iface
, ch
);
2107 return dwritefont_has_character(font
, ch
);
2110 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2112 FIXME("%p: stub.\n", iface
);
2114 return DWRITE_LOCALITY_LOCAL
;
2117 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2118 dwritefont_QueryInterface
,
2121 dwritefont_GetFontFamily
,
2122 dwritefont_GetWeight
,
2123 dwritefont_GetStretch
,
2124 dwritefont_GetStyle
,
2125 dwritefont_IsSymbolFont
,
2126 dwritefont_GetFaceNames
,
2127 dwritefont_GetInformationalStrings
,
2128 dwritefont_GetSimulations
,
2129 dwritefont_GetMetrics
,
2130 dwritefont_HasCharacter
,
2131 dwritefont_CreateFontFace
,
2132 dwritefont1_GetMetrics
,
2133 dwritefont1_GetPanose
,
2134 dwritefont1_GetUnicodeRanges
,
2135 dwritefont1_IsMonospacedFont
,
2136 dwritefont2_IsColorFont
,
2137 dwritefont3_CreateFontFace
,
2139 dwritefont3_GetFontFaceReference
,
2140 dwritefont3_HasCharacter
,
2141 dwritefont3_GetLocality
2144 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2148 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2149 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2152 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2156 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2157 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2160 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2164 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2166 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2167 IDWriteFontFaceReference1_iface
);
2170 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2172 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2173 *lf
= font
->data
->lf
;
2176 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2178 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2182 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2184 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2185 *fontsig
= font
->data
->fontsig
;
2189 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2191 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2192 *fontsig
= fontface
->fontsig
;
2196 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2198 struct dwrite_font
*object
;
2202 if (!(object
= heap_alloc(sizeof(*object
))))
2203 return E_OUTOFMEMORY
;
2205 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2206 object
->refcount
= 1;
2207 object
->family
= family
;
2208 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2209 object
->data
= family
->data
->fonts
[index
];
2210 object
->style
= object
->data
->style
;
2211 addref_font_data(object
->data
);
2213 *font
= &object
->IDWriteFont3_iface
;
2218 /* IDWriteFontList2 */
2219 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2221 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2223 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2224 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2225 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2226 IsEqualIID(riid
, &IID_IUnknown
))
2229 IDWriteFontList2_AddRef(iface
);
2233 WARN("%s not implemented.\n", debugstr_guid(riid
));
2236 return E_NOINTERFACE
;
2239 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2241 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2242 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2244 TRACE("%p, refcount %u.\n", iface
, refcount
);
2249 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2251 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2252 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2254 TRACE("%p, refcount %u.\n", iface
, refcount
);
2260 for (i
= 0; i
< fontlist
->font_count
; i
++)
2261 release_font_data(fontlist
->fonts
[i
]);
2262 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2263 heap_free(fontlist
->fonts
);
2264 heap_free(fontlist
);
2270 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2272 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2273 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2276 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2278 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2280 TRACE("%p.\n", iface
);
2282 return fontlist
->font_count
;
2285 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2287 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2289 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2293 if (fontlist
->font_count
== 0)
2296 if (index
>= fontlist
->font_count
)
2297 return E_INVALIDARG
;
2299 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2302 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2304 FIXME("%p, %u.\n", iface
, index
);
2306 return DWRITE_LOCALITY_LOCAL
;
2309 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2311 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2313 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2317 if (fontlist
->font_count
== 0)
2320 if (index
>= fontlist
->font_count
)
2323 return create_font(fontlist
->family
, index
, font
);
2326 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2327 IDWriteFontFaceReference
**reference
)
2332 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2336 hr
= IDWriteFontList2_GetFont(iface
, index
, &font
);
2340 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2341 IDWriteFont3_Release(font
);
2346 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2348 FIXME("%p, %p.\n", iface
, fontset
);
2353 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2355 dwritefontlist_QueryInterface
,
2356 dwritefontlist_AddRef
,
2357 dwritefontlist_Release
,
2358 dwritefontlist_GetFontCollection
,
2359 dwritefontlist_GetFontCount
,
2360 dwritefontlist_GetFont
,
2361 dwritefontlist1_GetFontLocality
,
2362 dwritefontlist1_GetFont
,
2363 dwritefontlist1_GetFontFaceReference
,
2364 dwritefontlist2_GetFontSet
,
2367 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2369 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2371 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2373 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2374 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2375 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2376 IsEqualIID(riid
, &IID_IUnknown
))
2380 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2381 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2382 IsEqualIID(riid
, &IID_IDWriteFontList
))
2384 *obj
= &family
->IDWriteFontList2_iface
;
2388 WARN("%s not implemented.\n", debugstr_guid(riid
));
2390 return E_NOINTERFACE
;
2393 IUnknown_AddRef((IUnknown
*)*obj
);
2397 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2399 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2400 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2402 TRACE("%p, %u.\n", iface
, refcount
);
2407 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2409 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2410 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2412 TRACE("%p, %u.\n", iface
, refcount
);
2416 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2417 release_fontfamily_data(family
->data
);
2424 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2426 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2428 TRACE("%p, %p.\n", iface
, collection
);
2430 *collection
= (IDWriteFontCollection
*)family
->collection
;
2431 IDWriteFontCollection_AddRef(*collection
);
2435 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2437 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2439 TRACE("%p.\n", iface
);
2441 return family
->data
->count
;
2444 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2446 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2448 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2452 if (!family
->data
->count
)
2455 if (index
>= family
->data
->count
)
2456 return E_INVALIDARG
;
2458 return create_font(family
, index
, (IDWriteFont3
**)font
);
2461 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2463 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2465 TRACE("%p, %p.\n", iface
, names
);
2467 return clone_localizedstrings(family
->data
->familyname
, names
);
2470 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2471 const struct dwrite_font_propvec
*req
)
2473 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2474 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2475 FLOAT cur_req_prod
, next_req_prod
;
2477 if (next_to_req
< cur_to_req
)
2480 if (next_to_req
> cur_to_req
)
2483 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2484 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2486 if (next_req_prod
> cur_req_prod
)
2489 if (next_req_prod
< cur_req_prod
)
2492 if (next
->stretch
> cur
->stretch
)
2494 if (next
->stretch
< cur
->stretch
)
2497 if (next
->style
> cur
->style
)
2499 if (next
->style
< cur
->style
)
2502 if (next
->weight
> cur
->weight
)
2504 if (next
->weight
< cur
->weight
)
2507 /* full match, no reason to prefer new variant */
2511 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2512 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2514 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2515 struct dwrite_font_propvec req
;
2518 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2520 if (!family
->data
->count
)
2523 return DWRITE_E_NOFONT
;
2526 init_font_prop_vec(weight
, stretch
, style
, &req
);
2529 for (i
= 1; i
< family
->data
->count
; ++i
)
2531 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2535 return create_font(family
, match
, (IDWriteFont3
**)font
);
2538 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2540 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2542 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2545 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2547 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2550 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2552 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2557 for (j
= 0; j
< b
; j
++) {
2558 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2559 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2560 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2561 fonts
->fonts
[j
+1] = s
;
2572 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2573 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2575 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2576 matching_filter_func func
= NULL
;
2577 struct dwrite_font_propvec req
;
2578 struct dwrite_fontlist
*fonts
;
2581 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2585 fonts
= heap_alloc(sizeof(*fonts
));
2587 return E_OUTOFMEMORY
;
2589 /* Allocate as many as family has, not all of them will be necessary used. */
2590 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2591 if (!fonts
->fonts
) {
2593 return E_OUTOFMEMORY
;
2596 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2597 fonts
->refcount
= 1;
2598 fonts
->family
= family
;
2599 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2600 fonts
->font_count
= 0;
2602 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2603 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2604 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2605 func
= is_font_acceptable_for_normal
;
2607 else /* requested oblique or italic */ {
2608 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2609 func
= is_font_acceptable_for_oblique_italic
;
2612 for (i
= 0; i
< family
->data
->count
; ++i
)
2614 if (!func
|| func(family
->data
->fonts
[i
]))
2616 fonts
->fonts
[fonts
->font_count
] = family
->data
->fonts
[i
];
2617 addref_font_data(family
->data
->fonts
[i
]);
2618 fonts
->font_count
++;
2622 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2623 init_font_prop_vec(weight
, stretch
, style
, &req
);
2624 matchingfonts_sort(fonts
, &req
);
2626 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2630 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2632 FIXME("%p, %u.\n", iface
, index
);
2634 return DWRITE_LOCALITY_LOCAL
;
2637 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2639 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2641 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2645 if (!family
->data
->count
)
2648 if (index
>= family
->data
->count
)
2651 return create_font(family
, index
, font
);
2654 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2655 IDWriteFontFaceReference
**reference
)
2657 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2658 const struct dwrite_font_data
*font
;
2660 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2664 if (index
>= family
->data
->count
)
2667 font
= family
->data
->fonts
[index
];
2668 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2669 font
->file
, font
->face_index
, font
->simulations
, reference
);
2672 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2673 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2675 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2680 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2682 FIXME("%p, %p.\n", iface
, fontset
);
2687 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2689 dwritefontfamily_QueryInterface
,
2690 dwritefontfamily_AddRef
,
2691 dwritefontfamily_Release
,
2692 dwritefontfamily_GetFontCollection
,
2693 dwritefontfamily_GetFontCount
,
2694 dwritefontfamily_GetFont
,
2695 dwritefontfamily_GetFamilyNames
,
2696 dwritefontfamily_GetFirstMatchingFont
,
2697 dwritefontfamily_GetMatchingFonts
,
2698 dwritefontfamily1_GetFontLocality
,
2699 dwritefontfamily1_GetFont
,
2700 dwritefontfamily1_GetFontFaceReference
,
2701 dwritefontfamily2_GetMatchingFonts
,
2702 dwritefontfamily2_GetFontSet
,
2705 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2707 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2708 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2711 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2713 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2714 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2717 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2719 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2720 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2723 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2724 IDWriteFontCollection
**collection
)
2726 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2727 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2730 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2732 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2733 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2736 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2738 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2739 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2742 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2744 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2745 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2748 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2750 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2751 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2754 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2755 IDWriteFontFaceReference
**reference
)
2757 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2758 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2761 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2763 FIXME("%p, %p.\n", iface
, fontset
);
2768 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2770 dwritefontfamilylist_QueryInterface
,
2771 dwritefontfamilylist_AddRef
,
2772 dwritefontfamilylist_Release
,
2773 dwritefontfamilylist_GetFontCollection
,
2774 dwritefontfamilylist_GetFontCount
,
2775 dwritefontfamilylist_GetFont
,
2776 dwritefontfamilylist1_GetFontLocality
,
2777 dwritefontfamilylist1_GetFont
,
2778 dwritefontfamilylist1_GetFontFaceReference
,
2779 dwritefontfamilylist2_GetFontSet
,
2782 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2783 struct dwrite_fontfamily
**family
)
2785 struct dwrite_fontfamily
*object
;
2789 object
= heap_alloc(sizeof(*object
));
2791 return E_OUTOFMEMORY
;
2793 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2794 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2795 object
->refcount
= 1;
2796 object
->collection
= collection
;
2797 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2798 object
->data
= collection
->family_data
[index
];
2799 InterlockedIncrement(&object
->data
->refcount
);
2806 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2809 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2812 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2814 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2816 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2818 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2819 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2820 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2821 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2822 IsEqualIID(riid
, &IID_IUnknown
))
2825 IDWriteFontCollection3_AddRef(iface
);
2831 if (IsEqualIID(riid
, &IID_issystemcollection
))
2834 WARN("%s not implemented.\n", debugstr_guid(riid
));
2836 return E_NOINTERFACE
;
2839 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2841 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2843 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2844 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2845 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2846 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2847 IsEqualIID(riid
, &IID_IUnknown
))
2850 IDWriteFontCollection3_AddRef(iface
);
2854 WARN("%s not implemented.\n", debugstr_guid(riid
));
2858 return E_NOINTERFACE
;
2861 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2863 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2864 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2866 TRACE("%p, refcount %d.\n", collection
, refcount
);
2871 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2873 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2874 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2877 TRACE("%p, refcount %d.\n", iface
, refcount
);
2881 factory_detach_fontcollection(collection
->factory
, iface
);
2882 for (i
= 0; i
< collection
->count
; ++i
)
2883 release_fontfamily_data(collection
->family_data
[i
]);
2884 heap_free(collection
->family_data
);
2885 heap_free(collection
);
2891 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2893 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2895 TRACE("%p.\n", iface
);
2897 return collection
->count
;
2900 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2901 IDWriteFontFamily
**ret
)
2903 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2904 struct dwrite_fontfamily
*family
;
2907 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2911 if (index
>= collection
->count
)
2914 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2915 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2920 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2924 for (i
= 0; i
< collection
->count
; ++i
)
2926 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2927 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2930 for (j
= 0; j
< count
; j
++) {
2932 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
2933 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2941 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
2942 UINT32
*index
, BOOL
*exists
)
2944 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2946 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
2948 *index
= collection_find_family(collection
, name
);
2949 *exists
= *index
!= ~0u;
2953 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
2956 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2957 struct dwrite_fontfamily
*family
;
2958 BOOL found_font
= FALSE
;
2959 IDWriteFontFile
*file
;
2960 UINT32 face_index
, count
;
2964 TRACE("%p, %p, %p.\n", iface
, face
, font
);
2969 return E_INVALIDARG
;
2972 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
2975 face_index
= IDWriteFontFace_GetIndex(face
);
2978 for (i
= 0; i
< collection
->count
; ++i
)
2980 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
2982 for (j
= 0; j
< family_data
->count
; ++j
)
2984 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2986 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2995 IDWriteFontFile_Release(file
);
2998 return DWRITE_E_NOFONT
;
3000 hr
= create_fontfamily(collection
, i
, &family
);
3004 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3005 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3009 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3011 FIXME("%p, %p.\n", iface
, fontset
);
3016 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3017 IDWriteFontFamily1
**ret
)
3019 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3020 struct dwrite_fontfamily
*family
;
3023 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3027 if (index
>= collection
->count
)
3030 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3031 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3036 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3037 UINT32 index
, IDWriteFontFamily2
**ret
)
3039 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3040 struct dwrite_fontfamily
*family
;
3043 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3047 if (index
>= collection
->count
)
3050 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3051 *ret
= &family
->IDWriteFontFamily2_iface
;
3056 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3057 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3058 IDWriteFontList2
**fontlist
)
3060 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3065 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3067 FIXME("%p.\n", iface
);
3069 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3072 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3074 FIXME("%p, %p.\n", iface
, fontset
);
3079 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3081 FIXME("%p.\n", iface
);
3086 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3088 dwritefontcollection_QueryInterface
,
3089 dwritefontcollection_AddRef
,
3090 dwritefontcollection_Release
,
3091 dwritefontcollection_GetFontFamilyCount
,
3092 dwritefontcollection_GetFontFamily
,
3093 dwritefontcollection_FindFamilyName
,
3094 dwritefontcollection_GetFontFromFontFace
,
3095 dwritefontcollection1_GetFontSet
,
3096 dwritefontcollection1_GetFontFamily
,
3097 dwritefontcollection2_GetFontFamily
,
3098 dwritefontcollection2_GetMatchingFonts
,
3099 dwritefontcollection2_GetFontFamilyModel
,
3100 dwritefontcollection2_GetFontSet
,
3101 dwritefontcollection3_GetExpirationEvent
,
3104 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3106 dwritesystemfontcollection_QueryInterface
,
3107 dwritefontcollection_AddRef
,
3108 dwritefontcollection_Release
,
3109 dwritefontcollection_GetFontFamilyCount
,
3110 dwritefontcollection_GetFontFamily
,
3111 dwritefontcollection_FindFamilyName
,
3112 dwritefontcollection_GetFontFromFontFace
,
3113 dwritefontcollection1_GetFontSet
,
3114 dwritefontcollection1_GetFontFamily
,
3115 dwritefontcollection2_GetFontFamily
,
3116 dwritefontcollection2_GetMatchingFonts
,
3117 dwritefontcollection2_GetFontFamilyModel
,
3118 dwritefontcollection2_GetFontSet
,
3119 dwritefontcollection3_GetExpirationEvent
,
3122 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3124 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3125 sizeof(*family_data
->fonts
)))
3127 return E_OUTOFMEMORY
;
3130 family_data
->fonts
[family_data
->count
++] = font_data
;
3131 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3132 family_data
->has_normal_face
= 1;
3133 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3134 family_data
->has_oblique_face
= 1;
3136 family_data
->has_italic_face
= 1;
3140 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3141 struct dwrite_fontfamily_data
*family
)
3143 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3144 sizeof(*collection
->family_data
)))
3146 return E_OUTOFMEMORY
;
3149 collection
->family_data
[collection
->count
++] = family
;
3153 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3155 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3156 collection
->refcount
= 1;
3157 collection
->count
= 0;
3158 collection
->size
= 0;
3159 collection
->family_data
= NULL
;
3164 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3166 IDWriteFontFileLoader
*loader
;
3173 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3177 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3181 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3182 IDWriteFontFileLoader_Release(loader
);
3189 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3191 BOOL exists
= FALSE
;
3196 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3197 if (FAILED(hr
) || !exists
)
3200 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3203 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3207 while (isspaceW(*in
))
3211 if (!(len
= strlenW(in
)))
3214 while (isspaceW(in
[len
-1]))
3217 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3226 INT len
; /* token length */
3227 INT fulllen
; /* full length including following separators */
3230 static inline BOOL
is_name_separator_char(WCHAR ch
)
3232 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3235 struct name_pattern
{
3236 const WCHAR
*part1
; /* NULL indicates end of list */
3237 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3240 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3242 const struct name_pattern
*pattern
;
3243 struct name_token
*token
;
3246 while ((pattern
= &patterns
[i
++])->part1
) {
3247 int len_part1
= strlenW(pattern
->part1
);
3248 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3250 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3251 if (len_part2
== 0) {
3252 /* simple case with single part pattern */
3253 if (token
->len
!= len_part1
)
3256 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3257 if (match
) *match
= *token
;
3258 list_remove(&token
->entry
);
3264 struct name_token
*next_token
;
3265 struct list
*next_entry
;
3267 /* pattern parts are stored in reading order, tokens list is reversed */
3268 if (token
->len
< len_part2
)
3271 /* it's possible to have combined string as a token, like ExtraCondensed */
3272 if (token
->len
== len_part1
+ len_part2
) {
3273 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3276 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3279 /* combined string match */
3280 if (match
) *match
= *token
;
3281 list_remove(&token
->entry
);
3286 /* now it's only possible to have two tokens matched to respective pattern parts */
3287 if (token
->len
!= len_part2
)
3290 next_entry
= list_next(tokens
, &token
->entry
);
3292 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3293 if (next_token
->len
!= len_part1
)
3296 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3299 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3302 /* both parts matched, remove tokens */
3304 match
->ptr
= next_token
->ptr
;
3305 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3307 list_remove(&token
->entry
);
3308 list_remove(&next_token
->entry
);
3309 heap_free(next_token
);
3324 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3326 static const WCHAR itaW
[] = {'i','t','a',0};
3327 static const WCHAR italW
[] = {'i','t','a','l',0};
3328 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3329 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3331 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3332 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3333 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3334 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3336 static const struct name_pattern italic_patterns
[] = {
3345 static const struct name_pattern oblique_patterns
[] = {
3354 /* italic patterns first */
3355 if (match_pattern_list(tokens
, italic_patterns
, match
))
3356 return DWRITE_FONT_STYLE_ITALIC
;
3358 /* oblique patterns */
3359 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3360 return DWRITE_FONT_STYLE_OBLIQUE
;
3365 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3366 struct name_token
*match
)
3368 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3369 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3370 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3371 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3372 static const WCHAR wideW
[] = {'w','i','d','e',0};
3373 static const WCHAR condW
[] = {'c','o','n','d',0};
3375 static const struct name_pattern ultracondensed_patterns
[] = {
3376 { extraW
, compressedW
},
3377 { extW
, compressedW
},
3378 { ultraW
, compressedW
},
3379 { ultraW
, condensedW
},
3384 static const struct name_pattern extracondensed_patterns
[] = {
3386 { extraW
, condensedW
},
3387 { extW
, condensedW
},
3393 static const struct name_pattern semicondensed_patterns
[] = {
3396 { semiW
, condensedW
},
3401 static const struct name_pattern semiexpanded_patterns
[] = {
3403 { semiW
, expandedW
},
3404 { semiW
, extendedW
},
3408 static const struct name_pattern extraexpanded_patterns
[] = {
3409 { extraW
, expandedW
},
3410 { extW
, expandedW
},
3411 { extraW
, extendedW
},
3412 { extW
, extendedW
},
3416 static const struct name_pattern ultraexpanded_patterns
[] = {
3417 { ultraW
, expandedW
},
3418 { ultraW
, extendedW
},
3422 static const struct name_pattern condensed_patterns
[] = {
3428 static const struct name_pattern expanded_patterns
[] = {
3434 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3435 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3437 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3438 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3440 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3441 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3443 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3444 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3446 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3447 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3449 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3450 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3452 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3453 return DWRITE_FONT_STRETCH_CONDENSED
;
3455 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3456 return DWRITE_FONT_STRETCH_EXPANDED
;
3461 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3462 struct name_token
*match
)
3464 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3465 static const WCHAR nordW
[] = {'n','o','r','d',0};
3467 static const struct name_pattern thin_patterns
[] = {
3474 static const struct name_pattern extralight_patterns
[] = {
3481 static const struct name_pattern semilight_patterns
[] = {
3486 static const struct name_pattern demibold_patterns
[] = {
3492 static const struct name_pattern extrabold_patterns
[] = {
3499 static const struct name_pattern extrablack_patterns
[] = {
3506 static const struct name_pattern bold_patterns
[] = {
3511 static const struct name_pattern thin2_patterns
[] = {
3516 static const struct name_pattern light_patterns
[] = {
3521 static const struct name_pattern medium_patterns
[] = {
3526 static const struct name_pattern black_patterns
[] = {
3533 static const struct name_pattern demibold2_patterns
[] = {
3538 static const struct name_pattern extrabold2_patterns
[] = {
3543 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3544 matching pattern. */
3546 if (match_pattern_list(tokens
, thin_patterns
, match
))
3547 return DWRITE_FONT_WEIGHT_THIN
;
3549 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3550 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3552 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3553 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3555 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3556 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3558 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3559 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3561 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3562 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3564 if (match_pattern_list(tokens
, bold_patterns
, match
))
3565 return DWRITE_FONT_WEIGHT_BOLD
;
3567 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3568 return DWRITE_FONT_WEIGHT_THIN
;
3570 if (match_pattern_list(tokens
, light_patterns
, match
))
3571 return DWRITE_FONT_WEIGHT_LIGHT
;
3573 if (match_pattern_list(tokens
, medium_patterns
, match
))
3574 return DWRITE_FONT_WEIGHT_MEDIUM
;
3576 if (match_pattern_list(tokens
, black_patterns
, match
))
3577 return DWRITE_FONT_WEIGHT_BLACK
;
3579 if (match_pattern_list(tokens
, black_patterns
, match
))
3580 return DWRITE_FONT_WEIGHT_BLACK
;
3582 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3583 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3585 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3586 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3588 /* FIXME: use abbreviated names to extract weight */
3593 struct knownweight_entry
{
3595 DWRITE_FONT_WEIGHT weight
;
3598 static int compare_knownweights(const void *a
, const void* b
)
3600 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3601 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3604 if (target
> entry
->weight
)
3606 else if (target
< entry
->weight
)
3612 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3614 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3615 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3616 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3617 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3618 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3619 const struct knownweight_entry
*ptr
;
3621 static const struct knownweight_entry knownweights
[] = {
3622 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3623 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3624 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3625 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3626 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3627 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3628 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3629 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3630 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3631 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3634 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3635 compare_knownweights
);
3641 strcpyW(nameW
, ptr
->nameW
);
3645 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3647 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3648 strW
[name
->len
] = 0;
3651 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3652 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3654 static const WCHAR bookW
[] = {'B','o','o','k',0};
3655 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3656 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3657 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3658 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3660 static const WCHAR
*regular_patterns
[] = {
3669 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3673 len
= strlenW(facenameW
);
3675 /* remove rightmost regular variant from face name */
3676 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3677 int pattern_len
= strlenW(ptr
);
3680 if (pattern_len
> len
)
3683 src
= facenameW
+ len
- pattern_len
;
3684 while (src
>= facenameW
) {
3685 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3686 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3687 len
= strlenW(facenameW
);
3699 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3707 struct name_token
*token
= heap_alloc(sizeof(*token
));
3712 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3718 /* skip separators */
3719 while (is_name_separator_char(*ptr
)) {
3724 list_add_head(tokens
, &token
->entry
);
3728 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3730 struct name_token
*token
, *token2
;
3731 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3734 list_remove(&token
->entry
);
3736 /* don't include last separator */
3737 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3738 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3746 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3748 struct name_token stretch_name
, weight_name
, style_name
;
3749 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3750 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3751 const WCHAR
*regular_ptr
= NULL
;
3752 DWRITE_FONT_STRETCH stretch
;
3753 DWRITE_FONT_WEIGHT weight
;
3757 /* remove leading and trailing spaces from family and face name */
3758 trim_spaces(familyW
, familynameW
);
3759 len
= trim_spaces(faceW
, facenameW
);
3761 /* remove rightmost regular variant from face name */
3762 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3764 /* append face name to family name, FIXME check if face name is a substring of family name */
3766 strcatW(familynameW
, spaceW
);
3767 strcatW(familynameW
, facenameW
);
3770 /* tokenize with " .-_" */
3771 fontname_tokenize(&tokens
, familynameW
);
3773 /* extract and resolve style */
3774 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3776 /* extract stretch */
3777 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3779 /* extract weight */
3780 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3782 /* resolve weight */
3783 if (weight
!= font
->weight
) {
3784 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3785 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3786 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3787 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3788 !(abs(weight
- font
->weight
) <= 150 &&
3789 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3790 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3791 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3793 font
->weight
= weight
;
3797 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3798 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3799 stretch itself is normal (extracted stretch is never normal). */
3800 if (stretch
!= font
->stretch
) {
3801 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3802 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3803 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3805 font
->stretch
= stretch
;
3809 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3811 /* get final combined string from what's left in token list, list is released */
3812 fontname_tokens_to_str(&tokens
, finalW
);
3814 if (!strcmpW(familyW
, finalW
))
3817 /* construct face name */
3818 strcpyW(familyW
, finalW
);
3820 /* resolved weight name */
3821 if (weight_name
.ptr
)
3822 font_name_token_to_str(&weight_name
, weightW
);
3823 /* ignore normal weight */
3824 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3826 /* for known weight values use appropriate names */
3827 else if (is_known_weight_value(font
->weight
, weightW
)) {
3829 /* use Wnnn format as a fallback in case weight is not one of known values */
3831 static const WCHAR fmtW
[] = {'W','%','d',0};
3832 sprintfW(weightW
, fmtW
, font
->weight
);
3835 /* resolved stretch name */
3836 if (stretch_name
.ptr
)
3837 font_name_token_to_str(&stretch_name
, stretchW
);
3838 /* ignore normal stretch */
3839 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3841 /* use predefined stretch names */
3843 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3844 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3845 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3846 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3847 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3848 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3850 static const WCHAR
*stretchnamesW
[] = {
3851 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3856 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3862 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3865 /* resolved style name */
3867 font_name_token_to_str(&style_name
, styleW
);
3868 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3870 /* use predefined names */
3872 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3873 strcpyW(styleW
, italicW
);
3875 strcpyW(styleW
, obliqueW
);
3878 /* use Regular match if it was found initially */
3879 if (!*weightW
&& !*stretchW
&& !*styleW
)
3880 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3884 strcpyW(faceW
, stretchW
);
3887 strcatW(faceW
, spaceW
);
3888 strcatW(faceW
, weightW
);
3892 strcatW(faceW
, spaceW
);
3893 strcatW(faceW
, styleW
);
3897 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3901 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3903 static const float width_axis_values
[] =
3905 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3906 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
3907 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
3908 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
3909 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
3910 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
3911 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
3912 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
3913 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
3914 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
3917 struct file_stream_desc stream_desc
;
3918 struct dwrite_font_props props
;
3919 struct dwrite_font_data
*data
;
3920 WCHAR familyW
[255], faceW
[255];
3925 data
= heap_alloc_zero(sizeof(*data
));
3927 return E_OUTOFMEMORY
;
3930 data
->file
= desc
->files
[0];
3931 data
->face_index
= desc
->index
;
3932 data
->face_type
= desc
->face_type
;
3933 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3934 data
->bold_sim_tested
= 0;
3935 data
->oblique_sim_tested
= 0;
3936 IDWriteFontFile_AddRef(data
->file
);
3938 stream_desc
.stream
= desc
->stream
;
3939 stream_desc
.face_type
= desc
->face_type
;
3940 stream_desc
.face_index
= desc
->index
;
3941 opentype_get_font_properties(&stream_desc
, &props
);
3942 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3943 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3945 /* get family name from font file */
3946 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
3948 WARN("unable to get family name from font\n");
3949 release_font_data(data
);
3953 data
->style
= props
.style
;
3954 data
->stretch
= props
.stretch
;
3955 data
->weight
= props
.weight
;
3956 data
->panose
= props
.panose
;
3957 data
->fontsig
= props
.fontsig
;
3958 data
->lf
= props
.lf
;
3959 data
->flags
= props
.flags
;
3961 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
3962 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
3963 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3964 set_en_localizedstring(data
->family_names
, familyW
);
3965 set_en_localizedstring(data
->names
, faceW
);
3968 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3970 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
3971 data
->axis
[0].value
= props
.weight
;
3972 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
3973 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
3974 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
3975 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
3981 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3982 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3984 struct dwrite_font_data
*data
;
3988 data
= heap_alloc_zero(sizeof(*data
));
3990 return E_OUTOFMEMORY
;
3994 data
->simulations
|= sim
;
3995 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3996 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3997 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3998 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3999 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4001 IDWriteFontFile_AddRef(data
->file
);
4002 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4004 create_localizedstrings(&data
->names
);
4005 add_localizedstring(data
->names
, enusW
, facenameW
);
4007 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4013 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4015 struct dwrite_fontfamily_data
*data
;
4017 data
= heap_alloc_zero(sizeof(*data
));
4019 return E_OUTOFMEMORY
;
4022 data
->familyname
= familyname
;
4023 IDWriteLocalizedStrings_AddRef(familyname
);
4030 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4032 size_t i
, j
, heaviest
;
4034 for (i
= 0; i
< family
->count
; ++i
)
4036 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4039 if (family
->fonts
[i
]->bold_sim_tested
)
4042 family
->fonts
[i
]->bold_sim_tested
= 1;
4043 for (j
= i
; j
< family
->count
; ++j
)
4045 if (family
->fonts
[j
]->bold_sim_tested
)
4048 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4049 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4050 if (family
->fonts
[j
]->weight
> weight
) {
4051 weight
= family
->fonts
[j
]->weight
;
4054 family
->fonts
[j
]->bold_sim_tested
= 1;
4058 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4059 static const struct name_pattern weightsim_patterns
[] = {
4074 WCHAR facenameW
[255], initialW
[255];
4075 struct dwrite_font_data
*boldface
;
4078 /* add Bold simulation based on heaviest face data */
4080 /* Simulated face name should only contain Bold as weight term,
4081 so remove existing regular and weight terms. */
4082 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4083 facename_remove_regular_term(initialW
, -1);
4085 /* remove current weight pattern */
4086 fontname_tokenize(&tokens
, initialW
);
4087 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4088 fontname_tokens_to_str(&tokens
, facenameW
);
4090 /* Bold suffix for new name */
4092 strcatW(facenameW
, spaceW
);
4093 strcatW(facenameW
, boldW
);
4095 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4096 boldface
->bold_sim_tested
= 1;
4097 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4098 fontfamily_add_font(family
, boldface
);
4104 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4108 for (i
= 0; i
< family
->count
; ++i
)
4110 UINT32 regular
= ~0u, oblique
= ~0u;
4111 struct dwrite_font_data
*obliqueface
;
4112 WCHAR facenameW
[255];
4114 if (family
->fonts
[i
]->oblique_sim_tested
)
4117 family
->fonts
[i
]->oblique_sim_tested
= 1;
4118 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4120 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4123 /* find regular style with same weight/stretch values */
4124 for (j
= i
; j
< family
->count
; ++j
)
4126 if (family
->fonts
[j
]->oblique_sim_tested
)
4129 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4130 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4132 family
->fonts
[j
]->oblique_sim_tested
= 1;
4133 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4136 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4140 if (regular
!= ~0u && oblique
!= ~0u)
4144 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4148 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4152 /* add oblique simulation based on this regular face */
4154 /* remove regular term if any, append 'Oblique' */
4155 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4156 facename_remove_regular_term(facenameW
, -1);
4159 strcatW(facenameW
, spaceW
);
4160 strcatW(facenameW
, obliqueW
);
4162 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4163 obliqueface
->oblique_sim_tested
= 1;
4164 obliqueface
->lf
.lfItalic
= 1;
4165 fontfamily_add_font(family
, obliqueface
);
4170 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4171 const WCHAR
*replacement_name
)
4173 UINT32 i
= collection_find_family(collection
, replacement_name
);
4174 struct dwrite_fontfamily_data
*target
;
4175 IDWriteLocalizedStrings
*strings
;
4178 /* replacement does not exist */
4182 hr
= create_localizedstrings(&strings
);
4186 /* add a new family with target name, reuse font data from replacement */
4187 add_localizedstring(strings
, enusW
, target_name
);
4188 hr
= init_fontfamily_data(strings
, &target
);
4190 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4193 for (i
= 0; i
< replacement
->count
; ++i
)
4195 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4196 addref_font_data(replacement
->fonts
[i
]);
4199 fontcollection_add_family(collection
, target
);
4200 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4201 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4203 IDWriteLocalizedStrings_Release(strings
);
4207 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4208 system font collections. */
4209 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4211 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4216 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4219 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4224 max_namelen
++; /* returned value doesn't include room for '\0' */
4225 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4226 data
= heap_alloc(max_datalen
);
4228 datalen
= max_datalen
;
4229 namelen
= max_namelen
;
4230 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4231 if (collection_find_family(collection
, name
) == ~0u) {
4232 if (type
== REG_MULTI_SZ
) {
4233 WCHAR
*replacement
= data
;
4234 while (*replacement
) {
4235 if (fontcollection_add_replacement(collection
, name
, replacement
))
4237 replacement
+= strlenW(replacement
) + 1;
4240 else if (type
== REG_SZ
)
4241 fontcollection_add_replacement(collection
, name
, data
);
4244 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4246 datalen
= max_datalen
;
4247 namelen
= max_namelen
;
4255 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4256 IDWriteFontCollection3
**ret
)
4258 struct fontfile_enum
{
4260 IDWriteFontFile
*file
;
4262 struct fontfile_enum
*fileenum
, *fileenum2
;
4263 struct dwrite_fontcollection
*collection
;
4264 struct list scannedfiles
;
4265 BOOL current
= FALSE
;
4271 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4272 if (!collection
) return E_OUTOFMEMORY
;
4274 hr
= init_font_collection(collection
, is_system
);
4276 heap_free(collection
);
4280 *ret
= &collection
->IDWriteFontCollection3_iface
;
4282 TRACE("building font collection:\n");
4284 list_init(&scannedfiles
);
4285 while (hr
== S_OK
) {
4286 DWRITE_FONT_FACE_TYPE face_type
;
4287 DWRITE_FONT_FILE_TYPE file_type
;
4288 BOOL supported
, same
= FALSE
;
4289 IDWriteFontFileStream
*stream
;
4290 IDWriteFontFile
*file
;
4294 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4295 if (FAILED(hr
) || !current
)
4298 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4302 /* check if we've scanned this file already */
4303 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4304 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4309 IDWriteFontFile_Release(file
);
4313 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4314 IDWriteFontFile_Release(file
);
4318 /* Unsupported formats are skipped. */
4319 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4320 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4321 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4322 IDWriteFontFileStream_Release(stream
);
4323 IDWriteFontFile_Release(file
);
4328 /* add to scanned list */
4329 fileenum
= heap_alloc(sizeof(*fileenum
));
4330 fileenum
->file
= file
;
4331 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4333 for (i
= 0; i
< face_count
; ++i
)
4335 struct dwrite_font_data
*font_data
;
4336 struct fontface_desc desc
;
4340 desc
.factory
= factory
;
4341 desc
.face_type
= face_type
;
4343 desc
.stream
= stream
;
4344 desc
.files_number
= 1;
4346 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4347 desc
.font_data
= NULL
;
4349 /* Allocate an initialize new font data structure. */
4350 hr
= init_font_data(&desc
, &font_data
);
4353 /* move to next one */
4358 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4360 /* ignore dot named faces */
4361 if (familyW
[0] == '.')
4363 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4364 release_font_data(font_data
);
4368 index
= collection_find_family(collection
, familyW
);
4370 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4372 struct dwrite_fontfamily_data
*family_data
;
4374 /* create and init new family */
4375 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4377 /* add font to family, family - to collection */
4378 hr
= fontfamily_add_font(family_data
, font_data
);
4380 hr
= fontcollection_add_family(collection
, family_data
);
4383 release_fontfamily_data(family_data
);
4391 IDWriteFontFileStream_Release(stream
);
4394 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4395 IDWriteFontFile_Release(fileenum
->file
);
4396 list_remove(&fileenum
->entry
);
4397 heap_free(fileenum
);
4400 for (i
= 0; i
< collection
->count
; ++i
)
4402 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4403 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4407 fontcollection_add_replacements(collection
);
4409 collection
->factory
= factory
;
4410 IDWriteFactory7_AddRef(factory
);
4415 struct system_fontfile_enumerator
4417 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4420 IDWriteFactory7
*factory
;
4425 DWORD filename_size
;
4428 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4430 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4433 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4435 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4436 IDWriteFontFileEnumerator_AddRef(iface
);
4441 WARN("%s not implemented.\n", debugstr_guid(riid
));
4445 return E_NOINTERFACE
;
4448 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4450 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4451 return InterlockedIncrement(&enumerator
->ref
);
4454 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4456 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4457 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
4461 IDWriteFactory7_Release(enumerator
->factory
);
4462 RegCloseKey(enumerator
->hkey
);
4463 heap_free(enumerator
->filename
);
4464 heap_free(enumerator
);
4470 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4474 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4475 if (!strchrW(filename
, '\\')) {
4476 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4477 WCHAR fullpathW
[MAX_PATH
];
4479 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4480 strcatW(fullpathW
, fontsW
);
4481 strcatW(fullpathW
, filename
);
4483 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4486 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4491 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4493 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4497 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4500 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4503 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4505 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4506 WCHAR name_buf
[256], *name
= name_buf
;
4507 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4512 enumerator
->index
++;
4514 /* iterate until we find next string value */
4517 name_count
= max_name_count
;
4518 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4520 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4521 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4522 if (r
== ERROR_MORE_DATA
) {
4523 if (name_count
>= max_name_count
) {
4524 if (name
!= name_buf
) heap_free(name
);
4525 max_name_count
*= 2;
4526 name
= heap_alloc(max_name_count
* sizeof(*name
));
4527 if (!name
) return E_OUTOFMEMORY
;
4529 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4530 heap_free(enumerator
->filename
);
4531 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4532 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4533 if (!enumerator
->filename
) {
4539 } while (r
== ERROR_MORE_DATA
);
4541 if (r
!= ERROR_SUCCESS
) {
4542 enumerator
->filename
[0] = 0;
4545 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4546 if (type
== REG_SZ
&& *name
!= '@') {
4550 enumerator
->index
++;
4552 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4555 if (name
!= name_buf
) heap_free(name
);
4559 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4561 systemfontfileenumerator_QueryInterface
,
4562 systemfontfileenumerator_AddRef
,
4563 systemfontfileenumerator_Release
,
4564 systemfontfileenumerator_MoveNext
,
4565 systemfontfileenumerator_GetCurrentFontFile
4568 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4570 struct system_fontfile_enumerator
*enumerator
;
4571 static const WCHAR fontslistW
[] = {
4572 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4573 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4574 'F','o','n','t','s',0
4579 enumerator
= heap_alloc(sizeof(*enumerator
));
4581 return E_OUTOFMEMORY
;
4583 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4584 enumerator
->ref
= 1;
4585 enumerator
->factory
= factory
;
4586 enumerator
->index
= -1;
4587 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4588 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4589 if (!enumerator
->filename
) {
4590 heap_free(enumerator
);
4591 return E_OUTOFMEMORY
;
4594 IDWriteFactory7_AddRef(factory
);
4596 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4598 ERR("failed to open fonts list key\n");
4599 IDWriteFactory7_Release(factory
);
4600 heap_free(enumerator
->filename
);
4601 heap_free(enumerator
);
4605 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4610 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4612 IDWriteFontFileEnumerator
*enumerator
;
4617 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4621 TRACE("building system font collection for factory %p\n", factory
);
4622 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4623 IDWriteFontFileEnumerator_Release(enumerator
);
4627 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4628 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4630 static const WCHAR defaultfontW
[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t','E','U','D','C','F','o','n','t',0};
4631 static const WCHAR emptyW
[] = {0};
4632 struct dwrite_fontfamily_data
*family_data
;
4633 IDWriteLocalizedStrings
*names
;
4634 DWRITE_FONT_FACE_TYPE face_type
;
4635 DWRITE_FONT_FILE_TYPE file_type
;
4636 IDWriteFontFileStream
*stream
;
4637 IDWriteFontFile
*file
;
4638 UINT32 face_count
, i
;
4642 /* create font file from this path */
4643 hr
= create_local_file_reference(factory
, pathW
, &file
);
4647 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4648 IDWriteFontFile_Release(file
);
4652 /* Unsupported formats are skipped. */
4653 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4654 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4655 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4656 IDWriteFontFileStream_Release(stream
);
4657 IDWriteFontFile_Release(file
);
4661 /* create and init new family */
4663 /* Family names are added for non-specific locale, represented with empty string.
4664 Default family appears with empty family name. */
4665 create_localizedstrings(&names
);
4666 if (!strcmpiW(keynameW
, defaultfontW
))
4667 add_localizedstring(names
, emptyW
, emptyW
);
4669 add_localizedstring(names
, emptyW
, keynameW
);
4671 hr
= init_fontfamily_data(names
, &family_data
);
4672 IDWriteLocalizedStrings_Release(names
);
4674 IDWriteFontFile_Release(file
);
4678 /* fill with faces */
4679 for (i
= 0; i
< face_count
; i
++) {
4680 struct dwrite_font_data
*font_data
;
4681 struct fontface_desc desc
;
4683 /* alloc and init new font data structure */
4684 desc
.factory
= factory
;
4685 desc
.face_type
= face_type
;
4688 desc
.stream
= stream
;
4689 desc
.files_number
= 1;
4690 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4691 desc
.font_data
= NULL
;
4693 hr
= init_font_data(&desc
, &font_data
);
4697 /* add font to family */
4698 hr
= fontfamily_add_font(family_data
, font_data
);
4700 release_font_data(font_data
);
4703 /* add family to collection */
4704 hr
= fontcollection_add_family(collection
, family_data
);
4706 release_fontfamily_data(family_data
);
4707 IDWriteFontFileStream_Release(stream
);
4708 IDWriteFontFile_Release(file
);
4713 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4715 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4716 struct dwrite_fontcollection
*collection
;
4717 static const WCHAR emptyW
[] = {0};
4718 WCHAR eudckeypathW
[16];
4726 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4730 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4731 if (!collection
) return E_OUTOFMEMORY
;
4733 hr
= init_font_collection(collection
, FALSE
);
4735 heap_free(collection
);
4739 *ret
= &collection
->IDWriteFontCollection3_iface
;
4740 collection
->factory
= factory
;
4741 IDWriteFactory7_AddRef(factory
);
4743 /* return empty collection if EUDC fonts are not configured */
4744 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4745 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4748 retval
= ERROR_SUCCESS
;
4750 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4751 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4752 DWORD type
, path_len
, name_len
;
4754 path_len
= ARRAY_SIZE(pathW
);
4755 name_len
= ARRAY_SIZE(keynameW
);
4756 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4757 if (retval
|| type
!= REG_SZ
)
4760 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4762 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4764 RegCloseKey(eudckey
);
4766 /* try to add global default if not defined for specific codepage */
4768 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4770 if (FAILED(hr
) || !exists
) {
4771 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4772 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4774 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4777 /* EUDC collection offers simulated faces too */
4778 for (i
= 0; i
< collection
->count
; ++i
)
4780 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4781 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4787 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4789 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4791 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4793 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4796 IDWriteFontFile_AddRef(iface
);
4800 WARN("%s not implemented.\n", debugstr_guid(riid
));
4803 return E_NOINTERFACE
;
4806 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4808 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4809 ULONG ref
= InterlockedIncrement(&This
->ref
);
4810 TRACE("(%p)->(%d)\n", This
, ref
);
4814 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4816 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4817 ULONG ref
= InterlockedDecrement(&This
->ref
);
4819 TRACE("(%p)->(%d)\n", This
, ref
);
4823 IDWriteFontFileLoader_Release(This
->loader
);
4824 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4825 heap_free(This
->reference_key
);
4832 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4834 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4835 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4836 *fontFileReferenceKey
= This
->reference_key
;
4837 *fontFileReferenceKeySize
= This
->key_size
;
4842 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4844 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4845 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4846 *fontFileLoader
= This
->loader
;
4847 IDWriteFontFileLoader_AddRef(This
->loader
);
4852 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4853 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4855 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4856 IDWriteFontFileStream
*stream
;
4859 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, is_supported
, file_type
, face_type
, face_count
);
4861 *is_supported
= FALSE
;
4862 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4864 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4867 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4871 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4873 /* TODO: Further Analysis */
4874 IDWriteFontFileStream_Release(stream
);
4878 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4879 dwritefontfile_QueryInterface
,
4880 dwritefontfile_AddRef
,
4881 dwritefontfile_Release
,
4882 dwritefontfile_GetReferenceKey
,
4883 dwritefontfile_GetLoader
,
4884 dwritefontfile_Analyze
,
4887 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4888 IDWriteFontFile
**ret
)
4890 struct dwrite_fontfile
*file
;
4895 file
= heap_alloc(sizeof(*file
));
4896 key
= heap_alloc(key_size
);
4897 if (!file
|| !key
) {
4900 return E_OUTOFMEMORY
;
4903 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4905 IDWriteFontFileLoader_AddRef(loader
);
4906 file
->loader
= loader
;
4907 file
->stream
= NULL
;
4908 file
->reference_key
= key
;
4909 memcpy(file
->reference_key
, reference_key
, key_size
);
4910 file
->key_size
= key_size
;
4912 *ret
= &file
->IDWriteFontFile_iface
;
4917 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
4919 struct file_stream_desc stream_desc
;
4920 struct dwrite_font_data
*font_data
;
4921 struct dwrite_fontface
*fontface
;
4927 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4929 return E_OUTOFMEMORY
;
4931 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4932 if (!fontface
->files
) {
4933 heap_free(fontface
);
4934 return E_OUTOFMEMORY
;
4937 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
4938 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
4939 fontface
->refcount
= 1;
4940 fontface
->type
= desc
->face_type
;
4941 fontface
->file_count
= desc
->files_number
;
4942 fontface
->vdmx
.exists
= TRUE
;
4943 fontface
->gasp
.exists
= TRUE
;
4944 fontface
->cpal
.exists
= TRUE
;
4945 fontface
->colr
.exists
= TRUE
;
4946 fontface
->index
= desc
->index
;
4947 fontface
->simulations
= desc
->simulations
;
4948 fontface
->factory
= desc
->factory
;
4949 IDWriteFactory7_AddRef(fontface
->factory
);
4951 for (i
= 0; i
< fontface
->file_count
; i
++) {
4952 fontface
->files
[i
] = desc
->files
[i
];
4953 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4955 fontface
->stream
= desc
->stream
;
4956 IDWriteFontFileStream_AddRef(fontface
->stream
);
4958 stream_desc
.stream
= fontface
->stream
;
4959 stream_desc
.face_type
= desc
->face_type
;
4960 stream_desc
.face_index
= desc
->index
;
4961 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4962 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
4963 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4964 /* TODO: test what happens if caret is already slanted */
4965 if (fontface
->caret
.slopeRise
== 1) {
4966 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4967 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4971 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace5_iface
))
4972 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4973 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace5_iface
))
4974 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4975 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
4977 /* Font properties are reused from font object when 'normal' face creation path is used:
4978 collection -> family -> matching font -> fontface.
4980 If face is created directly from factory we have to go through properties resolution.
4982 if (desc
->font_data
)
4984 font_data
= desc
->font_data
;
4985 addref_font_data(font_data
);
4989 hr
= init_font_data(desc
, &font_data
);
4992 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
4997 fontface
->weight
= font_data
->weight
;
4998 fontface
->style
= font_data
->style
;
4999 fontface
->stretch
= font_data
->stretch
;
5000 fontface
->panose
= font_data
->panose
;
5001 fontface
->fontsig
= font_data
->fontsig
;
5002 fontface
->lf
= font_data
->lf
;
5003 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5004 fontface
->names
= font_data
->names
;
5005 if (fontface
->names
)
5006 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5007 fontface
->family_names
= font_data
->family_names
;
5008 if (fontface
->family_names
)
5009 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5010 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5011 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5013 if (fontface
->info_strings
[i
])
5014 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5016 fontface
->cmap
.stream
= fontface
->stream
;
5017 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5018 release_font_data(font_data
);
5020 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5022 *ret
= &fontface
->IDWriteFontFace5_iface
;
5027 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5034 struct local_cached_stream
5037 IDWriteFontFileStream
*stream
;
5038 struct local_refkey
*key
;
5042 struct dwrite_localfontfilestream
5044 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5047 struct local_cached_stream
*entry
;
5048 const void *file_ptr
;
5052 struct dwrite_localfontfileloader
{
5053 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5056 struct list streams
;
5057 CRITICAL_SECTION cs
;
5060 static struct dwrite_localfontfileloader local_fontfile_loader
;
5062 struct dwrite_inmemory_stream_data
5070 struct dwrite_inmemory_filestream
5072 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5075 struct dwrite_inmemory_stream_data
*data
;
5078 struct dwrite_inmemory_fileloader
5080 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5083 struct dwrite_inmemory_stream_data
**streams
;
5088 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5090 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5093 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5095 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5098 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5100 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5103 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5105 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5108 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5110 if (InterlockedDecrement(&stream
->ref
) == 0) {
5112 IUnknown_Release(stream
->owner
);
5114 heap_free(stream
->data
);
5119 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5121 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5123 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5125 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5126 IsEqualIID(riid
, &IID_IUnknown
))
5129 if (InterlockedIncrement(&This
->ref
) == 1) {
5130 InterlockedDecrement(&This
->ref
);
5137 WARN("%s not implemented.\n", debugstr_guid(riid
));
5140 return E_NOINTERFACE
;
5143 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5145 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5146 ULONG ref
= InterlockedIncrement(&This
->ref
);
5147 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
5151 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5153 list_remove(&stream
->entry
);
5154 heap_free(stream
->key
);
5158 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5160 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5161 ULONG ref
= InterlockedDecrement(&This
->ref
);
5163 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
5166 UnmapViewOfFile(This
->file_ptr
);
5168 EnterCriticalSection(&local_fontfile_loader
.cs
);
5169 release_cached_stream(This
->entry
);
5170 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5178 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5179 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5181 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5183 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
5184 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5186 *fragment_context
= NULL
;
5188 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
5189 *fragment_start
= NULL
;
5193 *fragment_start
= (char*)This
->file_ptr
+ offset
;
5197 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5199 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5200 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
5203 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5205 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5206 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
5211 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5213 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5216 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
5218 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
5219 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
5220 *last_writetime
= li
.QuadPart
;
5225 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5227 localfontfilestream_QueryInterface
,
5228 localfontfilestream_AddRef
,
5229 localfontfilestream_Release
,
5230 localfontfilestream_ReadFileFragment
,
5231 localfontfilestream_ReleaseFileFragment
,
5232 localfontfilestream_GetFileSize
,
5233 localfontfilestream_GetLastWriteTime
5236 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
5238 struct dwrite_localfontfilestream
*This
;
5242 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
5244 return E_OUTOFMEMORY
;
5246 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5249 This
->file_ptr
= file_ptr
;
5251 This
->entry
= entry
;
5253 *ret
= &This
->IDWriteFontFileStream_iface
;
5257 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5259 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5261 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5263 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5264 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5265 IsEqualIID(riid
, &IID_IUnknown
))
5268 IDWriteLocalFontFileLoader_AddRef(iface
);
5272 WARN("%s not implemented.\n", debugstr_guid(riid
));
5275 return E_NOINTERFACE
;
5278 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5280 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5281 ULONG ref
= InterlockedIncrement(&This
->ref
);
5282 TRACE("(%p)->(%d)\n", This
, ref
);
5286 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5288 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5289 ULONG ref
= InterlockedDecrement(&This
->ref
);
5291 TRACE("(%p)->(%d)\n", This
, ref
);
5296 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5298 const struct local_refkey
*refkey
= key
;
5299 struct local_cached_stream
*stream
;
5300 IDWriteFontFileStream
*filestream
;
5301 HANDLE file
, mapping
;
5308 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5309 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5310 if (file
== INVALID_HANDLE_VALUE
) {
5311 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5315 GetFileSizeEx(file
, &size
);
5316 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5321 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5322 CloseHandle(mapping
);
5324 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5328 stream
= heap_alloc(sizeof(*stream
));
5330 UnmapViewOfFile(file_ptr
);
5331 return E_OUTOFMEMORY
;
5334 stream
->key
= heap_alloc(key_size
);
5336 UnmapViewOfFile(file_ptr
);
5338 return E_OUTOFMEMORY
;
5341 stream
->key_size
= key_size
;
5342 memcpy(stream
->key
, key
, key_size
);
5344 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5346 UnmapViewOfFile(file_ptr
);
5347 heap_free(stream
->key
);
5352 stream
->stream
= filestream
;
5359 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5360 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5362 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5363 const struct local_refkey
*refkey
= key
;
5364 struct local_cached_stream
*stream
;
5367 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, ret
);
5368 TRACE("name: %s\n", debugstr_w(refkey
->name
));
5370 EnterCriticalSection(&This
->cs
);
5374 /* search cache first */
5375 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
5376 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5377 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5382 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
) {
5383 list_add_head(&This
->streams
, &stream
->entry
);
5384 *ret
= stream
->stream
;
5387 LeaveCriticalSection(&This
->cs
);
5392 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
5394 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5395 const struct local_refkey
*refkey
= key
;
5397 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
5399 *length
= strlenW(refkey
->name
);
5403 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5405 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5406 const struct local_refkey
*refkey
= key
;
5408 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
5410 if (length
< strlenW(refkey
->name
))
5411 return E_INVALIDARG
;
5413 strcpyW(path
, refkey
->name
);
5417 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5418 UINT32 key_size
, FILETIME
*writetime
)
5420 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5421 const struct local_refkey
*refkey
= key
;
5423 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, writetime
);
5425 *writetime
= refkey
->writetime
;
5429 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
5430 localfontfileloader_QueryInterface
,
5431 localfontfileloader_AddRef
,
5432 localfontfileloader_Release
,
5433 localfontfileloader_CreateStreamFromKey
,
5434 localfontfileloader_GetFilePathLengthFromKey
,
5435 localfontfileloader_GetFilePathFromKey
,
5436 localfontfileloader_GetLastWriteTimeFromKey
5439 void init_local_fontfile_loader(void)
5441 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5442 local_fontfile_loader
.ref
= 1;
5443 list_init(&local_fontfile_loader
.streams
);
5444 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5445 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5448 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5450 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5453 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5455 struct local_refkey
*refkey
;
5458 return E_INVALIDARG
;
5460 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5463 refkey
= heap_alloc(*size
);
5465 return E_OUTOFMEMORY
;
5468 refkey
->writetime
= *writetime
;
5470 WIN32_FILE_ATTRIBUTE_DATA info
;
5472 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5473 refkey
->writetime
= info
.ftLastWriteTime
;
5475 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5477 strcpyW(refkey
->name
, path
);
5484 /* IDWriteGlyphRunAnalysis */
5485 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5487 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5489 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5491 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5492 IsEqualIID(riid
, &IID_IUnknown
))
5495 IDWriteGlyphRunAnalysis_AddRef(iface
);
5499 WARN("%s not implemented.\n", debugstr_guid(riid
));
5502 return E_NOINTERFACE
;
5505 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5507 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5508 ULONG ref
= InterlockedIncrement(&This
->ref
);
5509 TRACE("(%p)->(%u)\n", This
, ref
);
5513 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5515 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5516 ULONG ref
= InterlockedDecrement(&This
->ref
);
5518 TRACE("(%p)->(%u)\n", This
, ref
);
5521 if (This
->run
.fontFace
)
5522 IDWriteFontFace_Release(This
->run
.fontFace
);
5523 heap_free(This
->glyphs
);
5524 heap_free(This
->origins
);
5525 heap_free(This
->bitmap
);
5532 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5536 case DWRITE_RENDERING_MODE1_NATURAL
:
5537 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5538 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5545 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5547 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5550 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5552 struct dwrite_glyphbitmap glyph_bitmap
;
5553 IDWriteFontFace4
*fontface
;
5557 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5558 *bounds
= analysis
->bounds
;
5562 if (analysis
->run
.isSideways
)
5563 FIXME("sideways runs are not supported.\n");
5565 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5567 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5569 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5570 glyph_bitmap
.fontface
= fontface
;
5571 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5572 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5573 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5574 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5575 glyph_bitmap
.m
= &analysis
->m
;
5577 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5578 RECT
*bbox
= &glyph_bitmap
.bbox
;
5581 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5582 freetype_get_glyph_bbox(&glyph_bitmap
);
5584 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5585 (bbox
->bottom
- bbox
->top
);
5586 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5587 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5589 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5590 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5593 IDWriteFontFace4_Release(fontface
);
5595 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5596 *bounds
= analysis
->bounds
;
5599 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5601 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5603 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
5605 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5606 SetRectEmpty(bounds
);
5607 return E_INVALIDARG
;
5610 if (type
!= This
->texture_type
) {
5611 SetRectEmpty(bounds
);
5615 glyphrunanalysis_get_texturebounds(This
, bounds
);
5619 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5621 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5622 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5623 (runbounds
->left
- bounds
->left
) * 3;
5625 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5626 runbounds
->left
- bounds
->left
;
5629 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5631 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5632 struct dwrite_glyphbitmap glyph_bitmap
;
5633 IDWriteFontFace4
*fontface
;
5634 D2D_POINT_2F origin
;
5639 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5641 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5645 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5646 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5648 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5649 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5650 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5651 IDWriteFontFace4_Release(fontface
);
5652 return E_OUTOFMEMORY
;
5655 origin
.x
= origin
.y
= 0.0f
;
5657 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5658 glyph_bitmap
.fontface
= fontface
;
5659 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5660 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5661 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5662 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5663 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5664 glyph_bitmap
.m
= &analysis
->m
;
5665 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5666 IDWriteFontFace4_Release(fontface
);
5667 return E_OUTOFMEMORY
;
5670 bbox
= &glyph_bitmap
.bbox
;
5672 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5673 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5674 int x
, y
, width
, height
;
5677 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5678 freetype_get_glyph_bbox(&glyph_bitmap
);
5680 if (IsRectEmpty(bbox
))
5683 width
= bbox
->right
- bbox
->left
;
5684 height
= bbox
->bottom
- bbox
->top
;
5686 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5687 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5688 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5690 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5692 /* blit to analysis bitmap */
5693 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5696 /* convert 1bpp to 8bpp/24bpp */
5697 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5698 for (y
= 0; y
< height
; y
++) {
5699 for (x
= 0; x
< width
; x
++)
5700 if (src
[x
/ 8] & masks
[x
% 8])
5701 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5702 src
+= glyph_bitmap
.pitch
;
5703 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5707 for (y
= 0; y
< height
; y
++) {
5708 for (x
= 0; x
< width
; x
++)
5709 if (src
[x
/ 8] & masks
[x
% 8])
5710 dst
[x
] = DWRITE_ALPHA_MAX
;
5711 src
+= glyph_bitmap
.pitch
;
5712 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5717 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5718 for (y
= 0; y
< height
; y
++) {
5719 for (x
= 0; x
< width
; x
++)
5720 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5721 src
+= glyph_bitmap
.pitch
;
5722 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5726 for (y
= 0; y
< height
; y
++) {
5727 for (x
= 0; x
< width
; x
++)
5729 src
+= glyph_bitmap
.pitch
;
5730 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5735 heap_free(glyph_bitmap
.buf
);
5737 IDWriteFontFace4_Release(fontface
);
5739 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5741 /* we don't need this anymore */
5742 heap_free(analysis
->glyphs
);
5743 heap_free(analysis
->origins
);
5744 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5746 analysis
->glyphs
= NULL
;
5747 analysis
->origins
= NULL
;
5748 analysis
->run
.glyphIndices
= NULL
;
5749 analysis
->run
.fontFace
= NULL
;
5754 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5755 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5757 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5761 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5763 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5764 return E_INVALIDARG
;
5766 /* make sure buffer is large enough for requested texture type */
5767 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5768 if (This
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5771 if (size
< required
)
5772 return E_NOT_SUFFICIENT_BUFFER
;
5774 /* validate requested texture type */
5775 if (This
->texture_type
!= type
)
5776 return DWRITE_E_UNSUPPORTEDOPERATION
;
5778 memset(bitmap
, 0, size
);
5779 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5780 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5781 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5782 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5783 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5784 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5788 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5791 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5795 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5796 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5798 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5799 memcpy(dst
, src
, draw_width
);
5808 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5809 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5811 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5813 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5816 return E_INVALIDARG
;
5818 switch (This
->rendering_mode
)
5820 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5821 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5824 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5825 *gamma
= (FLOAT
)value
/ 1000.0f
;
5827 *cleartypelevel
= 1.0f
;
5830 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5831 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5833 case DWRITE_RENDERING_MODE1_ALIASED
:
5834 case DWRITE_RENDERING_MODE1_NATURAL
:
5835 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5836 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5837 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5838 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5847 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5848 glyphrunanalysis_QueryInterface
,
5849 glyphrunanalysis_AddRef
,
5850 glyphrunanalysis_Release
,
5851 glyphrunanalysis_GetAlphaTextureBounds
,
5852 glyphrunanalysis_CreateAlphaTexture
,
5853 glyphrunanalysis_GetAlphaBlendParams
5856 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5859 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5860 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5864 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5865 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5867 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5871 FIXME("Sideways mode is not supported.\n");
5873 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5875 switch (measuring_mode
)
5877 case DWRITE_MEASURING_MODE_NATURAL
:
5878 return (float)advance
* emsize
/ (float)upem
;
5879 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5880 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5881 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5883 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5888 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5890 struct dwrite_glyphrunanalysis
*analysis
;
5891 struct dwrite_fontface
*fontface
;
5892 D2D_POINT_2F origin
;
5898 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5899 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5900 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5901 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5902 return E_INVALIDARG
;
5904 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5905 return E_INVALIDARG
;
5907 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5908 return E_INVALIDARG
;
5910 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5911 return E_INVALIDARG
;
5913 analysis
= heap_alloc(sizeof(*analysis
));
5915 return E_OUTOFMEMORY
;
5917 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5919 analysis
->rendering_mode
= desc
->rendering_mode
;
5921 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5922 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5923 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5925 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5927 analysis
->flags
= 0;
5928 analysis
->bitmap
= NULL
;
5929 analysis
->max_glyph_bitmap_size
= 0;
5930 SetRectEmpty(&analysis
->bounds
);
5931 analysis
->run
= *desc
->run
;
5932 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5933 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
5934 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
5936 if (!analysis
->glyphs
|| !analysis
->origins
) {
5937 heap_free(analysis
->glyphs
);
5938 heap_free(analysis
->origins
);
5940 analysis
->glyphs
= NULL
;
5941 analysis
->origins
= NULL
;
5943 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5944 return E_OUTOFMEMORY
;
5947 /* check if transform is usable */
5948 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5949 analysis
->m
= *desc
->transform
;
5950 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5953 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5955 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5956 analysis
->run
.glyphAdvances
= NULL
;
5957 analysis
->run
.glyphOffsets
= NULL
;
5959 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5961 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5963 fontface
= unsafe_impl_from_IDWriteFontFace(desc
->run
->fontFace
);
5965 origin
.x
= desc
->origin
.x
;
5966 origin
.y
= desc
->origin
.y
;
5967 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
5971 /* Use nominal advances if not provided by caller. */
5972 if (desc
->run
->glyphAdvances
)
5973 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
];
5975 advance
= rtl_factor
* fontface_get_scaled_design_advance(fontface
, desc
->measuring_mode
,
5976 desc
->run
->fontEmSize
, 1.0f
, desc
->transform
, desc
->run
->glyphIndices
[i
], desc
->run
->isSideways
);
5978 analysis
->origins
[i
] = origin
;
5979 if (desc
->run
->bidiLevel
& 1)
5981 if (desc
->run
->isSideways
)
5982 analysis
->origins
[i
].y
+= advance
;
5984 analysis
->origins
[i
].x
+= advance
;
5987 /* Offsets are optional, appled to pre-transformed origin. */
5988 if (desc
->run
->glyphOffsets
) {
5989 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
;
5990 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
;
5992 if (desc
->run
->isSideways
) {
5993 analysis
->origins
[i
].x
+= ascenderoffset
;
5994 analysis
->origins
[i
].y
+= advanceoffset
;
5997 analysis
->origins
[i
].x
+= advanceoffset
;
5998 analysis
->origins
[i
].y
+= ascenderoffset
;
6002 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6003 transform_point(analysis
->origins
+ i
, &analysis
->m
);
6005 if (desc
->run
->isSideways
)
6006 origin
.y
+= advance
;
6008 origin
.x
+= advance
;
6011 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6015 /* IDWriteColorGlyphRunEnumerator1 */
6016 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6018 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6020 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6021 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6022 IsEqualIID(riid
, &IID_IUnknown
))
6025 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6029 WARN("%s not implemented.\n", debugstr_guid(riid
));
6032 return E_NOINTERFACE
;
6035 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6037 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6038 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6040 TRACE("%p, refcount %u.\n", iface
, refcount
);
6045 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6047 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6048 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6050 TRACE("%p, refcount %u.\n", iface
, refcount
);
6054 heap_free(glyphenum
->advances
);
6055 heap_free(glyphenum
->color_advances
);
6056 heap_free(glyphenum
->offsets
);
6057 heap_free(glyphenum
->color_offsets
);
6058 heap_free(glyphenum
->glyphindices
);
6059 heap_free(glyphenum
->glyphs
);
6060 if (glyphenum
->colr
.context
)
6061 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6062 IDWriteFontFace5_Release(glyphenum
->fontface
);
6063 heap_free(glyphenum
);
6069 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6071 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6072 FLOAT origin
= 0.0f
;
6078 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6082 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6084 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6085 FLOAT advance_adj
= 0.0f
;
6086 BOOL got_palette_index
;
6089 /* start with regular glyphs */
6090 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6091 UINT32 first_glyph
= 0;
6093 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6094 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6095 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6096 first_glyph
= min(first_glyph
, g
);
6099 glyphenum
->glyphindices
[g
] = 1;
6100 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6101 if (glyphenum
->color_offsets
)
6102 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6105 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6106 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6107 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6108 colorrun
->paletteIndex
= 0xffff;
6109 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6110 glyphenum
->has_regular_glyphs
= FALSE
;
6114 colorrun
->glyphRun
.glyphCount
= 0;
6115 got_palette_index
= FALSE
;
6119 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6121 glyphenum
->glyphindices
[g
] = 1;
6123 /* all glyph layers were returned */
6124 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6125 advance_adj
+= glyphenum
->advances
[g
];
6129 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6130 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6131 if (!got_palette_index
) {
6132 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6133 /* use foreground color or request one from the font */
6134 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6135 if (colorrun
->paletteIndex
!= 0xffff)
6137 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6138 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6140 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6141 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6143 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6144 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6145 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6146 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6147 got_palette_index
= TRUE
;
6150 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6151 /* offsets are relative to glyph origin, nothing to fix up */
6152 if (glyphenum
->color_offsets
)
6153 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6154 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6156 glyphenum
->color_advances
[index
-1] += advance_adj
;
6157 colorrun
->glyphRun
.glyphCount
++;
6161 advance_adj
+= glyphenum
->advances
[g
];
6164 /* reset last advance */
6165 if (colorrun
->glyphRun
.glyphCount
)
6166 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6168 return colorrun
->glyphRun
.glyphCount
> 0;
6171 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6173 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6175 TRACE("%p, %p.\n", iface
, has_run
);
6179 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6180 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6182 if (colorglyphenum_build_color_run(glyphenum
))
6185 glyphenum
->current_layer
++;
6188 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6193 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6194 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6196 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6199 return E_NOT_VALID_STATE
;
6202 *run
= &glyphenum
->colorrun
;
6206 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6207 DWRITE_COLOR_GLYPH_RUN
const **run
)
6209 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6211 TRACE("%p, %p.\n", iface
, run
);
6213 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6216 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6217 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6219 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6221 TRACE("%p, %p.\n", iface
, run
);
6223 return colorglyphenum_get_current_run(glyphenum
, run
);
6226 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6228 colorglyphenum_QueryInterface
,
6229 colorglyphenum_AddRef
,
6230 colorglyphenum_Release
,
6231 colorglyphenum_MoveNext
,
6232 colorglyphenum_GetCurrentRun
,
6233 colorglyphenum1_GetCurrentRun
,
6236 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6237 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6238 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6240 struct dwrite_colorglyphenum
*colorglyphenum
;
6241 BOOL colorfont
, has_colored_glyph
;
6242 struct dwrite_fontface
*fontface
;
6247 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6249 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6250 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6252 return DWRITE_E_NOCOLOR
;
6254 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6255 if (!colorglyphenum
)
6256 return E_OUTOFMEMORY
;
6258 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6259 colorglyphenum
->refcount
= 1;
6260 colorglyphenum
->origin_x
= originX
;
6261 colorglyphenum
->origin_y
= originY
;
6262 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6263 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6264 colorglyphenum
->glyphs
= NULL
;
6265 colorglyphenum
->run
= *run
;
6266 colorglyphenum
->run
.glyphIndices
= NULL
;
6267 colorglyphenum
->run
.glyphAdvances
= NULL
;
6268 colorglyphenum
->run
.glyphOffsets
= NULL
;
6269 colorglyphenum
->palette
= palette
;
6270 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6271 colorglyphenum
->colr
.exists
= TRUE
;
6272 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6273 colorglyphenum
->current_layer
= 0;
6274 colorglyphenum
->max_layer_num
= 0;
6276 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6278 has_colored_glyph
= FALSE
;
6279 colorglyphenum
->has_regular_glyphs
= FALSE
;
6280 for (i
= 0; i
< run
->glyphCount
; i
++) {
6281 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6282 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6283 has_colored_glyph
= TRUE
;
6285 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6286 colorglyphenum
->has_regular_glyphs
= TRUE
;
6289 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6290 is supposed to proceed normally, like if font had no color info at all. */
6291 if (!has_colored_glyph
) {
6292 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6293 return DWRITE_E_NOCOLOR
;
6296 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6297 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6298 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6299 if (run
->glyphOffsets
) {
6300 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6301 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6302 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6305 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6306 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6307 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6308 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6309 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6310 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6311 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6312 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6314 if (run
->glyphAdvances
)
6315 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6318 for (i
= 0; i
< run
->glyphCount
; ++i
)
6319 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6320 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6323 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6328 /* IDWriteFontFaceReference */
6329 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6331 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6333 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6334 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6335 IsEqualIID(riid
, &IID_IUnknown
))
6338 IDWriteFontFaceReference1_AddRef(iface
);
6342 WARN("%s not implemented.\n", debugstr_guid(riid
));
6346 return E_NOINTERFACE
;
6349 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6351 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6352 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6354 TRACE("%p, refcount %u.\n", iface
, refcount
);
6359 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6361 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6362 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6364 TRACE("%p, refcount %u.\n", iface
, refcount
);
6368 IDWriteFontFile_Release(reference
->file
);
6369 IDWriteFactory7_Release(reference
->factory
);
6370 heap_free(reference
->axis_values
);
6371 heap_free(reference
);
6377 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6379 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6381 TRACE("%p, %p.\n", iface
, fontface
);
6383 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6386 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6387 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6389 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6390 DWRITE_FONT_FILE_TYPE file_type
;
6391 DWRITE_FONT_FACE_TYPE face_type
;
6392 IDWriteFontFace
*fontface
;
6397 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6399 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6403 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6404 simulations
, &fontface
);
6407 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6408 IDWriteFontFace_Release(fontface
);
6414 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6416 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6417 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6420 TRACE("%p, %p.\n", iface
, ref
);
6422 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6423 reference
->simulations
== other
->simulations
;
6424 if (reference
->axis_values_count
)
6426 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6427 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6433 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6435 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6437 TRACE("%p.\n", iface
);
6439 return reference
->index
;
6442 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6444 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6446 TRACE("%p.\n", iface
);
6448 return reference
->simulations
;
6451 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6453 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6454 IDWriteFontFileLoader
*loader
;
6459 TRACE("%p, %p.\n", iface
, file
);
6461 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6465 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6469 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6470 IDWriteFontFileLoader_Release(loader
);
6475 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6477 FIXME("%p.\n", iface
);
6482 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6484 FIXME("%p.\n", iface
);
6489 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6491 FIXME("%p, %p.\n", iface
, writetime
);
6496 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6498 FIXME("%p.\n", iface
);
6500 return DWRITE_LOCALITY_LOCAL
;
6503 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6505 FIXME("%p.\n", iface
);
6510 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6511 WCHAR
const *chars
, UINT32 count
)
6513 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6518 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6519 UINT16
const *glyphs
, UINT32 count
)
6521 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6526 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6527 UINT64 offset
, UINT64 size
)
6529 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6534 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6536 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6537 IDWriteFontFace3
*fontface3
;
6540 TRACE("%p, %p.\n", iface
, fontface
);
6542 /* FIXME: created instance should likely respect given axis. */
6543 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6546 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6547 IDWriteFontFace3_Release(fontface3
);
6553 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6555 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6557 TRACE("%p.\n", iface
);
6559 return reference
->axis_values_count
;
6562 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6563 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6565 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6567 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6569 if (value_count
< reference
->axis_values_count
)
6570 return E_NOT_SUFFICIENT_BUFFER
;
6572 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6577 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6579 fontfacereference_QueryInterface
,
6580 fontfacereference_AddRef
,
6581 fontfacereference_Release
,
6582 fontfacereference_CreateFontFace
,
6583 fontfacereference_CreateFontFaceWithSimulations
,
6584 fontfacereference_Equals
,
6585 fontfacereference_GetFontFaceIndex
,
6586 fontfacereference_GetSimulations
,
6587 fontfacereference_GetFontFile
,
6588 fontfacereference_GetLocalFileSize
,
6589 fontfacereference_GetFileSize
,
6590 fontfacereference_GetFileTime
,
6591 fontfacereference_GetLocality
,
6592 fontfacereference_EnqueueFontDownloadRequest
,
6593 fontfacereference_EnqueueCharacterDownloadRequest
,
6594 fontfacereference_EnqueueGlyphDownloadRequest
,
6595 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6596 fontfacereference1_CreateFontFace
,
6597 fontfacereference1_GetFontAxisValueCount
,
6598 fontfacereference1_GetFontAxisValues
,
6601 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6602 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6603 IDWriteFontFaceReference1
**ret
)
6605 struct dwrite_fontfacereference
*object
;
6609 if (!is_simulation_valid(simulations
))
6610 return E_INVALIDARG
;
6612 object
= heap_alloc_zero(sizeof(*object
));
6614 return E_OUTOFMEMORY
;
6616 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6617 object
->refcount
= 1;
6619 object
->factory
= factory
;
6620 IDWriteFactory7_AddRef(object
->factory
);
6621 object
->file
= file
;
6622 IDWriteFontFile_AddRef(object
->file
);
6623 object
->index
= index
;
6624 object
->simulations
= simulations
;
6625 if (axis_values_count
)
6627 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6629 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6630 return E_OUTOFMEMORY
;
6632 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6633 object
->axis_values_count
= axis_values_count
;
6636 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6641 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6643 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6645 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6647 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6649 IDWriteFontFileStream_AddRef(iface
);
6655 WARN("%s not implemented.\n", debugstr_guid(riid
));
6656 return E_NOINTERFACE
;
6659 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6661 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6662 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6663 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6667 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6669 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6670 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6672 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6675 release_inmemory_stream(stream
->data
);
6682 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6683 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6685 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6687 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6688 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6690 *fragment_context
= NULL
;
6692 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6693 *fragment_start
= NULL
;
6697 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6701 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6703 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6705 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6708 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6710 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6712 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6714 *size
= stream
->data
->size
;
6719 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6721 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6723 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6725 *last_writetime
= 0;
6730 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6731 inmemoryfilestream_QueryInterface
,
6732 inmemoryfilestream_AddRef
,
6733 inmemoryfilestream_Release
,
6734 inmemoryfilestream_ReadFileFragment
,
6735 inmemoryfilestream_ReleaseFileFragment
,
6736 inmemoryfilestream_GetFileSize
,
6737 inmemoryfilestream_GetLastWriteTime
,
6740 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6741 REFIID riid
, void **obj
)
6743 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6745 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6747 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6748 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6749 IsEqualIID(riid
, &IID_IUnknown
))
6752 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6756 WARN("%s not implemented.\n", debugstr_guid(riid
));
6760 return E_NOINTERFACE
;
6763 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6765 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6766 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6767 TRACE("(%p)->(%u)\n", loader
, ref
);
6771 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6773 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6774 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6777 TRACE("(%p)->(%u)\n", loader
, ref
);
6780 for (i
= 0; i
< loader
->count
; ++i
)
6781 release_inmemory_stream(loader
->streams
[i
]);
6782 heap_free(loader
->streams
);
6789 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6790 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6792 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6793 struct dwrite_inmemory_filestream
*stream
;
6796 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6800 if (key_size
!= sizeof(DWORD
))
6801 return E_INVALIDARG
;
6803 index
= *(DWORD
*)key
;
6805 if (index
>= loader
->count
)
6806 return E_INVALIDARG
;
6808 if (!(stream
= heap_alloc(sizeof(*stream
))))
6809 return E_OUTOFMEMORY
;
6811 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6813 stream
->data
= loader
->streams
[index
];
6814 InterlockedIncrement(&stream
->data
->ref
);
6816 *ret
= &stream
->IDWriteFontFileStream_iface
;
6821 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6822 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6824 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6825 struct dwrite_inmemory_stream_data
*stream
;
6828 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6832 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6833 return E_OUTOFMEMORY
;
6835 if (!(stream
= heap_alloc(sizeof(*stream
))))
6836 return E_OUTOFMEMORY
;
6839 stream
->size
= data_size
;
6840 stream
->owner
= owner
;
6841 if (stream
->owner
) {
6842 IUnknown_AddRef(stream
->owner
);
6843 stream
->data
= (void *)data
;
6846 if (!(stream
->data
= heap_alloc(data_size
))) {
6848 return E_OUTOFMEMORY
;
6850 memcpy(stream
->data
, data
, data_size
);
6853 key
= loader
->count
;
6854 loader
->streams
[loader
->count
++] = stream
;
6856 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6857 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6860 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6862 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6864 TRACE("%p.\n", iface
);
6866 return loader
->count
;
6869 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6871 inmemoryfontfileloader_QueryInterface
,
6872 inmemoryfontfileloader_AddRef
,
6873 inmemoryfontfileloader_Release
,
6874 inmemoryfontfileloader_CreateStreamFromKey
,
6875 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6876 inmemoryfontfileloader_GetFileCount
,
6879 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6881 struct dwrite_inmemory_fileloader
*loader
;
6885 loader
= heap_alloc_zero(sizeof(*loader
));
6887 return E_OUTOFMEMORY
;
6889 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6892 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6897 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6899 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6901 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6902 IsEqualIID(riid
, &IID_IUnknown
))
6905 IDWriteFontResource_AddRef(iface
);
6909 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6911 return E_NOINTERFACE
;
6914 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6916 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6917 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6919 TRACE("%p, refcount %u.\n", iface
, refcount
);
6924 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6926 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6927 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6929 TRACE("%p, refcount %u.\n", iface
, refcount
);
6933 IDWriteFactory7_Release(resource
->factory
);
6934 IDWriteFontFile_Release(resource
->file
);
6935 heap_free(resource
);
6941 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6943 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6945 TRACE("%p, %p.\n", iface
, fontfile
);
6947 *fontfile
= resource
->file
;
6948 IDWriteFontFile_AddRef(*fontfile
);
6953 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6955 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6957 TRACE("%p.\n", iface
);
6959 return resource
->face_index
;
6962 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6964 FIXME("%p.\n", iface
);
6969 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6970 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6972 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
6977 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
6978 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
6980 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
6985 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
6988 FIXME("%p, %u.\n", iface
, axis
);
6990 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
6993 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
6994 IDWriteLocalizedStrings
**names
)
6996 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7001 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7003 FIXME("%p, %u.\n", iface
, axis
);
7008 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7009 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7011 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7016 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7018 FIXME("%p.\n", iface
);
7023 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7024 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7025 IDWriteFontFace5
**fontface
)
7027 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7028 IDWriteFontFaceReference1
*reference
;
7031 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7033 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7034 simulations
, axis_values
, num_values
, &reference
);
7037 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7038 IDWriteFontFaceReference1_Release(reference
);
7044 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7045 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7046 IDWriteFontFaceReference1
**reference
)
7048 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7050 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7052 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7053 simulations
, axis_values
, num_values
, reference
);
7056 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7058 dwritefontresource_QueryInterface
,
7059 dwritefontresource_AddRef
,
7060 dwritefontresource_Release
,
7061 dwritefontresource_GetFontFile
,
7062 dwritefontresource_GetFontFaceIndex
,
7063 dwritefontresource_GetFontAxisCount
,
7064 dwritefontresource_GetDefaultFontAxisValues
,
7065 dwritefontresource_GetFontAxisRanges
,
7066 dwritefontresource_GetFontAxisAttributes
,
7067 dwritefontresource_GetAxisNames
,
7068 dwritefontresource_GetAxisValueNameCount
,
7069 dwritefontresource_GetAxisValueNames
,
7070 dwritefontresource_HasVariations
,
7071 dwritefontresource_CreateFontFace
,
7072 dwritefontresource_CreateFontFaceReference
,
7075 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7076 IDWriteFontResource
**ret
)
7078 struct dwrite_fontresource
*resource
;
7082 resource
= heap_alloc_zero(sizeof(*resource
));
7084 return E_OUTOFMEMORY
;
7086 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7087 resource
->refcount
= 1;
7088 resource
->face_index
= face_index
;
7089 resource
->file
= file
;
7090 IDWriteFontFile_AddRef(resource
->file
);
7091 resource
->factory
= factory
;
7092 IDWriteFactory7_AddRef(resource
->factory
);
7094 *ret
= &resource
->IDWriteFontResource_iface
;