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
;
155 IDWriteFont3 IDWriteFont3_iface
;
158 DWRITE_FONT_STYLE style
;
159 struct dwrite_font_data
*data
;
160 struct dwrite_fontfamily
*family
;
163 enum runanalysis_flags
{
164 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
165 RUNANALYSIS_BITMAP_READY
= 1 << 1,
166 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
169 struct dwrite_glyphrunanalysis
{
170 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
173 DWRITE_RENDERING_MODE1 rendering_mode
;
174 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
175 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
178 D2D_POINT_2F
*origins
;
183 UINT32 max_glyph_bitmap_size
;
186 struct dwrite_colorglyphenum
188 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
191 FLOAT origin_x
; /* original run origin */
194 IDWriteFontFace5
*fontface
; /* for convenience */
195 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
196 DWRITE_GLYPH_RUN run
; /* base run */
197 UINT32 palette
; /* palette index to get layer color from */
198 FLOAT
*advances
; /* original or measured advances for base glyphs */
199 FLOAT
*color_advances
; /* returned color run points to this */
200 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
201 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
202 UINT16
*glyphindices
; /* returned color run points to this */
203 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
204 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
205 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
206 UINT16 max_layer_num
; /* max number of layers for this run */
207 struct dwrite_fonttable colr
; /* used to access layers */
210 #define GLYPH_BLOCK_SHIFT 8
211 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
212 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
213 #define GLYPH_MAX 65536
215 struct dwrite_fontfile
{
216 IDWriteFontFile IDWriteFontFile_iface
;
219 IDWriteFontFileLoader
*loader
;
222 IDWriteFontFileStream
*stream
;
225 struct dwrite_fontfacereference
227 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
230 IDWriteFontFile
*file
;
233 DWRITE_FONT_AXIS_VALUE
*axis_values
;
234 UINT32 axis_values_count
;
235 IDWriteFactory7
*factory
;
238 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
240 struct dwrite_fontresource
242 IDWriteFontResource IDWriteFontResource_iface
;
245 IDWriteFontFile
*file
;
247 IDWriteFactory7
*factory
;
250 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
252 struct dwrite_fontface
*fontface
= context
;
255 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
256 size
, data_context
, &exists
)) || !exists
)
260 *data_context
= NULL
;
264 static void dwrite_release_font_table(void *context
, void *data_context
)
266 struct dwrite_fontface
*fontface
= context
;
267 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
270 static UINT16
dwrite_get_font_upem(void *context
)
272 struct dwrite_fontface
*fontface
= context
;
273 return fontface
->metrics
.designUnitsPerEm
;
276 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
278 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
279 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
282 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
284 struct dwrite_fontface
*fontface
= context
;
285 return !!dwritefontface_get_glyph(fontface
, codepoint
);
288 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
290 struct dwrite_fontface
*fontface
= context
;
291 return dwritefontface_get_glyph(fontface
, codepoint
);
294 static const struct shaping_font_ops dwrite_font_ops
=
296 dwrite_grab_font_table
,
297 dwrite_release_font_table
,
298 dwrite_get_font_upem
,
303 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
305 if (fontface
->shaping_cache
)
306 return fontface
->shaping_cache
;
308 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
311 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
313 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
316 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
318 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
321 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
323 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
326 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
328 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
330 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
333 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
335 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
338 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
340 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
343 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
345 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
348 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
350 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
353 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
355 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
358 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
360 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
363 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
365 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
368 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
370 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
373 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
375 static const DWRITE_GLYPH_METRICS nil
;
376 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
378 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
379 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
383 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
385 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
388 /* start new block */
389 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
391 return E_OUTOFMEMORY
;
394 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
398 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
402 if (table
->data
|| !table
->exists
)
405 table
->exists
= FALSE
;
406 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
408 if (FAILED(hr
) || !table
->exists
) {
409 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
416 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
417 struct dwrite_font_propvec
*vec
)
419 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
420 vec
->style
= style
* 7.0f
;
421 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
424 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
426 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
429 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
431 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
434 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
436 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
437 return &fontface
->vdmx
;
440 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
442 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
443 return &fontface
->gasp
;
446 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
448 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
449 return &fontface
->cpal
;
452 static void addref_font_data(struct dwrite_font_data
*data
)
454 InterlockedIncrement(&data
->ref
);
457 static void release_font_data(struct dwrite_font_data
*data
)
461 if (InterlockedDecrement(&data
->ref
) > 0)
464 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
466 if (data
->info_strings
[i
])
467 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
470 IDWriteLocalizedStrings_Release(data
->names
);
472 if (data
->family_names
)
473 IDWriteLocalizedStrings_Release(data
->family_names
);
475 dwrite_cmap_release(&data
->cmap
);
476 IDWriteFontFile_Release(data
->file
);
477 heap_free(data
->facename
);
481 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
485 if (InterlockedDecrement(&data
->refcount
) > 0)
488 for (i
= 0; i
< data
->count
; ++i
)
489 release_font_data(data
->fonts
[i
]);
490 heap_free(data
->fonts
);
491 IDWriteLocalizedStrings_Release(data
->familyname
);
495 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
497 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
498 fontface
->cached
= NULL
;
501 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
503 UINT32 left_key_size
, right_key_size
;
504 const void *left_key
, *right_key
;
510 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
514 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
518 if (left_key_size
!= right_key_size
)
521 return !memcmp(left_key
, right_key
, left_key_size
);
524 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
526 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
528 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
530 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
531 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
532 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
533 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
534 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
535 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
536 IsEqualIID(riid
, &IID_IUnknown
))
540 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
541 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
547 if (InterlockedIncrement(&fontface
->refcount
) == 1)
549 InterlockedDecrement(&fontface
->refcount
);
556 WARN("%s not implemented.\n", debugstr_guid(riid
));
558 return E_NOINTERFACE
;
561 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
563 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
564 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
566 TRACE("%p, refcount %u.\n", iface
, refcount
);
571 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
573 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
574 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
576 TRACE("%p, refcount %u.\n", iface
, refcount
);
582 if (fontface
->cached
)
584 factory_lock(fontface
->factory
);
585 list_remove(&fontface
->cached
->entry
);
586 factory_unlock(fontface
->factory
);
587 heap_free(fontface
->cached
);
589 release_scriptshaping_cache(fontface
->shaping_cache
);
590 if (fontface
->vdmx
.context
)
591 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
592 if (fontface
->gasp
.context
)
593 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
594 if (fontface
->cpal
.context
)
595 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
596 if (fontface
->colr
.context
)
597 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
598 for (i
= 0; i
< fontface
->file_count
; i
++)
600 if (fontface
->files
[i
])
601 IDWriteFontFile_Release(fontface
->files
[i
]);
603 if (fontface
->stream
)
604 IDWriteFontFileStream_Release(fontface
->stream
);
605 heap_free(fontface
->files
);
607 IDWriteLocalizedStrings_Release(fontface
->names
);
608 if (fontface
->family_names
)
609 IDWriteLocalizedStrings_Release(fontface
->family_names
);
610 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
612 if (fontface
->info_strings
[i
])
613 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
616 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
617 heap_free(fontface
->glyphs
[i
]);
619 freetype_notify_cacheremove(iface
);
621 dwrite_cmap_release(&fontface
->cmap
);
622 IDWriteFactory7_Release(fontface
->factory
);
629 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
631 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
633 TRACE("%p.\n", iface
);
635 return fontface
->type
;
638 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
639 IDWriteFontFile
**fontfiles
)
641 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
644 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
646 if (fontfiles
== NULL
)
648 *number_of_files
= fontface
->file_count
;
652 if (*number_of_files
< fontface
->file_count
)
655 for (i
= 0; i
< fontface
->file_count
; i
++)
657 IDWriteFontFile_AddRef(fontface
->files
[i
]);
658 fontfiles
[i
] = fontface
->files
[i
];
664 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
666 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
668 TRACE("%p.\n", iface
);
670 return fontface
->index
;
673 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
675 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
677 TRACE("%p.\n", iface
);
679 return fontface
->simulations
;
682 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
684 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
686 TRACE("%p.\n", iface
);
688 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
691 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
693 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
695 TRACE("%p, %p.\n", iface
, metrics
);
697 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
700 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
702 TRACE("%p.\n", iface
);
704 return freetype_get_glyphcount(iface
);
707 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
708 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
710 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
714 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
720 FIXME("sideways metrics are not supported.\n");
722 for (i
= 0; i
< glyph_count
; i
++) {
723 DWRITE_GLYPH_METRICS metrics
;
725 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
727 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
728 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
738 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
739 UINT32 count
, UINT16
*glyphs
)
741 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
744 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
751 memset(glyphs
, 0, count
* sizeof(*glyphs
));
755 for (i
= 0; i
< count
; ++i
)
756 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
761 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
762 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
764 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
765 struct file_stream_desc stream_desc
;
767 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
769 stream_desc
.stream
= fontface
->stream
;
770 stream_desc
.face_type
= fontface
->type
;
771 stream_desc
.face_index
= fontface
->index
;
772 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
775 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
777 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
779 TRACE("%p, %p.\n", iface
, table_context
);
781 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
784 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
785 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
786 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
788 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
789 count
, is_sideways
, is_rtl
, sink
);
791 if (!glyphs
|| !sink
)
795 FIXME("sideways mode is not supported.\n");
797 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
800 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
801 float ppem
, unsigned int gasp
)
803 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
807 case DWRITE_MEASURING_MODE_NATURAL
:
809 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
810 mode
= DWRITE_RENDERING_MODE_NATURAL
;
812 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
815 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
816 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
818 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
819 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
828 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
829 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
831 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
835 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
838 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
842 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
843 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
846 ppem
= emSize
* ppdip
;
848 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
849 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
853 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
854 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
858 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
859 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
861 DWRITE_FONT_METRICS1 metrics1
;
862 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
863 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
867 static inline int round_metric(FLOAT metric
)
869 return (int)floorf(metric
+ 0.5f
);
872 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
874 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
877 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
880 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
881 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
882 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
884 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
885 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
886 DWRITE_MEASURING_MODE mode
;
891 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
892 glyph_count
, metrics
, is_sideways
);
894 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
895 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
897 size
= emSize
* ppdip
;
898 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
899 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
901 for (i
= 0; i
< glyph_count
; i
++) {
902 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
903 DWRITE_GLYPH_METRICS design
;
906 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
910 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
912 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
914 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
916 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
917 SCALE_METRIC(leftSideBearing
);
918 SCALE_METRIC(rightSideBearing
);
919 SCALE_METRIC(topSideBearing
);
920 SCALE_METRIC(advanceHeight
);
921 SCALE_METRIC(bottomSideBearing
);
922 SCALE_METRIC(verticalOriginY
);
929 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
931 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
933 TRACE("%p, %p.\n", iface
, metrics
);
935 *metrics
= fontface
->metrics
;
938 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
939 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
941 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
942 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
943 UINT16 ascent
, descent
;
946 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
948 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
949 memset(metrics
, 0, sizeof(*metrics
));
953 em_size
*= pixels_per_dip
;
954 if (m
&& m
->m22
!= 0.0f
)
955 em_size
*= fabs(m
->m22
);
957 scale
= em_size
/ design
->designUnitsPerEm
;
958 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
960 ascent
= round_metric(design
->ascent
* scale
);
961 descent
= round_metric(design
->descent
* scale
);
964 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
965 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
966 metrics
->ascent
= round_metric(ascent
/ scale
);
967 metrics
->descent
= round_metric(descent
/ scale
);
969 SCALE_METRIC(lineGap
);
970 SCALE_METRIC(capHeight
);
971 SCALE_METRIC(xHeight
);
972 SCALE_METRIC(underlinePosition
);
973 SCALE_METRIC(underlineThickness
);
974 SCALE_METRIC(strikethroughPosition
);
975 SCALE_METRIC(strikethroughThickness
);
976 SCALE_METRIC(glyphBoxLeft
);
977 SCALE_METRIC(glyphBoxTop
);
978 SCALE_METRIC(glyphBoxRight
);
979 SCALE_METRIC(glyphBoxBottom
);
980 SCALE_METRIC(subscriptPositionX
);
981 SCALE_METRIC(subscriptPositionY
);
982 SCALE_METRIC(subscriptSizeX
);
983 SCALE_METRIC(subscriptSizeY
);
984 SCALE_METRIC(superscriptPositionX
);
985 SCALE_METRIC(superscriptPositionY
);
986 SCALE_METRIC(superscriptSizeX
);
987 SCALE_METRIC(superscriptSizeY
);
989 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
995 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
997 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
999 TRACE("%p, %p.\n", iface
, metrics
);
1001 *metrics
= fontface
->caret
;
1004 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1005 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1007 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1009 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1012 if (max_count
&& !ranges
)
1013 return E_INVALIDARG
;
1015 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1016 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1019 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1021 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1023 TRACE("%p.\n", iface
);
1025 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1028 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1029 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1031 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1036 FIXME("Sideways mode is not supported.\n");
1038 switch (measuring_mode
)
1040 case DWRITE_MEASURING_MODE_NATURAL
:
1041 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1042 glyph
, measuring_mode
, &has_contours
);
1044 advance
+= adjustment
;
1047 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1048 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1053 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1054 FIXME("Transform is not supported.\n");
1056 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1059 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1061 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1065 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1070 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1071 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1073 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1076 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1079 FIXME("sideways mode not supported\n");
1081 for (i
= 0; i
< glyph_count
; ++i
)
1083 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1084 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1090 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1091 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1092 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1094 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1095 DWRITE_MEASURING_MODE measuring_mode
;
1098 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1099 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1101 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1102 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1103 return E_INVALIDARG
;
1106 if (em_size
== 0.0f
) {
1107 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1111 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1112 for (i
= 0; i
< glyph_count
; ++i
)
1114 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1115 glyphs
[i
], is_sideways
);
1121 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1122 const UINT16
*indices
, INT32
*adjustments
)
1124 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1127 TRACE("%p, %u, %p, %p.\n", iface
, count
, indices
, adjustments
);
1129 if (!(indices
|| adjustments
) || !count
)
1130 return E_INVALIDARG
;
1132 if (!indices
|| count
== 1) {
1133 memset(adjustments
, 0, count
*sizeof(INT32
));
1134 return E_INVALIDARG
;
1137 if (!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
))
1139 memset(adjustments
, 0, count
*sizeof(INT32
));
1143 for (i
= 0; i
< count
-1; i
++)
1144 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1145 adjustments
[count
-1] = 0;
1150 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1152 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1154 TRACE("%p.\n", iface
);
1156 return !!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1159 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1160 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1161 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1163 DWRITE_GRID_FIT_MODE gridfitmode
;
1164 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1165 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1168 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1169 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1171 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1173 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1175 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1178 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1180 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1182 TRACE("%p.\n", iface
);
1184 return !!(fontface
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1187 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1189 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1191 TRACE("%p.\n", iface
);
1193 return !!(fontface
->flags
& FONT_IS_COLORED
);
1196 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1198 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1200 TRACE("%p.\n", iface
);
1202 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1205 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1207 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1209 TRACE("%p.\n", iface
);
1211 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1214 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1215 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1217 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1219 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1221 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1224 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1225 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1226 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1227 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1229 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1233 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1234 measuringmode
, params
, renderingmode
, gridfitmode
);
1237 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1240 FIXME("sideways mode not supported\n");
1242 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1244 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1245 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1247 IDWriteRenderingParams2
*params2
;
1250 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1252 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1253 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1254 IDWriteRenderingParams2_Release(params2
);
1257 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1260 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1262 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1264 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1265 if (emSize
>= emthreshold
)
1266 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1268 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1271 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1272 if (emSize
>= emthreshold
)
1273 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1274 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1275 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1277 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1278 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1284 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1285 IDWriteFontFaceReference
**reference
)
1287 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1289 TRACE("%p, %p.\n", iface
, reference
);
1291 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1292 IDWriteFontFaceReference_AddRef(*reference
);
1297 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1299 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1301 TRACE("%p, %p.\n", iface
, panose
);
1303 *panose
= fontface
->panose
;
1306 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1308 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1310 TRACE("%p.\n", iface
);
1312 return fontface
->weight
;
1315 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1317 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1319 TRACE("%p.\n", iface
);
1321 return fontface
->stretch
;
1324 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1326 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1328 TRACE("%p.\n", iface
);
1330 return fontface
->style
;
1333 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1335 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1337 TRACE("%p, %p.\n", iface
, names
);
1339 return clone_localizedstrings(fontface
->family_names
, names
);
1342 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1344 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1346 TRACE("%p, %p.\n", iface
, names
);
1348 return clone_localizedstrings(fontface
->names
, names
);
1351 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1352 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1353 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1360 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1361 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1366 if (!strings_cache
[stringid
])
1368 struct file_stream_desc desc
= *stream_desc
;
1371 hr
= get_filestream_from_file(file
, &desc
.stream
);
1373 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1375 if (!stream_desc
->stream
&& desc
.stream
)
1376 IDWriteFontFileStream_Release(desc
.stream
);
1379 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1381 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1389 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1390 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1392 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1393 struct file_stream_desc stream_desc
;
1395 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1397 stream_desc
.stream
= fontface
->stream
;
1398 stream_desc
.face_index
= fontface
->index
;
1399 stream_desc
.face_type
= fontface
->type
;
1400 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1403 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1405 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1407 TRACE("%p, %#x.\n", iface
, ch
);
1409 return !!dwritefontface_get_glyph(fontface
, ch
);
1412 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1413 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1414 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1416 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1420 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1421 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1424 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1427 FIXME("sideways mode not supported\n");
1429 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1431 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1432 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1434 IDWriteRenderingParams3
*params3
;
1437 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1439 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1440 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1441 IDWriteRenderingParams3_Release(params3
);
1444 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1447 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1449 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1451 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1452 if (emSize
>= emthreshold
)
1453 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1455 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1458 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1459 if (emSize
>= emthreshold
)
1460 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1461 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1462 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1464 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1465 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1471 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1473 FIXME("%p, %#x: stub\n", iface
, ch
);
1478 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1480 FIXME("%p, %u: stub\n", iface
, glyph
);
1485 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1486 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1488 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1493 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1494 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1496 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1501 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1502 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1504 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1509 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1511 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1513 TRACE("%p.\n", iface
);
1515 return fontface
->glyph_image_formats
;
1518 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1519 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1521 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1526 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1528 FIXME("%p, %p: stub\n", iface
, context
);
1531 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1533 FIXME("%p: stub\n", iface
);
1538 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1541 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1546 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1551 FIXME("%p: stub\n", iface
);
1556 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1558 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1560 TRACE("%p, %p.\n", iface
, resource
);
1562 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->files
[0], fontface
->index
, resource
);
1565 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1567 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1569 TRACE("%p, %p.\n", iface
, other
);
1571 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1574 /* TODO: add variations support */
1576 return fontface
->index
== other_face
->index
&&
1577 fontface
->simulations
== other_face
->simulations
&&
1578 is_same_fontfile(fontface
->files
[0], other_face
->files
[0]);
1581 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1583 dwritefontface_QueryInterface
,
1584 dwritefontface_AddRef
,
1585 dwritefontface_Release
,
1586 dwritefontface_GetType
,
1587 dwritefontface_GetFiles
,
1588 dwritefontface_GetIndex
,
1589 dwritefontface_GetSimulations
,
1590 dwritefontface_IsSymbolFont
,
1591 dwritefontface_GetMetrics
,
1592 dwritefontface_GetGlyphCount
,
1593 dwritefontface_GetDesignGlyphMetrics
,
1594 dwritefontface_GetGlyphIndices
,
1595 dwritefontface_TryGetFontTable
,
1596 dwritefontface_ReleaseFontTable
,
1597 dwritefontface_GetGlyphRunOutline
,
1598 dwritefontface_GetRecommendedRenderingMode
,
1599 dwritefontface_GetGdiCompatibleMetrics
,
1600 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1601 dwritefontface1_GetMetrics
,
1602 dwritefontface1_GetGdiCompatibleMetrics
,
1603 dwritefontface1_GetCaretMetrics
,
1604 dwritefontface1_GetUnicodeRanges
,
1605 dwritefontface1_IsMonospacedFont
,
1606 dwritefontface1_GetDesignGlyphAdvances
,
1607 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1608 dwritefontface1_GetKerningPairAdjustments
,
1609 dwritefontface1_HasKerningPairs
,
1610 dwritefontface1_GetRecommendedRenderingMode
,
1611 dwritefontface1_GetVerticalGlyphVariants
,
1612 dwritefontface1_HasVerticalGlyphVariants
,
1613 dwritefontface2_IsColorFont
,
1614 dwritefontface2_GetColorPaletteCount
,
1615 dwritefontface2_GetPaletteEntryCount
,
1616 dwritefontface2_GetPaletteEntries
,
1617 dwritefontface2_GetRecommendedRenderingMode
,
1618 dwritefontface3_GetFontFaceReference
,
1619 dwritefontface3_GetPanose
,
1620 dwritefontface3_GetWeight
,
1621 dwritefontface3_GetStretch
,
1622 dwritefontface3_GetStyle
,
1623 dwritefontface3_GetFamilyNames
,
1624 dwritefontface3_GetFaceNames
,
1625 dwritefontface3_GetInformationalStrings
,
1626 dwritefontface3_HasCharacter
,
1627 dwritefontface3_GetRecommendedRenderingMode
,
1628 dwritefontface3_IsCharacterLocal
,
1629 dwritefontface3_IsGlyphLocal
,
1630 dwritefontface3_AreCharactersLocal
,
1631 dwritefontface3_AreGlyphsLocal
,
1632 dwritefontface4_GetGlyphImageFormats_
,
1633 dwritefontface4_GetGlyphImageFormats
,
1634 dwritefontface4_GetGlyphImageData
,
1635 dwritefontface4_ReleaseGlyphImageData
,
1636 dwritefontface5_GetFontAxisValueCount
,
1637 dwritefontface5_GetFontAxisValues
,
1638 dwritefontface5_HasVariations
,
1639 dwritefontface5_GetFontResource
,
1640 dwritefontface5_Equals
,
1643 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1645 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1646 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1649 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1651 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1652 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1655 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1657 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1658 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1661 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1662 IDWriteFontFace3
**ret
)
1664 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1666 TRACE("%p, %p.\n", iface
, ret
);
1668 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1669 IDWriteFontFace3_AddRef(*ret
);
1674 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1675 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1677 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1678 DWRITE_FONT_FILE_TYPE file_type
;
1679 DWRITE_FONT_FACE_TYPE face_type
;
1680 IDWriteFontFace
*face
;
1685 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1687 hr
= IDWriteFontFile_Analyze(fontface
->files
[0], &is_supported
, &file_type
, &face_type
, &face_num
);
1691 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, fontface
->files
, fontface
->index
,
1692 simulations
, &face
);
1695 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1696 IDWriteFontFace_Release(face
);
1702 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1704 FIXME("%p, %p.\n", iface
, ref
);
1709 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1711 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1713 TRACE("%p.\n", iface
);
1715 return fontface
->index
;
1718 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1720 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1722 TRACE("%p.\n", iface
);
1724 return fontface
->simulations
;
1727 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1729 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1731 TRACE("%p, %p.\n", iface
, file
);
1733 *file
= fontface
->files
[0];
1734 IDWriteFontFile_AddRef(*file
);
1739 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1741 FIXME("%p.\n", iface
);
1746 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1748 FIXME("%p.\n", iface
);
1753 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1755 FIXME("%p, %p.\n", iface
, writetime
);
1760 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1762 FIXME("%p.\n", iface
);
1764 return DWRITE_LOCALITY_LOCAL
;
1767 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1769 FIXME("%p.\n", iface
);
1774 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1775 WCHAR
const *chars
, UINT32 count
)
1777 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1782 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1783 UINT16
const *glyphs
, UINT32 count
)
1785 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1790 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1791 UINT64 offset
, UINT64 size
)
1793 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1798 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1800 dwritefontface_reference_QueryInterface
,
1801 dwritefontface_reference_AddRef
,
1802 dwritefontface_reference_Release
,
1803 dwritefontface_reference_CreateFontFace
,
1804 dwritefontface_reference_CreateFontFaceWithSimulations
,
1805 dwritefontface_reference_Equals
,
1806 dwritefontface_reference_GetFontFaceIndex
,
1807 dwritefontface_reference_GetSimulations
,
1808 dwritefontface_reference_GetFontFile
,
1809 dwritefontface_reference_GetLocalFileSize
,
1810 dwritefontface_reference_GetFileSize
,
1811 dwritefontface_reference_GetFileTime
,
1812 dwritefontface_reference_GetLocality
,
1813 dwritefontface_reference_EnqueueFontDownloadRequest
,
1814 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1815 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1816 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1819 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1821 struct dwrite_font_data
*data
= font
->data
;
1822 struct fontface_desc desc
;
1823 struct list
*cached_list
;
1828 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1829 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1833 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1836 desc
.factory
= font
->family
->collection
->factory
;
1837 desc
.face_type
= data
->face_type
;
1838 desc
.files
= &data
->file
;
1839 desc
.files_number
= 1;
1840 desc
.index
= data
->face_index
;
1841 desc
.simulations
= data
->simulations
;
1842 desc
.font_data
= data
;
1843 hr
= create_fontface(&desc
, cached_list
, fontface
);
1845 IDWriteFontFileStream_Release(desc
.stream
);
1849 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1851 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1853 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1855 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1856 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1857 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1858 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1859 IsEqualIID(riid
, &IID_IUnknown
))
1862 IDWriteFont3_AddRef(iface
);
1866 WARN("%s not implemented.\n", debugstr_guid(riid
));
1869 return E_NOINTERFACE
;
1872 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1874 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1875 ULONG ref
= InterlockedIncrement(&This
->ref
);
1876 TRACE("(%p)->(%d)\n", This
, ref
);
1880 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1882 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1883 ULONG ref
= InterlockedDecrement(&This
->ref
);
1885 TRACE("(%p)->(%d)\n", This
, ref
);
1888 IDWriteFontFamily2_Release(&This
->family
->IDWriteFontFamily2_iface
);
1889 release_font_data(This
->data
);
1896 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1898 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1899 TRACE("(%p)->(%p)\n", This
, family
);
1901 *family
= (IDWriteFontFamily
*)This
->family
;
1902 IDWriteFontFamily_AddRef(*family
);
1906 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1908 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1909 TRACE("(%p)\n", This
);
1910 return This
->data
->weight
;
1913 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1915 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1916 TRACE("(%p)\n", This
);
1917 return This
->data
->stretch
;
1920 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1922 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1923 TRACE("(%p)\n", This
);
1927 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1929 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1931 TRACE("%p.\n", iface
);
1933 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
1936 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1938 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1940 TRACE("%p, %p.\n", iface
, names
);
1942 return clone_localizedstrings(font
->data
->names
, names
);
1945 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1946 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1948 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1949 struct dwrite_font_data
*data
= font
->data
;
1950 struct file_stream_desc stream_desc
;
1952 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
1954 /* Stream will be created if necessary. */
1955 stream_desc
.stream
= NULL
;
1956 stream_desc
.face_index
= data
->face_index
;
1957 stream_desc
.face_type
= data
->face_type
;
1958 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
1961 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1963 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1964 TRACE("(%p)\n", This
);
1965 return This
->data
->simulations
;
1968 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1970 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1972 TRACE("(%p)->(%p)\n", This
, metrics
);
1973 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1976 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
1979 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
1980 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
1984 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
1986 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1988 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
1990 *exists
= dwritefont_has_character(font
, ch
);
1995 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1997 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1999 TRACE("%p, %p.\n", iface
, fontface
);
2001 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2004 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2006 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
2007 TRACE("(%p)->(%p)\n", This
, metrics
);
2008 *metrics
= This
->data
->metrics
;
2011 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2013 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
2014 TRACE("(%p)->(%p)\n", This
, panose
);
2015 *panose
= This
->data
->panose
;
2018 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2021 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2023 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2026 if (max_count
&& !ranges
)
2027 return E_INVALIDARG
;
2029 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2030 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2033 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2035 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2037 TRACE("%p.\n", iface
);
2039 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2042 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2044 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2046 TRACE("%p.\n", iface
);
2048 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2051 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2053 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2055 TRACE("%p, %p.\n", iface
, fontface
);
2057 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2060 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2062 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2064 TRACE("%p, %p.\n", iface
, other
);
2066 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2069 return font
->data
->face_index
== other_font
->data
->face_index
2070 && font
->data
->simulations
== other_font
->data
->simulations
2071 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2074 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2076 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2078 TRACE("%p, %p.\n", iface
, reference
);
2080 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2081 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2082 (IDWriteFontFaceReference1
**)reference
);
2085 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2087 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2089 TRACE("%p, %#x.\n", iface
, ch
);
2091 return dwritefont_has_character(font
, ch
);
2094 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2096 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
2097 FIXME("(%p): stub\n", This
);
2098 return DWRITE_LOCALITY_LOCAL
;
2101 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2102 dwritefont_QueryInterface
,
2105 dwritefont_GetFontFamily
,
2106 dwritefont_GetWeight
,
2107 dwritefont_GetStretch
,
2108 dwritefont_GetStyle
,
2109 dwritefont_IsSymbolFont
,
2110 dwritefont_GetFaceNames
,
2111 dwritefont_GetInformationalStrings
,
2112 dwritefont_GetSimulations
,
2113 dwritefont_GetMetrics
,
2114 dwritefont_HasCharacter
,
2115 dwritefont_CreateFontFace
,
2116 dwritefont1_GetMetrics
,
2117 dwritefont1_GetPanose
,
2118 dwritefont1_GetUnicodeRanges
,
2119 dwritefont1_IsMonospacedFont
,
2120 dwritefont2_IsColorFont
,
2121 dwritefont3_CreateFontFace
,
2123 dwritefont3_GetFontFaceReference
,
2124 dwritefont3_HasCharacter
,
2125 dwritefont3_GetLocality
2128 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2132 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2133 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2136 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2140 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2141 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2144 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2148 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2150 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2151 IDWriteFontFaceReference1_iface
);
2154 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2156 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2157 *lf
= font
->data
->lf
;
2160 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2162 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2166 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2168 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2169 *fontsig
= font
->data
->fontsig
;
2173 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2175 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2176 *fontsig
= fontface
->fontsig
;
2180 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2182 struct dwrite_font
*This
;
2186 This
= heap_alloc(sizeof(*This
));
2188 return E_OUTOFMEMORY
;
2190 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2192 This
->family
= family
;
2193 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2194 This
->data
= family
->data
->fonts
[index
];
2195 This
->style
= This
->data
->style
;
2196 addref_font_data(This
->data
);
2198 *font
= &This
->IDWriteFont3_iface
;
2203 /* IDWriteFontList2 */
2204 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2206 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2208 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2209 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2210 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2211 IsEqualIID(riid
, &IID_IUnknown
))
2214 IDWriteFontList2_AddRef(iface
);
2218 WARN("%s not implemented.\n", debugstr_guid(riid
));
2221 return E_NOINTERFACE
;
2224 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2226 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2227 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2229 TRACE("%p, refcount %u.\n", iface
, refcount
);
2234 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2236 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2237 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2239 TRACE("%p, refcount %u.\n", iface
, refcount
);
2245 for (i
= 0; i
< fontlist
->font_count
; i
++)
2246 release_font_data(fontlist
->fonts
[i
]);
2247 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2248 heap_free(fontlist
->fonts
);
2249 heap_free(fontlist
);
2255 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2257 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2258 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2261 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2263 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2265 TRACE("%p.\n", iface
);
2267 return fontlist
->font_count
;
2270 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2272 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2274 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2278 if (fontlist
->font_count
== 0)
2281 if (index
>= fontlist
->font_count
)
2282 return E_INVALIDARG
;
2284 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2287 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2289 FIXME("%p, %u.\n", iface
, index
);
2291 return DWRITE_LOCALITY_LOCAL
;
2294 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2296 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2298 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2302 if (fontlist
->font_count
== 0)
2305 if (index
>= fontlist
->font_count
)
2308 return create_font(fontlist
->family
, index
, font
);
2311 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2312 IDWriteFontFaceReference
**reference
)
2317 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2321 hr
= IDWriteFontList2_GetFont(iface
, index
, &font
);
2325 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2326 IDWriteFont3_Release(font
);
2331 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2333 FIXME("%p, %p.\n", iface
, fontset
);
2338 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2340 dwritefontlist_QueryInterface
,
2341 dwritefontlist_AddRef
,
2342 dwritefontlist_Release
,
2343 dwritefontlist_GetFontCollection
,
2344 dwritefontlist_GetFontCount
,
2345 dwritefontlist_GetFont
,
2346 dwritefontlist1_GetFontLocality
,
2347 dwritefontlist1_GetFont
,
2348 dwritefontlist1_GetFontFaceReference
,
2349 dwritefontlist2_GetFontSet
,
2352 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2354 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2356 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2358 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2359 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2360 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2361 IsEqualIID(riid
, &IID_IUnknown
))
2365 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2366 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2367 IsEqualIID(riid
, &IID_IDWriteFontList
))
2369 *obj
= &family
->IDWriteFontList2_iface
;
2373 WARN("%s not implemented.\n", debugstr_guid(riid
));
2375 return E_NOINTERFACE
;
2378 IUnknown_AddRef((IUnknown
*)*obj
);
2382 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2384 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2385 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2387 TRACE("%p, %u.\n", iface
, refcount
);
2392 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2394 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2395 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2397 TRACE("%p, %u.\n", iface
, refcount
);
2401 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2402 release_fontfamily_data(family
->data
);
2409 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2411 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2413 TRACE("%p, %p.\n", iface
, collection
);
2415 *collection
= (IDWriteFontCollection
*)family
->collection
;
2416 IDWriteFontCollection_AddRef(*collection
);
2420 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2422 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2424 TRACE("%p.\n", iface
);
2426 return family
->data
->count
;
2429 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2431 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2433 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2437 if (!family
->data
->count
)
2440 if (index
>= family
->data
->count
)
2441 return E_INVALIDARG
;
2443 return create_font(family
, index
, (IDWriteFont3
**)font
);
2446 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2448 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2450 TRACE("%p, %p.\n", iface
, names
);
2452 return clone_localizedstrings(family
->data
->familyname
, names
);
2455 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2456 const struct dwrite_font_propvec
*req
)
2458 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2459 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2460 FLOAT cur_req_prod
, next_req_prod
;
2462 if (next_to_req
< cur_to_req
)
2465 if (next_to_req
> cur_to_req
)
2468 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2469 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2471 if (next_req_prod
> cur_req_prod
)
2474 if (next_req_prod
< cur_req_prod
)
2477 if (next
->stretch
> cur
->stretch
)
2479 if (next
->stretch
< cur
->stretch
)
2482 if (next
->style
> cur
->style
)
2484 if (next
->style
< cur
->style
)
2487 if (next
->weight
> cur
->weight
)
2489 if (next
->weight
< cur
->weight
)
2492 /* full match, no reason to prefer new variant */
2496 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2497 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2499 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2500 struct dwrite_font_propvec req
;
2503 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2505 if (!family
->data
->count
)
2508 return DWRITE_E_NOFONT
;
2511 init_font_prop_vec(weight
, stretch
, style
, &req
);
2514 for (i
= 1; i
< family
->data
->count
; ++i
)
2516 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2520 return create_font(family
, match
, (IDWriteFont3
**)font
);
2523 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2525 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2527 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2530 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2532 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2535 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2537 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2542 for (j
= 0; j
< b
; j
++) {
2543 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2544 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2545 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2546 fonts
->fonts
[j
+1] = s
;
2557 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2558 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2560 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2561 matching_filter_func func
= NULL
;
2562 struct dwrite_font_propvec req
;
2563 struct dwrite_fontlist
*fonts
;
2566 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2570 fonts
= heap_alloc(sizeof(*fonts
));
2572 return E_OUTOFMEMORY
;
2574 /* Allocate as many as family has, not all of them will be necessary used. */
2575 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2576 if (!fonts
->fonts
) {
2578 return E_OUTOFMEMORY
;
2581 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2582 fonts
->refcount
= 1;
2583 fonts
->family
= family
;
2584 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2585 fonts
->font_count
= 0;
2587 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2588 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2589 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2590 func
= is_font_acceptable_for_normal
;
2592 else /* requested oblique or italic */ {
2593 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2594 func
= is_font_acceptable_for_oblique_italic
;
2597 for (i
= 0; i
< family
->data
->count
; ++i
)
2599 if (!func
|| func(family
->data
->fonts
[i
]))
2601 fonts
->fonts
[fonts
->font_count
] = family
->data
->fonts
[i
];
2602 addref_font_data(family
->data
->fonts
[i
]);
2603 fonts
->font_count
++;
2607 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2608 init_font_prop_vec(weight
, stretch
, style
, &req
);
2609 matchingfonts_sort(fonts
, &req
);
2611 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2615 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2617 FIXME("%p, %u.\n", iface
, index
);
2619 return DWRITE_LOCALITY_LOCAL
;
2622 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2624 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2626 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2630 if (!family
->data
->count
)
2633 if (index
>= family
->data
->count
)
2636 return create_font(family
, index
, font
);
2639 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2640 IDWriteFontFaceReference
**reference
)
2642 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2643 const struct dwrite_font_data
*font
;
2645 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2649 if (index
>= family
->data
->count
)
2652 font
= family
->data
->fonts
[index
];
2653 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2654 font
->file
, font
->face_index
, font
->simulations
, reference
);
2657 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2658 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2660 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2665 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2667 FIXME("%p, %p.\n", iface
, fontset
);
2672 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2674 dwritefontfamily_QueryInterface
,
2675 dwritefontfamily_AddRef
,
2676 dwritefontfamily_Release
,
2677 dwritefontfamily_GetFontCollection
,
2678 dwritefontfamily_GetFontCount
,
2679 dwritefontfamily_GetFont
,
2680 dwritefontfamily_GetFamilyNames
,
2681 dwritefontfamily_GetFirstMatchingFont
,
2682 dwritefontfamily_GetMatchingFonts
,
2683 dwritefontfamily1_GetFontLocality
,
2684 dwritefontfamily1_GetFont
,
2685 dwritefontfamily1_GetFontFaceReference
,
2686 dwritefontfamily2_GetMatchingFonts
,
2687 dwritefontfamily2_GetFontSet
,
2690 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2692 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2693 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2696 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2698 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2699 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2702 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2704 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2705 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2708 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2709 IDWriteFontCollection
**collection
)
2711 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2712 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2715 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2717 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2718 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2721 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2723 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2724 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2727 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2729 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2730 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2733 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2735 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2736 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2739 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2740 IDWriteFontFaceReference
**reference
)
2742 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2743 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2746 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2748 FIXME("%p, %p.\n", iface
, fontset
);
2753 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2755 dwritefontfamilylist_QueryInterface
,
2756 dwritefontfamilylist_AddRef
,
2757 dwritefontfamilylist_Release
,
2758 dwritefontfamilylist_GetFontCollection
,
2759 dwritefontfamilylist_GetFontCount
,
2760 dwritefontfamilylist_GetFont
,
2761 dwritefontfamilylist1_GetFontLocality
,
2762 dwritefontfamilylist1_GetFont
,
2763 dwritefontfamilylist1_GetFontFaceReference
,
2764 dwritefontfamilylist2_GetFontSet
,
2767 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2768 struct dwrite_fontfamily
**family
)
2770 struct dwrite_fontfamily
*object
;
2774 object
= heap_alloc(sizeof(*object
));
2776 return E_OUTOFMEMORY
;
2778 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2779 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2780 object
->refcount
= 1;
2781 object
->collection
= collection
;
2782 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2783 object
->data
= collection
->family_data
[index
];
2784 InterlockedIncrement(&object
->data
->refcount
);
2791 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2794 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2797 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2799 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2801 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2803 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2804 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2805 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2806 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2807 IsEqualIID(riid
, &IID_IUnknown
))
2810 IDWriteFontCollection3_AddRef(iface
);
2816 if (IsEqualIID(riid
, &IID_issystemcollection
))
2819 WARN("%s not implemented.\n", debugstr_guid(riid
));
2821 return E_NOINTERFACE
;
2824 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2826 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2828 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2829 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2830 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2831 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2832 IsEqualIID(riid
, &IID_IUnknown
))
2835 IDWriteFontCollection3_AddRef(iface
);
2839 WARN("%s not implemented.\n", debugstr_guid(riid
));
2843 return E_NOINTERFACE
;
2846 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2848 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2849 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2851 TRACE("%p, refcount %d.\n", collection
, refcount
);
2856 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2858 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2859 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2862 TRACE("%p, refcount %d.\n", iface
, refcount
);
2866 factory_detach_fontcollection(collection
->factory
, iface
);
2867 for (i
= 0; i
< collection
->count
; ++i
)
2868 release_fontfamily_data(collection
->family_data
[i
]);
2869 heap_free(collection
->family_data
);
2870 heap_free(collection
);
2876 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2878 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2880 TRACE("%p.\n", iface
);
2882 return collection
->count
;
2885 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2886 IDWriteFontFamily
**ret
)
2888 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2889 struct dwrite_fontfamily
*family
;
2892 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2896 if (index
>= collection
->count
)
2899 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2900 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2905 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2909 for (i
= 0; i
< collection
->count
; ++i
)
2911 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2912 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2915 for (j
= 0; j
< count
; j
++) {
2917 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
2918 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2926 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
2927 UINT32
*index
, BOOL
*exists
)
2929 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2931 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
2933 *index
= collection_find_family(collection
, name
);
2934 *exists
= *index
!= ~0u;
2938 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
2941 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2942 struct dwrite_fontfamily
*family
;
2943 BOOL found_font
= FALSE
;
2944 IDWriteFontFile
*file
;
2945 UINT32 face_index
, count
;
2949 TRACE("%p, %p, %p.\n", iface
, face
, font
);
2954 return E_INVALIDARG
;
2957 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
2960 face_index
= IDWriteFontFace_GetIndex(face
);
2963 for (i
= 0; i
< collection
->count
; ++i
)
2965 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
2967 for (j
= 0; j
< family_data
->count
; ++j
)
2969 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2971 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2980 IDWriteFontFile_Release(file
);
2983 return DWRITE_E_NOFONT
;
2985 hr
= create_fontfamily(collection
, i
, &family
);
2989 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
2990 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
2994 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
2996 FIXME("%p, %p.\n", iface
, fontset
);
3001 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3002 IDWriteFontFamily1
**ret
)
3004 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3005 struct dwrite_fontfamily
*family
;
3008 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3012 if (index
>= collection
->count
)
3015 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3016 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3021 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3022 UINT32 index
, IDWriteFontFamily2
**ret
)
3024 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3025 struct dwrite_fontfamily
*family
;
3028 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3032 if (index
>= collection
->count
)
3035 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3036 *ret
= &family
->IDWriteFontFamily2_iface
;
3041 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3042 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3043 IDWriteFontList2
**fontlist
)
3045 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3050 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3052 FIXME("%p.\n", iface
);
3054 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3057 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3059 FIXME("%p, %p.\n", iface
, fontset
);
3064 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3066 FIXME("%p.\n", iface
);
3071 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3073 dwritefontcollection_QueryInterface
,
3074 dwritefontcollection_AddRef
,
3075 dwritefontcollection_Release
,
3076 dwritefontcollection_GetFontFamilyCount
,
3077 dwritefontcollection_GetFontFamily
,
3078 dwritefontcollection_FindFamilyName
,
3079 dwritefontcollection_GetFontFromFontFace
,
3080 dwritefontcollection1_GetFontSet
,
3081 dwritefontcollection1_GetFontFamily
,
3082 dwritefontcollection2_GetFontFamily
,
3083 dwritefontcollection2_GetMatchingFonts
,
3084 dwritefontcollection2_GetFontFamilyModel
,
3085 dwritefontcollection2_GetFontSet
,
3086 dwritefontcollection3_GetExpirationEvent
,
3089 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3091 dwritesystemfontcollection_QueryInterface
,
3092 dwritefontcollection_AddRef
,
3093 dwritefontcollection_Release
,
3094 dwritefontcollection_GetFontFamilyCount
,
3095 dwritefontcollection_GetFontFamily
,
3096 dwritefontcollection_FindFamilyName
,
3097 dwritefontcollection_GetFontFromFontFace
,
3098 dwritefontcollection1_GetFontSet
,
3099 dwritefontcollection1_GetFontFamily
,
3100 dwritefontcollection2_GetFontFamily
,
3101 dwritefontcollection2_GetMatchingFonts
,
3102 dwritefontcollection2_GetFontFamilyModel
,
3103 dwritefontcollection2_GetFontSet
,
3104 dwritefontcollection3_GetExpirationEvent
,
3107 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3109 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3110 sizeof(*family_data
->fonts
)))
3112 return E_OUTOFMEMORY
;
3115 family_data
->fonts
[family_data
->count
++] = font_data
;
3116 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3117 family_data
->has_normal_face
= 1;
3118 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3119 family_data
->has_oblique_face
= 1;
3121 family_data
->has_italic_face
= 1;
3125 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3126 struct dwrite_fontfamily_data
*family
)
3128 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3129 sizeof(*collection
->family_data
)))
3131 return E_OUTOFMEMORY
;
3134 collection
->family_data
[collection
->count
++] = family
;
3138 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3140 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3141 collection
->refcount
= 1;
3142 collection
->count
= 0;
3143 collection
->size
= 0;
3144 collection
->family_data
= NULL
;
3149 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3151 IDWriteFontFileLoader
*loader
;
3158 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3162 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3166 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3167 IDWriteFontFileLoader_Release(loader
);
3174 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3176 BOOL exists
= FALSE
;
3181 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3182 if (FAILED(hr
) || !exists
)
3185 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3188 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3192 while (isspaceW(*in
))
3196 if (!(len
= strlenW(in
)))
3199 while (isspaceW(in
[len
-1]))
3202 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3211 INT len
; /* token length */
3212 INT fulllen
; /* full length including following separators */
3215 static inline BOOL
is_name_separator_char(WCHAR ch
)
3217 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3220 struct name_pattern
{
3221 const WCHAR
*part1
; /* NULL indicates end of list */
3222 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3225 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3227 const struct name_pattern
*pattern
;
3228 struct name_token
*token
;
3231 while ((pattern
= &patterns
[i
++])->part1
) {
3232 int len_part1
= strlenW(pattern
->part1
);
3233 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3235 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3236 if (len_part2
== 0) {
3237 /* simple case with single part pattern */
3238 if (token
->len
!= len_part1
)
3241 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3242 if (match
) *match
= *token
;
3243 list_remove(&token
->entry
);
3249 struct name_token
*next_token
;
3250 struct list
*next_entry
;
3252 /* pattern parts are stored in reading order, tokens list is reversed */
3253 if (token
->len
< len_part2
)
3256 /* it's possible to have combined string as a token, like ExtraCondensed */
3257 if (token
->len
== len_part1
+ len_part2
) {
3258 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3261 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3264 /* combined string match */
3265 if (match
) *match
= *token
;
3266 list_remove(&token
->entry
);
3271 /* now it's only possible to have two tokens matched to respective pattern parts */
3272 if (token
->len
!= len_part2
)
3275 next_entry
= list_next(tokens
, &token
->entry
);
3277 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3278 if (next_token
->len
!= len_part1
)
3281 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3284 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3287 /* both parts matched, remove tokens */
3289 match
->ptr
= next_token
->ptr
;
3290 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3292 list_remove(&token
->entry
);
3293 list_remove(&next_token
->entry
);
3294 heap_free(next_token
);
3309 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3311 static const WCHAR itaW
[] = {'i','t','a',0};
3312 static const WCHAR italW
[] = {'i','t','a','l',0};
3313 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3314 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3316 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3317 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3318 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3319 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3321 static const struct name_pattern italic_patterns
[] = {
3330 static const struct name_pattern oblique_patterns
[] = {
3339 /* italic patterns first */
3340 if (match_pattern_list(tokens
, italic_patterns
, match
))
3341 return DWRITE_FONT_STYLE_ITALIC
;
3343 /* oblique patterns */
3344 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3345 return DWRITE_FONT_STYLE_OBLIQUE
;
3350 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3351 struct name_token
*match
)
3353 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3354 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3355 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3356 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3357 static const WCHAR wideW
[] = {'w','i','d','e',0};
3358 static const WCHAR condW
[] = {'c','o','n','d',0};
3360 static const struct name_pattern ultracondensed_patterns
[] = {
3361 { extraW
, compressedW
},
3362 { extW
, compressedW
},
3363 { ultraW
, compressedW
},
3364 { ultraW
, condensedW
},
3369 static const struct name_pattern extracondensed_patterns
[] = {
3371 { extraW
, condensedW
},
3372 { extW
, condensedW
},
3378 static const struct name_pattern semicondensed_patterns
[] = {
3381 { semiW
, condensedW
},
3386 static const struct name_pattern semiexpanded_patterns
[] = {
3388 { semiW
, expandedW
},
3389 { semiW
, extendedW
},
3393 static const struct name_pattern extraexpanded_patterns
[] = {
3394 { extraW
, expandedW
},
3395 { extW
, expandedW
},
3396 { extraW
, extendedW
},
3397 { extW
, extendedW
},
3401 static const struct name_pattern ultraexpanded_patterns
[] = {
3402 { ultraW
, expandedW
},
3403 { ultraW
, extendedW
},
3407 static const struct name_pattern condensed_patterns
[] = {
3413 static const struct name_pattern expanded_patterns
[] = {
3419 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3420 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3422 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3423 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3425 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3426 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3428 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3429 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3431 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3432 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3434 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3435 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3437 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3438 return DWRITE_FONT_STRETCH_CONDENSED
;
3440 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3441 return DWRITE_FONT_STRETCH_EXPANDED
;
3446 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3447 struct name_token
*match
)
3449 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3450 static const WCHAR nordW
[] = {'n','o','r','d',0};
3452 static const struct name_pattern thin_patterns
[] = {
3459 static const struct name_pattern extralight_patterns
[] = {
3466 static const struct name_pattern semilight_patterns
[] = {
3471 static const struct name_pattern demibold_patterns
[] = {
3477 static const struct name_pattern extrabold_patterns
[] = {
3484 static const struct name_pattern extrablack_patterns
[] = {
3491 static const struct name_pattern bold_patterns
[] = {
3496 static const struct name_pattern thin2_patterns
[] = {
3501 static const struct name_pattern light_patterns
[] = {
3506 static const struct name_pattern medium_patterns
[] = {
3511 static const struct name_pattern black_patterns
[] = {
3518 static const struct name_pattern demibold2_patterns
[] = {
3523 static const struct name_pattern extrabold2_patterns
[] = {
3528 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3529 matching pattern. */
3531 if (match_pattern_list(tokens
, thin_patterns
, match
))
3532 return DWRITE_FONT_WEIGHT_THIN
;
3534 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3535 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3537 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3538 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3540 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3541 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3543 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3544 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3546 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3547 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3549 if (match_pattern_list(tokens
, bold_patterns
, match
))
3550 return DWRITE_FONT_WEIGHT_BOLD
;
3552 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3553 return DWRITE_FONT_WEIGHT_THIN
;
3555 if (match_pattern_list(tokens
, light_patterns
, match
))
3556 return DWRITE_FONT_WEIGHT_LIGHT
;
3558 if (match_pattern_list(tokens
, medium_patterns
, match
))
3559 return DWRITE_FONT_WEIGHT_MEDIUM
;
3561 if (match_pattern_list(tokens
, black_patterns
, match
))
3562 return DWRITE_FONT_WEIGHT_BLACK
;
3564 if (match_pattern_list(tokens
, black_patterns
, match
))
3565 return DWRITE_FONT_WEIGHT_BLACK
;
3567 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3568 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3570 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3571 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3573 /* FIXME: use abbreviated names to extract weight */
3578 struct knownweight_entry
{
3580 DWRITE_FONT_WEIGHT weight
;
3583 static int compare_knownweights(const void *a
, const void* b
)
3585 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3586 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3589 if (target
> entry
->weight
)
3591 else if (target
< entry
->weight
)
3597 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3599 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3600 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3601 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3602 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3603 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3604 const struct knownweight_entry
*ptr
;
3606 static const struct knownweight_entry knownweights
[] = {
3607 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3608 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3609 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3610 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3611 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3612 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3613 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3614 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3615 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3616 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3619 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3620 compare_knownweights
);
3626 strcpyW(nameW
, ptr
->nameW
);
3630 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3632 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3633 strW
[name
->len
] = 0;
3636 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3637 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3639 static const WCHAR bookW
[] = {'B','o','o','k',0};
3640 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3641 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3642 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3643 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3645 static const WCHAR
*regular_patterns
[] = {
3654 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3658 len
= strlenW(facenameW
);
3660 /* remove rightmost regular variant from face name */
3661 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3662 int pattern_len
= strlenW(ptr
);
3665 if (pattern_len
> len
)
3668 src
= facenameW
+ len
- pattern_len
;
3669 while (src
>= facenameW
) {
3670 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3671 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3672 len
= strlenW(facenameW
);
3684 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3692 struct name_token
*token
= heap_alloc(sizeof(*token
));
3697 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3703 /* skip separators */
3704 while (is_name_separator_char(*ptr
)) {
3709 list_add_head(tokens
, &token
->entry
);
3713 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3715 struct name_token
*token
, *token2
;
3716 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3719 list_remove(&token
->entry
);
3721 /* don't include last separator */
3722 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3723 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3731 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3733 struct name_token stretch_name
, weight_name
, style_name
;
3734 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3735 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3736 const WCHAR
*regular_ptr
= NULL
;
3737 DWRITE_FONT_STRETCH stretch
;
3738 DWRITE_FONT_WEIGHT weight
;
3742 /* remove leading and trailing spaces from family and face name */
3743 trim_spaces(familyW
, familynameW
);
3744 len
= trim_spaces(faceW
, facenameW
);
3746 /* remove rightmost regular variant from face name */
3747 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3749 /* append face name to family name, FIXME check if face name is a substring of family name */
3751 strcatW(familynameW
, spaceW
);
3752 strcatW(familynameW
, facenameW
);
3755 /* tokenize with " .-_" */
3756 fontname_tokenize(&tokens
, familynameW
);
3758 /* extract and resolve style */
3759 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3761 /* extract stretch */
3762 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3764 /* extract weight */
3765 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3767 /* resolve weight */
3768 if (weight
!= font
->weight
) {
3769 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3770 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3771 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3772 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3773 !(abs(weight
- font
->weight
) <= 150 &&
3774 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3775 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3776 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3778 font
->weight
= weight
;
3782 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3783 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3784 stretch itself is normal (extracted stretch is never normal). */
3785 if (stretch
!= font
->stretch
) {
3786 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3787 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3788 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3790 font
->stretch
= stretch
;
3794 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3796 /* get final combined string from what's left in token list, list is released */
3797 fontname_tokens_to_str(&tokens
, finalW
);
3799 if (!strcmpW(familyW
, finalW
))
3802 /* construct face name */
3803 strcpyW(familyW
, finalW
);
3805 /* resolved weight name */
3806 if (weight_name
.ptr
)
3807 font_name_token_to_str(&weight_name
, weightW
);
3808 /* ignore normal weight */
3809 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3811 /* for known weight values use appropriate names */
3812 else if (is_known_weight_value(font
->weight
, weightW
)) {
3814 /* use Wnnn format as a fallback in case weight is not one of known values */
3816 static const WCHAR fmtW
[] = {'W','%','d',0};
3817 sprintfW(weightW
, fmtW
, font
->weight
);
3820 /* resolved stretch name */
3821 if (stretch_name
.ptr
)
3822 font_name_token_to_str(&stretch_name
, stretchW
);
3823 /* ignore normal stretch */
3824 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3826 /* use predefined stretch names */
3828 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3829 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3830 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3831 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3832 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3833 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3835 static const WCHAR
*stretchnamesW
[] = {
3836 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3841 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3847 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3850 /* resolved style name */
3852 font_name_token_to_str(&style_name
, styleW
);
3853 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3855 /* use predefined names */
3857 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3858 strcpyW(styleW
, italicW
);
3860 strcpyW(styleW
, obliqueW
);
3863 /* use Regular match if it was found initially */
3864 if (!*weightW
&& !*stretchW
&& !*styleW
)
3865 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3869 strcpyW(faceW
, stretchW
);
3872 strcatW(faceW
, spaceW
);
3873 strcatW(faceW
, weightW
);
3877 strcatW(faceW
, spaceW
);
3878 strcatW(faceW
, styleW
);
3882 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3886 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3888 static const float width_axis_values
[] =
3890 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3891 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
3892 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
3893 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
3894 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
3895 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
3896 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
3897 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
3898 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
3899 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
3902 struct file_stream_desc stream_desc
;
3903 struct dwrite_font_props props
;
3904 struct dwrite_font_data
*data
;
3905 WCHAR familyW
[255], faceW
[255];
3910 data
= heap_alloc_zero(sizeof(*data
));
3912 return E_OUTOFMEMORY
;
3915 data
->file
= desc
->files
[0];
3916 data
->face_index
= desc
->index
;
3917 data
->face_type
= desc
->face_type
;
3918 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3919 data
->bold_sim_tested
= 0;
3920 data
->oblique_sim_tested
= 0;
3921 IDWriteFontFile_AddRef(data
->file
);
3923 stream_desc
.stream
= desc
->stream
;
3924 stream_desc
.face_type
= desc
->face_type
;
3925 stream_desc
.face_index
= desc
->index
;
3926 opentype_get_font_properties(&stream_desc
, &props
);
3927 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3928 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3930 /* get family name from font file */
3931 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
3933 WARN("unable to get family name from font\n");
3934 release_font_data(data
);
3938 data
->style
= props
.style
;
3939 data
->stretch
= props
.stretch
;
3940 data
->weight
= props
.weight
;
3941 data
->panose
= props
.panose
;
3942 data
->fontsig
= props
.fontsig
;
3943 data
->lf
= props
.lf
;
3944 data
->flags
= props
.flags
;
3946 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
3947 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
3948 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3949 set_en_localizedstring(data
->family_names
, familyW
);
3950 set_en_localizedstring(data
->names
, faceW
);
3953 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3955 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
3956 data
->axis
[0].value
= props
.weight
;
3957 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
3958 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
3959 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
3960 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
3966 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3967 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3969 struct dwrite_font_data
*data
;
3973 data
= heap_alloc_zero(sizeof(*data
));
3975 return E_OUTOFMEMORY
;
3979 data
->simulations
|= sim
;
3980 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3981 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3982 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3983 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3984 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3986 IDWriteFontFile_AddRef(data
->file
);
3987 IDWriteLocalizedStrings_AddRef(data
->family_names
);
3989 create_localizedstrings(&data
->names
);
3990 add_localizedstring(data
->names
, enusW
, facenameW
);
3992 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3998 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4000 struct dwrite_fontfamily_data
*data
;
4002 data
= heap_alloc_zero(sizeof(*data
));
4004 return E_OUTOFMEMORY
;
4007 data
->familyname
= familyname
;
4008 IDWriteLocalizedStrings_AddRef(familyname
);
4015 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4017 size_t i
, j
, heaviest
;
4019 for (i
= 0; i
< family
->count
; ++i
)
4021 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4024 if (family
->fonts
[i
]->bold_sim_tested
)
4027 family
->fonts
[i
]->bold_sim_tested
= 1;
4028 for (j
= i
; j
< family
->count
; ++j
)
4030 if (family
->fonts
[j
]->bold_sim_tested
)
4033 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4034 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4035 if (family
->fonts
[j
]->weight
> weight
) {
4036 weight
= family
->fonts
[j
]->weight
;
4039 family
->fonts
[j
]->bold_sim_tested
= 1;
4043 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4044 static const struct name_pattern weightsim_patterns
[] = {
4059 WCHAR facenameW
[255], initialW
[255];
4060 struct dwrite_font_data
*boldface
;
4063 /* add Bold simulation based on heaviest face data */
4065 /* Simulated face name should only contain Bold as weight term,
4066 so remove existing regular and weight terms. */
4067 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4068 facename_remove_regular_term(initialW
, -1);
4070 /* remove current weight pattern */
4071 fontname_tokenize(&tokens
, initialW
);
4072 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4073 fontname_tokens_to_str(&tokens
, facenameW
);
4075 /* Bold suffix for new name */
4077 strcatW(facenameW
, spaceW
);
4078 strcatW(facenameW
, boldW
);
4080 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4081 boldface
->bold_sim_tested
= 1;
4082 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4083 fontfamily_add_font(family
, boldface
);
4089 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4093 for (i
= 0; i
< family
->count
; ++i
)
4095 UINT32 regular
= ~0u, oblique
= ~0u;
4096 struct dwrite_font_data
*obliqueface
;
4097 WCHAR facenameW
[255];
4099 if (family
->fonts
[i
]->oblique_sim_tested
)
4102 family
->fonts
[i
]->oblique_sim_tested
= 1;
4103 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4105 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4108 /* find regular style with same weight/stretch values */
4109 for (j
= i
; j
< family
->count
; ++j
)
4111 if (family
->fonts
[j
]->oblique_sim_tested
)
4114 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4115 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4117 family
->fonts
[j
]->oblique_sim_tested
= 1;
4118 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4121 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4125 if (regular
!= ~0u && oblique
!= ~0u)
4129 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4133 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4137 /* add oblique simulation based on this regular face */
4139 /* remove regular term if any, append 'Oblique' */
4140 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4141 facename_remove_regular_term(facenameW
, -1);
4144 strcatW(facenameW
, spaceW
);
4145 strcatW(facenameW
, obliqueW
);
4147 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4148 obliqueface
->oblique_sim_tested
= 1;
4149 obliqueface
->lf
.lfItalic
= 1;
4150 fontfamily_add_font(family
, obliqueface
);
4155 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4156 const WCHAR
*replacement_name
)
4158 UINT32 i
= collection_find_family(collection
, replacement_name
);
4159 struct dwrite_fontfamily_data
*target
;
4160 IDWriteLocalizedStrings
*strings
;
4163 /* replacement does not exist */
4167 hr
= create_localizedstrings(&strings
);
4171 /* add a new family with target name, reuse font data from replacement */
4172 add_localizedstring(strings
, enusW
, target_name
);
4173 hr
= init_fontfamily_data(strings
, &target
);
4175 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4178 for (i
= 0; i
< replacement
->count
; ++i
)
4180 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4181 addref_font_data(replacement
->fonts
[i
]);
4184 fontcollection_add_family(collection
, target
);
4185 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4186 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4188 IDWriteLocalizedStrings_Release(strings
);
4192 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4193 system font collections. */
4194 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4196 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4201 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4204 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4209 max_namelen
++; /* returned value doesn't include room for '\0' */
4210 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4211 data
= heap_alloc(max_datalen
);
4213 datalen
= max_datalen
;
4214 namelen
= max_namelen
;
4215 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4216 if (collection_find_family(collection
, name
) == ~0u) {
4217 if (type
== REG_MULTI_SZ
) {
4218 WCHAR
*replacement
= data
;
4219 while (*replacement
) {
4220 if (fontcollection_add_replacement(collection
, name
, replacement
))
4222 replacement
+= strlenW(replacement
) + 1;
4225 else if (type
== REG_SZ
)
4226 fontcollection_add_replacement(collection
, name
, data
);
4229 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4231 datalen
= max_datalen
;
4232 namelen
= max_namelen
;
4240 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4241 IDWriteFontCollection3
**ret
)
4243 struct fontfile_enum
{
4245 IDWriteFontFile
*file
;
4247 struct fontfile_enum
*fileenum
, *fileenum2
;
4248 struct dwrite_fontcollection
*collection
;
4249 struct list scannedfiles
;
4250 BOOL current
= FALSE
;
4256 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4257 if (!collection
) return E_OUTOFMEMORY
;
4259 hr
= init_font_collection(collection
, is_system
);
4261 heap_free(collection
);
4265 *ret
= &collection
->IDWriteFontCollection3_iface
;
4267 TRACE("building font collection:\n");
4269 list_init(&scannedfiles
);
4270 while (hr
== S_OK
) {
4271 DWRITE_FONT_FACE_TYPE face_type
;
4272 DWRITE_FONT_FILE_TYPE file_type
;
4273 BOOL supported
, same
= FALSE
;
4274 IDWriteFontFileStream
*stream
;
4275 IDWriteFontFile
*file
;
4279 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4280 if (FAILED(hr
) || !current
)
4283 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4287 /* check if we've scanned this file already */
4288 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4289 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4294 IDWriteFontFile_Release(file
);
4298 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4299 IDWriteFontFile_Release(file
);
4303 /* Unsupported formats are skipped. */
4304 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4305 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4306 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4307 IDWriteFontFileStream_Release(stream
);
4308 IDWriteFontFile_Release(file
);
4313 /* add to scanned list */
4314 fileenum
= heap_alloc(sizeof(*fileenum
));
4315 fileenum
->file
= file
;
4316 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4318 for (i
= 0; i
< face_count
; ++i
)
4320 struct dwrite_font_data
*font_data
;
4321 struct fontface_desc desc
;
4325 desc
.factory
= factory
;
4326 desc
.face_type
= face_type
;
4328 desc
.stream
= stream
;
4329 desc
.files_number
= 1;
4331 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4332 desc
.font_data
= NULL
;
4334 /* Allocate an initialize new font data structure. */
4335 hr
= init_font_data(&desc
, &font_data
);
4338 /* move to next one */
4343 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4345 /* ignore dot named faces */
4346 if (familyW
[0] == '.')
4348 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4349 release_font_data(font_data
);
4353 index
= collection_find_family(collection
, familyW
);
4355 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4357 struct dwrite_fontfamily_data
*family_data
;
4359 /* create and init new family */
4360 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4362 /* add font to family, family - to collection */
4363 hr
= fontfamily_add_font(family_data
, font_data
);
4365 hr
= fontcollection_add_family(collection
, family_data
);
4368 release_fontfamily_data(family_data
);
4376 IDWriteFontFileStream_Release(stream
);
4379 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4380 IDWriteFontFile_Release(fileenum
->file
);
4381 list_remove(&fileenum
->entry
);
4382 heap_free(fileenum
);
4385 for (i
= 0; i
< collection
->count
; ++i
)
4387 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4388 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4392 fontcollection_add_replacements(collection
);
4394 collection
->factory
= factory
;
4395 IDWriteFactory7_AddRef(factory
);
4400 struct system_fontfile_enumerator
4402 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4405 IDWriteFactory7
*factory
;
4410 DWORD filename_size
;
4413 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4415 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4418 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4420 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4421 IDWriteFontFileEnumerator_AddRef(iface
);
4426 WARN("%s not implemented.\n", debugstr_guid(riid
));
4430 return E_NOINTERFACE
;
4433 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4435 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4436 return InterlockedIncrement(&enumerator
->ref
);
4439 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4441 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4442 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
4446 IDWriteFactory7_Release(enumerator
->factory
);
4447 RegCloseKey(enumerator
->hkey
);
4448 heap_free(enumerator
->filename
);
4449 heap_free(enumerator
);
4455 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4459 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4460 if (!strchrW(filename
, '\\')) {
4461 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4462 WCHAR fullpathW
[MAX_PATH
];
4464 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4465 strcatW(fullpathW
, fontsW
);
4466 strcatW(fullpathW
, filename
);
4468 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4471 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4476 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4478 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4482 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4485 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4488 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4490 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4491 WCHAR name_buf
[256], *name
= name_buf
;
4492 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4497 enumerator
->index
++;
4499 /* iterate until we find next string value */
4502 name_count
= max_name_count
;
4503 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4505 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4506 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4507 if (r
== ERROR_MORE_DATA
) {
4508 if (name_count
>= max_name_count
) {
4509 if (name
!= name_buf
) heap_free(name
);
4510 max_name_count
*= 2;
4511 name
= heap_alloc(max_name_count
* sizeof(*name
));
4512 if (!name
) return E_OUTOFMEMORY
;
4514 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4515 heap_free(enumerator
->filename
);
4516 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4517 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4518 if (!enumerator
->filename
) {
4524 } while (r
== ERROR_MORE_DATA
);
4526 if (r
!= ERROR_SUCCESS
) {
4527 enumerator
->filename
[0] = 0;
4530 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4531 if (type
== REG_SZ
&& *name
!= '@') {
4535 enumerator
->index
++;
4537 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4540 if (name
!= name_buf
) heap_free(name
);
4544 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4546 systemfontfileenumerator_QueryInterface
,
4547 systemfontfileenumerator_AddRef
,
4548 systemfontfileenumerator_Release
,
4549 systemfontfileenumerator_MoveNext
,
4550 systemfontfileenumerator_GetCurrentFontFile
4553 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4555 struct system_fontfile_enumerator
*enumerator
;
4556 static const WCHAR fontslistW
[] = {
4557 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4558 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4559 'F','o','n','t','s',0
4564 enumerator
= heap_alloc(sizeof(*enumerator
));
4566 return E_OUTOFMEMORY
;
4568 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4569 enumerator
->ref
= 1;
4570 enumerator
->factory
= factory
;
4571 enumerator
->index
= -1;
4572 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4573 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4574 if (!enumerator
->filename
) {
4575 heap_free(enumerator
);
4576 return E_OUTOFMEMORY
;
4579 IDWriteFactory7_AddRef(factory
);
4581 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4583 ERR("failed to open fonts list key\n");
4584 IDWriteFactory7_Release(factory
);
4585 heap_free(enumerator
->filename
);
4586 heap_free(enumerator
);
4590 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4595 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4597 IDWriteFontFileEnumerator
*enumerator
;
4602 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4606 TRACE("building system font collection for factory %p\n", factory
);
4607 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4608 IDWriteFontFileEnumerator_Release(enumerator
);
4612 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4613 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4615 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};
4616 static const WCHAR emptyW
[] = {0};
4617 struct dwrite_fontfamily_data
*family_data
;
4618 IDWriteLocalizedStrings
*names
;
4619 DWRITE_FONT_FACE_TYPE face_type
;
4620 DWRITE_FONT_FILE_TYPE file_type
;
4621 IDWriteFontFileStream
*stream
;
4622 IDWriteFontFile
*file
;
4623 UINT32 face_count
, i
;
4627 /* create font file from this path */
4628 hr
= create_local_file_reference(factory
, pathW
, &file
);
4632 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4633 IDWriteFontFile_Release(file
);
4637 /* Unsupported formats are skipped. */
4638 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4639 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4640 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4641 IDWriteFontFileStream_Release(stream
);
4642 IDWriteFontFile_Release(file
);
4646 /* create and init new family */
4648 /* Family names are added for non-specific locale, represented with empty string.
4649 Default family appears with empty family name. */
4650 create_localizedstrings(&names
);
4651 if (!strcmpiW(keynameW
, defaultfontW
))
4652 add_localizedstring(names
, emptyW
, emptyW
);
4654 add_localizedstring(names
, emptyW
, keynameW
);
4656 hr
= init_fontfamily_data(names
, &family_data
);
4657 IDWriteLocalizedStrings_Release(names
);
4659 IDWriteFontFile_Release(file
);
4663 /* fill with faces */
4664 for (i
= 0; i
< face_count
; i
++) {
4665 struct dwrite_font_data
*font_data
;
4666 struct fontface_desc desc
;
4668 /* alloc and init new font data structure */
4669 desc
.factory
= factory
;
4670 desc
.face_type
= face_type
;
4673 desc
.stream
= stream
;
4674 desc
.files_number
= 1;
4675 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4676 desc
.font_data
= NULL
;
4678 hr
= init_font_data(&desc
, &font_data
);
4682 /* add font to family */
4683 hr
= fontfamily_add_font(family_data
, font_data
);
4685 release_font_data(font_data
);
4688 /* add family to collection */
4689 hr
= fontcollection_add_family(collection
, family_data
);
4691 release_fontfamily_data(family_data
);
4692 IDWriteFontFileStream_Release(stream
);
4693 IDWriteFontFile_Release(file
);
4698 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4700 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4701 struct dwrite_fontcollection
*collection
;
4702 static const WCHAR emptyW
[] = {0};
4703 WCHAR eudckeypathW
[16];
4711 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4715 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4716 if (!collection
) return E_OUTOFMEMORY
;
4718 hr
= init_font_collection(collection
, FALSE
);
4720 heap_free(collection
);
4724 *ret
= &collection
->IDWriteFontCollection3_iface
;
4725 collection
->factory
= factory
;
4726 IDWriteFactory7_AddRef(factory
);
4728 /* return empty collection if EUDC fonts are not configured */
4729 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4730 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4733 retval
= ERROR_SUCCESS
;
4735 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4736 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4737 DWORD type
, path_len
, name_len
;
4739 path_len
= ARRAY_SIZE(pathW
);
4740 name_len
= ARRAY_SIZE(keynameW
);
4741 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4742 if (retval
|| type
!= REG_SZ
)
4745 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4747 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4749 RegCloseKey(eudckey
);
4751 /* try to add global default if not defined for specific codepage */
4753 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4755 if (FAILED(hr
) || !exists
) {
4756 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4757 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4759 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4762 /* EUDC collection offers simulated faces too */
4763 for (i
= 0; i
< collection
->count
; ++i
)
4765 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4766 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4772 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4774 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4776 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4778 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4781 IDWriteFontFile_AddRef(iface
);
4785 WARN("%s not implemented.\n", debugstr_guid(riid
));
4788 return E_NOINTERFACE
;
4791 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4793 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4794 ULONG ref
= InterlockedIncrement(&This
->ref
);
4795 TRACE("(%p)->(%d)\n", This
, ref
);
4799 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4801 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4802 ULONG ref
= InterlockedDecrement(&This
->ref
);
4804 TRACE("(%p)->(%d)\n", This
, ref
);
4808 IDWriteFontFileLoader_Release(This
->loader
);
4809 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4810 heap_free(This
->reference_key
);
4817 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4819 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4820 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4821 *fontFileReferenceKey
= This
->reference_key
;
4822 *fontFileReferenceKeySize
= This
->key_size
;
4827 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4829 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4830 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4831 *fontFileLoader
= This
->loader
;
4832 IDWriteFontFileLoader_AddRef(This
->loader
);
4837 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4838 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4840 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4841 IDWriteFontFileStream
*stream
;
4844 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, is_supported
, file_type
, face_type
, face_count
);
4846 *is_supported
= FALSE
;
4847 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4849 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4852 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4856 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4858 /* TODO: Further Analysis */
4859 IDWriteFontFileStream_Release(stream
);
4863 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4864 dwritefontfile_QueryInterface
,
4865 dwritefontfile_AddRef
,
4866 dwritefontfile_Release
,
4867 dwritefontfile_GetReferenceKey
,
4868 dwritefontfile_GetLoader
,
4869 dwritefontfile_Analyze
,
4872 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4873 IDWriteFontFile
**ret
)
4875 struct dwrite_fontfile
*file
;
4880 file
= heap_alloc(sizeof(*file
));
4881 key
= heap_alloc(key_size
);
4882 if (!file
|| !key
) {
4885 return E_OUTOFMEMORY
;
4888 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4890 IDWriteFontFileLoader_AddRef(loader
);
4891 file
->loader
= loader
;
4892 file
->stream
= NULL
;
4893 file
->reference_key
= key
;
4894 memcpy(file
->reference_key
, reference_key
, key_size
);
4895 file
->key_size
= key_size
;
4897 *ret
= &file
->IDWriteFontFile_iface
;
4902 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
4904 struct file_stream_desc stream_desc
;
4905 struct dwrite_font_data
*font_data
;
4906 struct dwrite_fontface
*fontface
;
4912 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4914 return E_OUTOFMEMORY
;
4916 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4917 if (!fontface
->files
) {
4918 heap_free(fontface
);
4919 return E_OUTOFMEMORY
;
4922 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
4923 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
4924 fontface
->refcount
= 1;
4925 fontface
->type
= desc
->face_type
;
4926 fontface
->file_count
= desc
->files_number
;
4927 fontface
->vdmx
.exists
= TRUE
;
4928 fontface
->gasp
.exists
= TRUE
;
4929 fontface
->cpal
.exists
= TRUE
;
4930 fontface
->colr
.exists
= TRUE
;
4931 fontface
->index
= desc
->index
;
4932 fontface
->simulations
= desc
->simulations
;
4933 fontface
->factory
= desc
->factory
;
4934 IDWriteFactory7_AddRef(fontface
->factory
);
4936 for (i
= 0; i
< fontface
->file_count
; i
++) {
4937 fontface
->files
[i
] = desc
->files
[i
];
4938 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4940 fontface
->stream
= desc
->stream
;
4941 IDWriteFontFileStream_AddRef(fontface
->stream
);
4943 stream_desc
.stream
= fontface
->stream
;
4944 stream_desc
.face_type
= desc
->face_type
;
4945 stream_desc
.face_index
= desc
->index
;
4946 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4947 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
4948 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4949 /* TODO: test what happens if caret is already slanted */
4950 if (fontface
->caret
.slopeRise
== 1) {
4951 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4952 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4956 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace5_iface
))
4957 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4958 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace5_iface
))
4959 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4960 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
4962 /* Font properties are reused from font object when 'normal' face creation path is used:
4963 collection -> family -> matching font -> fontface.
4965 If face is created directly from factory we have to go through properties resolution.
4967 if (desc
->font_data
)
4969 font_data
= desc
->font_data
;
4970 addref_font_data(font_data
);
4974 hr
= init_font_data(desc
, &font_data
);
4977 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
4982 fontface
->weight
= font_data
->weight
;
4983 fontface
->style
= font_data
->style
;
4984 fontface
->stretch
= font_data
->stretch
;
4985 fontface
->panose
= font_data
->panose
;
4986 fontface
->fontsig
= font_data
->fontsig
;
4987 fontface
->lf
= font_data
->lf
;
4988 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
4989 fontface
->names
= font_data
->names
;
4990 if (fontface
->names
)
4991 IDWriteLocalizedStrings_AddRef(fontface
->names
);
4992 fontface
->family_names
= font_data
->family_names
;
4993 if (fontface
->family_names
)
4994 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
4995 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
4996 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
4998 if (fontface
->info_strings
[i
])
4999 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5001 fontface
->cmap
.stream
= fontface
->stream
;
5002 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5003 release_font_data(font_data
);
5005 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5007 *ret
= &fontface
->IDWriteFontFace5_iface
;
5012 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5019 struct local_cached_stream
5022 IDWriteFontFileStream
*stream
;
5023 struct local_refkey
*key
;
5027 struct dwrite_localfontfilestream
5029 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5032 struct local_cached_stream
*entry
;
5033 const void *file_ptr
;
5037 struct dwrite_localfontfileloader
{
5038 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5041 struct list streams
;
5042 CRITICAL_SECTION cs
;
5045 static struct dwrite_localfontfileloader local_fontfile_loader
;
5047 struct dwrite_inmemory_stream_data
5055 struct dwrite_inmemory_filestream
5057 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5060 struct dwrite_inmemory_stream_data
*data
;
5063 struct dwrite_inmemory_fileloader
5065 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5068 struct dwrite_inmemory_stream_data
**streams
;
5073 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5075 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5078 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5080 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5083 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5085 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5088 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5090 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5093 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5095 if (InterlockedDecrement(&stream
->ref
) == 0) {
5097 IUnknown_Release(stream
->owner
);
5099 heap_free(stream
->data
);
5104 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5106 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5108 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5110 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5111 IsEqualIID(riid
, &IID_IUnknown
))
5114 if (InterlockedIncrement(&This
->ref
) == 1) {
5115 InterlockedDecrement(&This
->ref
);
5122 WARN("%s not implemented.\n", debugstr_guid(riid
));
5125 return E_NOINTERFACE
;
5128 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5130 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5131 ULONG ref
= InterlockedIncrement(&This
->ref
);
5132 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
5136 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5138 list_remove(&stream
->entry
);
5139 heap_free(stream
->key
);
5143 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5145 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5146 ULONG ref
= InterlockedDecrement(&This
->ref
);
5148 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
5151 UnmapViewOfFile(This
->file_ptr
);
5153 EnterCriticalSection(&local_fontfile_loader
.cs
);
5154 release_cached_stream(This
->entry
);
5155 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5163 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5164 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5166 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5168 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
5169 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5171 *fragment_context
= NULL
;
5173 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
5174 *fragment_start
= NULL
;
5178 *fragment_start
= (char*)This
->file_ptr
+ offset
;
5182 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5184 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5185 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
5188 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5190 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5191 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
5196 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5198 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5201 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
5203 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
5204 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
5205 *last_writetime
= li
.QuadPart
;
5210 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5212 localfontfilestream_QueryInterface
,
5213 localfontfilestream_AddRef
,
5214 localfontfilestream_Release
,
5215 localfontfilestream_ReadFileFragment
,
5216 localfontfilestream_ReleaseFileFragment
,
5217 localfontfilestream_GetFileSize
,
5218 localfontfilestream_GetLastWriteTime
5221 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
5223 struct dwrite_localfontfilestream
*This
;
5227 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
5229 return E_OUTOFMEMORY
;
5231 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5234 This
->file_ptr
= file_ptr
;
5236 This
->entry
= entry
;
5238 *ret
= &This
->IDWriteFontFileStream_iface
;
5242 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5244 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5246 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5248 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5249 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5250 IsEqualIID(riid
, &IID_IUnknown
))
5253 IDWriteLocalFontFileLoader_AddRef(iface
);
5257 WARN("%s not implemented.\n", debugstr_guid(riid
));
5260 return E_NOINTERFACE
;
5263 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5265 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5266 ULONG ref
= InterlockedIncrement(&This
->ref
);
5267 TRACE("(%p)->(%d)\n", This
, ref
);
5271 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5273 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5274 ULONG ref
= InterlockedDecrement(&This
->ref
);
5276 TRACE("(%p)->(%d)\n", This
, ref
);
5281 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5283 const struct local_refkey
*refkey
= key
;
5284 struct local_cached_stream
*stream
;
5285 IDWriteFontFileStream
*filestream
;
5286 HANDLE file
, mapping
;
5293 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5294 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5295 if (file
== INVALID_HANDLE_VALUE
) {
5296 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5300 GetFileSizeEx(file
, &size
);
5301 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5306 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5307 CloseHandle(mapping
);
5309 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5313 stream
= heap_alloc(sizeof(*stream
));
5315 UnmapViewOfFile(file_ptr
);
5316 return E_OUTOFMEMORY
;
5319 stream
->key
= heap_alloc(key_size
);
5321 UnmapViewOfFile(file_ptr
);
5323 return E_OUTOFMEMORY
;
5326 stream
->key_size
= key_size
;
5327 memcpy(stream
->key
, key
, key_size
);
5329 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5331 UnmapViewOfFile(file_ptr
);
5332 heap_free(stream
->key
);
5337 stream
->stream
= filestream
;
5344 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5345 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5347 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5348 const struct local_refkey
*refkey
= key
;
5349 struct local_cached_stream
*stream
;
5352 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, ret
);
5353 TRACE("name: %s\n", debugstr_w(refkey
->name
));
5355 EnterCriticalSection(&This
->cs
);
5359 /* search cache first */
5360 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
5361 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5362 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5367 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
) {
5368 list_add_head(&This
->streams
, &stream
->entry
);
5369 *ret
= stream
->stream
;
5372 LeaveCriticalSection(&This
->cs
);
5377 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
5379 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5380 const struct local_refkey
*refkey
= key
;
5382 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
5384 *length
= strlenW(refkey
->name
);
5388 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5390 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5391 const struct local_refkey
*refkey
= key
;
5393 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
5395 if (length
< strlenW(refkey
->name
))
5396 return E_INVALIDARG
;
5398 strcpyW(path
, refkey
->name
);
5402 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5403 UINT32 key_size
, FILETIME
*writetime
)
5405 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5406 const struct local_refkey
*refkey
= key
;
5408 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, writetime
);
5410 *writetime
= refkey
->writetime
;
5414 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
5415 localfontfileloader_QueryInterface
,
5416 localfontfileloader_AddRef
,
5417 localfontfileloader_Release
,
5418 localfontfileloader_CreateStreamFromKey
,
5419 localfontfileloader_GetFilePathLengthFromKey
,
5420 localfontfileloader_GetFilePathFromKey
,
5421 localfontfileloader_GetLastWriteTimeFromKey
5424 void init_local_fontfile_loader(void)
5426 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5427 local_fontfile_loader
.ref
= 1;
5428 list_init(&local_fontfile_loader
.streams
);
5429 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5430 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5433 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5435 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5438 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5440 struct local_refkey
*refkey
;
5443 return E_INVALIDARG
;
5445 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5448 refkey
= heap_alloc(*size
);
5450 return E_OUTOFMEMORY
;
5453 refkey
->writetime
= *writetime
;
5455 WIN32_FILE_ATTRIBUTE_DATA info
;
5457 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5458 refkey
->writetime
= info
.ftLastWriteTime
;
5460 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5462 strcpyW(refkey
->name
, path
);
5469 /* IDWriteGlyphRunAnalysis */
5470 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5472 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5474 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5476 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5477 IsEqualIID(riid
, &IID_IUnknown
))
5480 IDWriteGlyphRunAnalysis_AddRef(iface
);
5484 WARN("%s not implemented.\n", debugstr_guid(riid
));
5487 return E_NOINTERFACE
;
5490 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5492 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5493 ULONG ref
= InterlockedIncrement(&This
->ref
);
5494 TRACE("(%p)->(%u)\n", This
, ref
);
5498 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5500 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5501 ULONG ref
= InterlockedDecrement(&This
->ref
);
5503 TRACE("(%p)->(%u)\n", This
, ref
);
5506 if (This
->run
.fontFace
)
5507 IDWriteFontFace_Release(This
->run
.fontFace
);
5508 heap_free(This
->glyphs
);
5509 heap_free(This
->origins
);
5510 heap_free(This
->bitmap
);
5517 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5521 case DWRITE_RENDERING_MODE1_NATURAL
:
5522 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5523 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5530 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5532 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5535 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5537 struct dwrite_glyphbitmap glyph_bitmap
;
5538 IDWriteFontFace4
*fontface
;
5542 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5543 *bounds
= analysis
->bounds
;
5547 if (analysis
->run
.isSideways
)
5548 FIXME("sideways runs are not supported.\n");
5550 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5552 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5554 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5555 glyph_bitmap
.fontface
= fontface
;
5556 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5557 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5558 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5559 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5560 glyph_bitmap
.m
= &analysis
->m
;
5562 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5563 RECT
*bbox
= &glyph_bitmap
.bbox
;
5566 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5567 freetype_get_glyph_bbox(&glyph_bitmap
);
5569 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5570 (bbox
->bottom
- bbox
->top
);
5571 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5572 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5574 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5575 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5578 IDWriteFontFace4_Release(fontface
);
5580 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5581 *bounds
= analysis
->bounds
;
5584 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5586 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5588 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
5590 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5591 SetRectEmpty(bounds
);
5592 return E_INVALIDARG
;
5595 if (type
!= This
->texture_type
) {
5596 SetRectEmpty(bounds
);
5600 glyphrunanalysis_get_texturebounds(This
, bounds
);
5604 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5606 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5607 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5608 (runbounds
->left
- bounds
->left
) * 3;
5610 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5611 runbounds
->left
- bounds
->left
;
5614 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5616 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5617 struct dwrite_glyphbitmap glyph_bitmap
;
5618 IDWriteFontFace4
*fontface
;
5619 D2D_POINT_2F origin
;
5624 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5626 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5630 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5631 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5633 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5634 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5635 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5636 IDWriteFontFace4_Release(fontface
);
5637 return E_OUTOFMEMORY
;
5640 origin
.x
= origin
.y
= 0.0f
;
5642 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5643 glyph_bitmap
.fontface
= fontface
;
5644 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5645 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5646 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5647 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5648 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5649 glyph_bitmap
.m
= &analysis
->m
;
5650 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5651 IDWriteFontFace4_Release(fontface
);
5652 return E_OUTOFMEMORY
;
5655 bbox
= &glyph_bitmap
.bbox
;
5657 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5658 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5659 int x
, y
, width
, height
;
5662 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5663 freetype_get_glyph_bbox(&glyph_bitmap
);
5665 if (IsRectEmpty(bbox
))
5668 width
= bbox
->right
- bbox
->left
;
5669 height
= bbox
->bottom
- bbox
->top
;
5671 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5672 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5673 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5675 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5677 /* blit to analysis bitmap */
5678 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5681 /* convert 1bpp to 8bpp/24bpp */
5682 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5683 for (y
= 0; y
< height
; y
++) {
5684 for (x
= 0; x
< width
; x
++)
5685 if (src
[x
/ 8] & masks
[x
% 8])
5686 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5687 src
+= glyph_bitmap
.pitch
;
5688 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5692 for (y
= 0; y
< height
; y
++) {
5693 for (x
= 0; x
< width
; x
++)
5694 if (src
[x
/ 8] & masks
[x
% 8])
5695 dst
[x
] = DWRITE_ALPHA_MAX
;
5696 src
+= glyph_bitmap
.pitch
;
5697 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5702 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5703 for (y
= 0; y
< height
; y
++) {
5704 for (x
= 0; x
< width
; x
++)
5705 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5706 src
+= glyph_bitmap
.pitch
;
5707 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5711 for (y
= 0; y
< height
; y
++) {
5712 for (x
= 0; x
< width
; x
++)
5714 src
+= glyph_bitmap
.pitch
;
5715 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5720 heap_free(glyph_bitmap
.buf
);
5722 IDWriteFontFace4_Release(fontface
);
5724 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5726 /* we don't need this anymore */
5727 heap_free(analysis
->glyphs
);
5728 heap_free(analysis
->origins
);
5729 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5731 analysis
->glyphs
= NULL
;
5732 analysis
->origins
= NULL
;
5733 analysis
->run
.glyphIndices
= NULL
;
5734 analysis
->run
.fontFace
= NULL
;
5739 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5740 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5742 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5746 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5748 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5749 return E_INVALIDARG
;
5751 /* make sure buffer is large enough for requested texture type */
5752 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5753 if (This
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5756 if (size
< required
)
5757 return E_NOT_SUFFICIENT_BUFFER
;
5759 /* validate requested texture type */
5760 if (This
->texture_type
!= type
)
5761 return DWRITE_E_UNSUPPORTEDOPERATION
;
5763 memset(bitmap
, 0, size
);
5764 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5765 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5766 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5767 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5768 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5769 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5773 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5776 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5780 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5781 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5783 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5784 memcpy(dst
, src
, draw_width
);
5793 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5794 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5796 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5798 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5801 return E_INVALIDARG
;
5803 switch (This
->rendering_mode
)
5805 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5806 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5809 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5810 *gamma
= (FLOAT
)value
/ 1000.0f
;
5812 *cleartypelevel
= 1.0f
;
5815 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5816 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5818 case DWRITE_RENDERING_MODE1_ALIASED
:
5819 case DWRITE_RENDERING_MODE1_NATURAL
:
5820 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5821 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5822 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5823 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5832 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5833 glyphrunanalysis_QueryInterface
,
5834 glyphrunanalysis_AddRef
,
5835 glyphrunanalysis_Release
,
5836 glyphrunanalysis_GetAlphaTextureBounds
,
5837 glyphrunanalysis_CreateAlphaTexture
,
5838 glyphrunanalysis_GetAlphaBlendParams
5841 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5844 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5845 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5849 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5850 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5852 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5856 FIXME("Sideways mode is not supported.\n");
5858 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5860 switch (measuring_mode
)
5862 case DWRITE_MEASURING_MODE_NATURAL
:
5863 return (float)advance
* emsize
/ (float)upem
;
5864 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5865 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5866 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5868 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5873 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5875 struct dwrite_glyphrunanalysis
*analysis
;
5876 struct dwrite_fontface
*fontface
;
5877 D2D_POINT_2F origin
;
5883 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5884 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5885 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5886 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5887 return E_INVALIDARG
;
5889 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5890 return E_INVALIDARG
;
5892 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5893 return E_INVALIDARG
;
5895 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5896 return E_INVALIDARG
;
5898 analysis
= heap_alloc(sizeof(*analysis
));
5900 return E_OUTOFMEMORY
;
5902 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5904 analysis
->rendering_mode
= desc
->rendering_mode
;
5906 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5907 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5908 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5910 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5912 analysis
->flags
= 0;
5913 analysis
->bitmap
= NULL
;
5914 analysis
->max_glyph_bitmap_size
= 0;
5915 SetRectEmpty(&analysis
->bounds
);
5916 analysis
->run
= *desc
->run
;
5917 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5918 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
5919 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
5921 if (!analysis
->glyphs
|| !analysis
->origins
) {
5922 heap_free(analysis
->glyphs
);
5923 heap_free(analysis
->origins
);
5925 analysis
->glyphs
= NULL
;
5926 analysis
->origins
= NULL
;
5928 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5929 return E_OUTOFMEMORY
;
5932 /* check if transform is usable */
5933 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5934 analysis
->m
= *desc
->transform
;
5935 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5938 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5940 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5941 analysis
->run
.glyphAdvances
= NULL
;
5942 analysis
->run
.glyphOffsets
= NULL
;
5944 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5946 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5948 fontface
= unsafe_impl_from_IDWriteFontFace(desc
->run
->fontFace
);
5950 origin
.x
= desc
->origin
.x
;
5951 origin
.y
= desc
->origin
.y
;
5952 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
5956 /* Use nominal advances if not provided by caller. */
5957 if (desc
->run
->glyphAdvances
)
5958 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
];
5960 advance
= rtl_factor
* fontface_get_scaled_design_advance(fontface
, desc
->measuring_mode
,
5961 desc
->run
->fontEmSize
, 1.0f
, desc
->transform
, desc
->run
->glyphIndices
[i
], desc
->run
->isSideways
);
5963 analysis
->origins
[i
] = origin
;
5964 if (desc
->run
->bidiLevel
& 1)
5966 if (desc
->run
->isSideways
)
5967 analysis
->origins
[i
].y
+= advance
;
5969 analysis
->origins
[i
].x
+= advance
;
5972 /* Offsets are optional, appled to pre-transformed origin. */
5973 if (desc
->run
->glyphOffsets
) {
5974 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
;
5975 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
;
5977 if (desc
->run
->isSideways
) {
5978 analysis
->origins
[i
].x
+= ascenderoffset
;
5979 analysis
->origins
[i
].y
+= advanceoffset
;
5982 analysis
->origins
[i
].x
+= advanceoffset
;
5983 analysis
->origins
[i
].y
+= ascenderoffset
;
5987 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5988 transform_point(analysis
->origins
+ i
, &analysis
->m
);
5990 if (desc
->run
->isSideways
)
5991 origin
.y
+= advance
;
5993 origin
.x
+= advance
;
5996 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6000 /* IDWriteColorGlyphRunEnumerator1 */
6001 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6003 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6005 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6006 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6007 IsEqualIID(riid
, &IID_IUnknown
))
6010 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6014 WARN("%s not implemented.\n", debugstr_guid(riid
));
6017 return E_NOINTERFACE
;
6020 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6022 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6023 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6025 TRACE("%p, refcount %u.\n", iface
, refcount
);
6030 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6032 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6033 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6035 TRACE("%p, refcount %u.\n", iface
, refcount
);
6039 heap_free(glyphenum
->advances
);
6040 heap_free(glyphenum
->color_advances
);
6041 heap_free(glyphenum
->offsets
);
6042 heap_free(glyphenum
->color_offsets
);
6043 heap_free(glyphenum
->glyphindices
);
6044 heap_free(glyphenum
->glyphs
);
6045 if (glyphenum
->colr
.context
)
6046 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6047 IDWriteFontFace5_Release(glyphenum
->fontface
);
6048 heap_free(glyphenum
);
6054 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6056 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6057 FLOAT origin
= 0.0f
;
6063 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6067 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6069 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6070 FLOAT advance_adj
= 0.0f
;
6071 BOOL got_palette_index
;
6074 /* start with regular glyphs */
6075 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6076 UINT32 first_glyph
= 0;
6078 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6079 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6080 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6081 first_glyph
= min(first_glyph
, g
);
6084 glyphenum
->glyphindices
[g
] = 1;
6085 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6086 if (glyphenum
->color_offsets
)
6087 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6090 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6091 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6092 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6093 colorrun
->paletteIndex
= 0xffff;
6094 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6095 glyphenum
->has_regular_glyphs
= FALSE
;
6099 colorrun
->glyphRun
.glyphCount
= 0;
6100 got_palette_index
= FALSE
;
6104 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6106 glyphenum
->glyphindices
[g
] = 1;
6108 /* all glyph layers were returned */
6109 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6110 advance_adj
+= glyphenum
->advances
[g
];
6114 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6115 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6116 if (!got_palette_index
) {
6117 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6118 /* use foreground color or request one from the font */
6119 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6120 if (colorrun
->paletteIndex
!= 0xffff)
6122 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6123 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6125 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6126 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6128 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6129 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6130 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6131 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6132 got_palette_index
= TRUE
;
6135 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6136 /* offsets are relative to glyph origin, nothing to fix up */
6137 if (glyphenum
->color_offsets
)
6138 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6139 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6141 glyphenum
->color_advances
[index
-1] += advance_adj
;
6142 colorrun
->glyphRun
.glyphCount
++;
6146 advance_adj
+= glyphenum
->advances
[g
];
6149 /* reset last advance */
6150 if (colorrun
->glyphRun
.glyphCount
)
6151 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6153 return colorrun
->glyphRun
.glyphCount
> 0;
6156 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6158 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6160 TRACE("%p, %p.\n", iface
, has_run
);
6164 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6165 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6167 if (colorglyphenum_build_color_run(glyphenum
))
6170 glyphenum
->current_layer
++;
6173 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6178 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6179 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6181 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6184 return E_NOT_VALID_STATE
;
6187 *run
= &glyphenum
->colorrun
;
6191 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6192 DWRITE_COLOR_GLYPH_RUN
const **run
)
6194 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6196 TRACE("%p, %p.\n", iface
, run
);
6198 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6201 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6202 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6204 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6206 TRACE("%p, %p.\n", iface
, run
);
6208 return colorglyphenum_get_current_run(glyphenum
, run
);
6211 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6213 colorglyphenum_QueryInterface
,
6214 colorglyphenum_AddRef
,
6215 colorglyphenum_Release
,
6216 colorglyphenum_MoveNext
,
6217 colorglyphenum_GetCurrentRun
,
6218 colorglyphenum1_GetCurrentRun
,
6221 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6222 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6223 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6225 struct dwrite_colorglyphenum
*colorglyphenum
;
6226 BOOL colorfont
, has_colored_glyph
;
6227 struct dwrite_fontface
*fontface
;
6232 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6234 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6235 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6237 return DWRITE_E_NOCOLOR
;
6239 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6240 if (!colorglyphenum
)
6241 return E_OUTOFMEMORY
;
6243 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6244 colorglyphenum
->refcount
= 1;
6245 colorglyphenum
->origin_x
= originX
;
6246 colorglyphenum
->origin_y
= originY
;
6247 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6248 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6249 colorglyphenum
->glyphs
= NULL
;
6250 colorglyphenum
->run
= *run
;
6251 colorglyphenum
->run
.glyphIndices
= NULL
;
6252 colorglyphenum
->run
.glyphAdvances
= NULL
;
6253 colorglyphenum
->run
.glyphOffsets
= NULL
;
6254 colorglyphenum
->palette
= palette
;
6255 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6256 colorglyphenum
->colr
.exists
= TRUE
;
6257 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6258 colorglyphenum
->current_layer
= 0;
6259 colorglyphenum
->max_layer_num
= 0;
6261 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6263 has_colored_glyph
= FALSE
;
6264 colorglyphenum
->has_regular_glyphs
= FALSE
;
6265 for (i
= 0; i
< run
->glyphCount
; i
++) {
6266 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6267 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6268 has_colored_glyph
= TRUE
;
6270 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6271 colorglyphenum
->has_regular_glyphs
= TRUE
;
6274 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6275 is supposed to proceed normally, like if font had no color info at all. */
6276 if (!has_colored_glyph
) {
6277 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6278 return DWRITE_E_NOCOLOR
;
6281 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6282 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6283 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6284 if (run
->glyphOffsets
) {
6285 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6286 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6287 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6290 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6291 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6292 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6293 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6294 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6295 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6296 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6297 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6299 if (run
->glyphAdvances
)
6300 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6303 for (i
= 0; i
< run
->glyphCount
; ++i
)
6304 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6305 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6308 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6313 /* IDWriteFontFaceReference */
6314 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6316 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6318 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6319 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6320 IsEqualIID(riid
, &IID_IUnknown
))
6323 IDWriteFontFaceReference1_AddRef(iface
);
6327 WARN("%s not implemented.\n", debugstr_guid(riid
));
6331 return E_NOINTERFACE
;
6334 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6336 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6337 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6339 TRACE("%p, refcount %u.\n", iface
, refcount
);
6344 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6346 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6347 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6349 TRACE("%p, refcount %u.\n", iface
, refcount
);
6353 IDWriteFontFile_Release(reference
->file
);
6354 IDWriteFactory7_Release(reference
->factory
);
6355 heap_free(reference
->axis_values
);
6356 heap_free(reference
);
6362 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6364 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6366 TRACE("%p, %p.\n", iface
, fontface
);
6368 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6371 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6372 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6374 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6375 DWRITE_FONT_FILE_TYPE file_type
;
6376 DWRITE_FONT_FACE_TYPE face_type
;
6377 IDWriteFontFace
*fontface
;
6382 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6384 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6388 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6389 simulations
, &fontface
);
6392 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6393 IDWriteFontFace_Release(fontface
);
6399 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6401 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6402 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6405 TRACE("%p, %p.\n", iface
, ref
);
6407 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6408 reference
->simulations
== other
->simulations
;
6409 if (reference
->axis_values_count
)
6411 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6412 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6418 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6420 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6422 TRACE("%p.\n", iface
);
6424 return reference
->index
;
6427 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6429 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6431 TRACE("%p.\n", iface
);
6433 return reference
->simulations
;
6436 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6438 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6439 IDWriteFontFileLoader
*loader
;
6444 TRACE("%p, %p.\n", iface
, file
);
6446 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6450 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6454 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6455 IDWriteFontFileLoader_Release(loader
);
6460 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6462 FIXME("%p.\n", iface
);
6467 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6469 FIXME("%p.\n", iface
);
6474 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6476 FIXME("%p, %p.\n", iface
, writetime
);
6481 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6483 FIXME("%p.\n", iface
);
6485 return DWRITE_LOCALITY_LOCAL
;
6488 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6490 FIXME("%p.\n", iface
);
6495 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6496 WCHAR
const *chars
, UINT32 count
)
6498 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6503 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6504 UINT16
const *glyphs
, UINT32 count
)
6506 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6511 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6512 UINT64 offset
, UINT64 size
)
6514 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6519 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6521 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6522 IDWriteFontFace3
*fontface3
;
6525 TRACE("%p, %p.\n", iface
, fontface
);
6527 /* FIXME: created instance should likely respect given axis. */
6528 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6531 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6532 IDWriteFontFace3_Release(fontface3
);
6538 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6540 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6542 TRACE("%p.\n", iface
);
6544 return reference
->axis_values_count
;
6547 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6548 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6550 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6552 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6554 if (value_count
< reference
->axis_values_count
)
6555 return E_NOT_SUFFICIENT_BUFFER
;
6557 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6562 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6564 fontfacereference_QueryInterface
,
6565 fontfacereference_AddRef
,
6566 fontfacereference_Release
,
6567 fontfacereference_CreateFontFace
,
6568 fontfacereference_CreateFontFaceWithSimulations
,
6569 fontfacereference_Equals
,
6570 fontfacereference_GetFontFaceIndex
,
6571 fontfacereference_GetSimulations
,
6572 fontfacereference_GetFontFile
,
6573 fontfacereference_GetLocalFileSize
,
6574 fontfacereference_GetFileSize
,
6575 fontfacereference_GetFileTime
,
6576 fontfacereference_GetLocality
,
6577 fontfacereference_EnqueueFontDownloadRequest
,
6578 fontfacereference_EnqueueCharacterDownloadRequest
,
6579 fontfacereference_EnqueueGlyphDownloadRequest
,
6580 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6581 fontfacereference1_CreateFontFace
,
6582 fontfacereference1_GetFontAxisValueCount
,
6583 fontfacereference1_GetFontAxisValues
,
6586 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6587 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6588 IDWriteFontFaceReference1
**ret
)
6590 struct dwrite_fontfacereference
*object
;
6594 if (!is_simulation_valid(simulations
))
6595 return E_INVALIDARG
;
6597 object
= heap_alloc_zero(sizeof(*object
));
6599 return E_OUTOFMEMORY
;
6601 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6602 object
->refcount
= 1;
6604 object
->factory
= factory
;
6605 IDWriteFactory7_AddRef(object
->factory
);
6606 object
->file
= file
;
6607 IDWriteFontFile_AddRef(object
->file
);
6608 object
->index
= index
;
6609 object
->simulations
= simulations
;
6610 if (axis_values_count
)
6612 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6614 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6615 return E_OUTOFMEMORY
;
6617 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6618 object
->axis_values_count
= axis_values_count
;
6621 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6626 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6628 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6630 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6632 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6634 IDWriteFontFileStream_AddRef(iface
);
6640 WARN("%s not implemented.\n", debugstr_guid(riid
));
6641 return E_NOINTERFACE
;
6644 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6646 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6647 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6648 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6652 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6654 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6655 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6657 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6660 release_inmemory_stream(stream
->data
);
6667 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6668 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6670 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6672 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6673 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6675 *fragment_context
= NULL
;
6677 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6678 *fragment_start
= NULL
;
6682 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6686 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6688 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6690 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6693 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6695 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6697 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6699 *size
= stream
->data
->size
;
6704 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6706 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6708 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6710 *last_writetime
= 0;
6715 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6716 inmemoryfilestream_QueryInterface
,
6717 inmemoryfilestream_AddRef
,
6718 inmemoryfilestream_Release
,
6719 inmemoryfilestream_ReadFileFragment
,
6720 inmemoryfilestream_ReleaseFileFragment
,
6721 inmemoryfilestream_GetFileSize
,
6722 inmemoryfilestream_GetLastWriteTime
,
6725 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6726 REFIID riid
, void **obj
)
6728 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6730 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6732 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6733 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6734 IsEqualIID(riid
, &IID_IUnknown
))
6737 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6741 WARN("%s not implemented.\n", debugstr_guid(riid
));
6745 return E_NOINTERFACE
;
6748 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6750 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6751 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6752 TRACE("(%p)->(%u)\n", loader
, ref
);
6756 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6758 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6759 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6762 TRACE("(%p)->(%u)\n", loader
, ref
);
6765 for (i
= 0; i
< loader
->count
; ++i
)
6766 release_inmemory_stream(loader
->streams
[i
]);
6767 heap_free(loader
->streams
);
6774 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6775 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6777 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6778 struct dwrite_inmemory_filestream
*stream
;
6781 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6785 if (key_size
!= sizeof(DWORD
))
6786 return E_INVALIDARG
;
6788 index
= *(DWORD
*)key
;
6790 if (index
>= loader
->count
)
6791 return E_INVALIDARG
;
6793 if (!(stream
= heap_alloc(sizeof(*stream
))))
6794 return E_OUTOFMEMORY
;
6796 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6798 stream
->data
= loader
->streams
[index
];
6799 InterlockedIncrement(&stream
->data
->ref
);
6801 *ret
= &stream
->IDWriteFontFileStream_iface
;
6806 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6807 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6809 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6810 struct dwrite_inmemory_stream_data
*stream
;
6813 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6817 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6818 return E_OUTOFMEMORY
;
6820 if (!(stream
= heap_alloc(sizeof(*stream
))))
6821 return E_OUTOFMEMORY
;
6824 stream
->size
= data_size
;
6825 stream
->owner
= owner
;
6826 if (stream
->owner
) {
6827 IUnknown_AddRef(stream
->owner
);
6828 stream
->data
= (void *)data
;
6831 if (!(stream
->data
= heap_alloc(data_size
))) {
6833 return E_OUTOFMEMORY
;
6835 memcpy(stream
->data
, data
, data_size
);
6838 key
= loader
->count
;
6839 loader
->streams
[loader
->count
++] = stream
;
6841 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6842 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6845 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6847 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6849 TRACE("%p.\n", iface
);
6851 return loader
->count
;
6854 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6856 inmemoryfontfileloader_QueryInterface
,
6857 inmemoryfontfileloader_AddRef
,
6858 inmemoryfontfileloader_Release
,
6859 inmemoryfontfileloader_CreateStreamFromKey
,
6860 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6861 inmemoryfontfileloader_GetFileCount
,
6864 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6866 struct dwrite_inmemory_fileloader
*loader
;
6870 loader
= heap_alloc_zero(sizeof(*loader
));
6872 return E_OUTOFMEMORY
;
6874 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6877 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6882 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6884 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6886 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6887 IsEqualIID(riid
, &IID_IUnknown
))
6890 IDWriteFontResource_AddRef(iface
);
6894 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6896 return E_NOINTERFACE
;
6899 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6901 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6902 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6904 TRACE("%p, refcount %u.\n", iface
, refcount
);
6909 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6911 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6912 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6914 TRACE("%p, refcount %u.\n", iface
, refcount
);
6918 IDWriteFactory7_Release(resource
->factory
);
6919 IDWriteFontFile_Release(resource
->file
);
6920 heap_free(resource
);
6926 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6928 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6930 TRACE("%p, %p.\n", iface
, fontfile
);
6932 *fontfile
= resource
->file
;
6933 IDWriteFontFile_AddRef(*fontfile
);
6938 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6940 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6942 TRACE("%p.\n", iface
);
6944 return resource
->face_index
;
6947 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6949 FIXME("%p.\n", iface
);
6954 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6955 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6957 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
6962 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
6963 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
6965 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
6970 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
6973 FIXME("%p, %u.\n", iface
, axis
);
6975 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
6978 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
6979 IDWriteLocalizedStrings
**names
)
6981 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
6986 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
6988 FIXME("%p, %u.\n", iface
, axis
);
6993 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
6994 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
6996 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7001 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7003 FIXME("%p.\n", iface
);
7008 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7009 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7010 IDWriteFontFace5
**fontface
)
7012 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7013 IDWriteFontFaceReference1
*reference
;
7016 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7018 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7019 simulations
, axis_values
, num_values
, &reference
);
7022 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7023 IDWriteFontFaceReference1_Release(reference
);
7029 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7030 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7031 IDWriteFontFaceReference1
**reference
)
7033 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7035 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7037 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7038 simulations
, axis_values
, num_values
, reference
);
7041 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7043 dwritefontresource_QueryInterface
,
7044 dwritefontresource_AddRef
,
7045 dwritefontresource_Release
,
7046 dwritefontresource_GetFontFile
,
7047 dwritefontresource_GetFontFaceIndex
,
7048 dwritefontresource_GetFontAxisCount
,
7049 dwritefontresource_GetDefaultFontAxisValues
,
7050 dwritefontresource_GetFontAxisRanges
,
7051 dwritefontresource_GetFontAxisAttributes
,
7052 dwritefontresource_GetAxisNames
,
7053 dwritefontresource_GetAxisValueNameCount
,
7054 dwritefontresource_GetAxisValueNames
,
7055 dwritefontresource_HasVariations
,
7056 dwritefontresource_CreateFontFace
,
7057 dwritefontresource_CreateFontFaceReference
,
7060 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7061 IDWriteFontResource
**ret
)
7063 struct dwrite_fontresource
*resource
;
7067 resource
= heap_alloc_zero(sizeof(*resource
));
7069 return E_OUTOFMEMORY
;
7071 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7072 resource
->refcount
= 1;
7073 resource
->face_index
= face_index
;
7074 resource
->file
= file
;
7075 IDWriteFontFile_AddRef(resource
->file
);
7076 resource
->factory
= factory
;
7077 IDWriteFactory7_AddRef(resource
->factory
);
7079 *ret
= &resource
->IDWriteFontResource_iface
;