4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2017 Nikolay Sivov for CodeWeavers
6 * Copyright 2014 Aric Stewart for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "dwrite_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
31 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
33 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
34 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
35 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
36 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
37 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
38 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
39 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
40 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
42 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
44 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
45 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
46 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
48 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
49 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
50 static const WCHAR semiW
[] = {'s','e','m','i',0};
51 static const WCHAR extW
[] = {'e','x','t',0};
52 static const WCHAR thinW
[] = {'t','h','i','n',0};
53 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
54 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
55 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
56 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
57 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
58 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
59 static const WCHAR boldW
[] = {'B','o','l','d',0};
60 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
61 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
62 static const WCHAR demiW
[] = {'d','e','m','i',0};
63 static const WCHAR spaceW
[] = {' ',0};
64 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
66 struct dwrite_font_propvec
{
72 struct dwrite_font_data
76 DWRITE_FONT_STYLE style
;
77 DWRITE_FONT_STRETCH stretch
;
78 DWRITE_FONT_WEIGHT weight
;
80 FONTSIGNATURE fontsig
;
81 UINT32 flags
; /* enum font_flags */
82 struct dwrite_font_propvec propvec
;
83 struct dwrite_cmap cmap
;
84 /* Static axis for weight/width/italic. */
85 DWRITE_FONT_AXIS_VALUE axis
[3];
87 DWRITE_FONT_METRICS1 metrics
;
88 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
89 IDWriteLocalizedStrings
*family_names
;
90 IDWriteLocalizedStrings
*names
;
92 /* data needed to create fontface instance */
93 DWRITE_FONT_FACE_TYPE face_type
;
94 IDWriteFontFile
*file
;
103 /* used to mark font as tested when scanning for simulation candidate */
104 unsigned int bold_sim_tested
: 1;
105 unsigned int oblique_sim_tested
: 1;
108 struct dwrite_fontfamily_data
112 IDWriteLocalizedStrings
*familyname
;
114 struct dwrite_font_data
**fonts
;
118 unsigned int has_normal_face
: 1;
119 unsigned int has_oblique_face
: 1;
120 unsigned int has_italic_face
: 1;
123 struct dwrite_fontcollection
125 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
128 IDWriteFactory7
*factory
;
129 struct dwrite_fontfamily_data
**family_data
;
134 struct dwrite_fontfamily
136 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
137 IDWriteFontList2 IDWriteFontList2_iface
;
140 struct dwrite_fontfamily_data
*data
;
141 struct dwrite_fontcollection
*collection
;
144 struct dwrite_fontlist
146 IDWriteFontList2 IDWriteFontList2_iface
;
149 struct dwrite_font_data
**fonts
;
151 struct dwrite_fontfamily
*family
;
156 IDWriteFont3 IDWriteFont3_iface
;
159 DWRITE_FONT_STYLE style
;
160 struct dwrite_font_data
*data
;
161 struct dwrite_fontfamily
*family
;
164 enum runanalysis_flags
{
165 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
166 RUNANALYSIS_BITMAP_READY
= 1 << 1,
167 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
170 struct dwrite_glyphrunanalysis
172 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
175 DWRITE_RENDERING_MODE1 rendering_mode
;
176 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
177 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
180 D2D_POINT_2F
*origins
;
185 UINT32 max_glyph_bitmap_size
;
188 struct dwrite_colorglyphenum
190 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
193 FLOAT origin_x
; /* original run origin */
196 IDWriteFontFace5
*fontface
; /* for convenience */
197 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
198 DWRITE_GLYPH_RUN run
; /* base run */
199 UINT32 palette
; /* palette index to get layer color from */
200 FLOAT
*advances
; /* original or measured advances for base glyphs */
201 FLOAT
*color_advances
; /* returned color run points to this */
202 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
203 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
204 UINT16
*glyphindices
; /* returned color run points to this */
205 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
206 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
207 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
208 UINT16 max_layer_num
; /* max number of layers for this run */
209 struct dwrite_fonttable colr
; /* used to access layers */
212 #define GLYPH_BLOCK_SHIFT 8
213 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
214 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
215 #define GLYPH_MAX 65536
217 struct dwrite_fontfile
219 IDWriteFontFile IDWriteFontFile_iface
;
222 IDWriteFontFileLoader
*loader
;
225 IDWriteFontFileStream
*stream
;
228 struct dwrite_fontfacereference
230 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
233 IDWriteFontFile
*file
;
236 DWRITE_FONT_AXIS_VALUE
*axis_values
;
237 UINT32 axis_values_count
;
238 IDWriteFactory7
*factory
;
241 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
243 struct dwrite_fontresource
245 IDWriteFontResource IDWriteFontResource_iface
;
248 IDWriteFontFile
*file
;
250 IDWriteFactory7
*factory
;
253 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
255 struct dwrite_fontface
*fontface
= context
;
258 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
259 size
, data_context
, &exists
)) || !exists
)
263 *data_context
= NULL
;
267 static void dwrite_release_font_table(void *context
, void *data_context
)
269 struct dwrite_fontface
*fontface
= context
;
270 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
273 static UINT16
dwrite_get_font_upem(void *context
)
275 struct dwrite_fontface
*fontface
= context
;
276 return fontface
->metrics
.designUnitsPerEm
;
279 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
281 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
282 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
285 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
287 struct dwrite_fontface
*fontface
= context
;
288 return !!dwritefontface_get_glyph(fontface
, codepoint
);
291 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
293 struct dwrite_fontface
*fontface
= context
;
294 return dwritefontface_get_glyph(fontface
, codepoint
);
297 static const struct shaping_font_ops dwrite_font_ops
=
299 dwrite_grab_font_table
,
300 dwrite_release_font_table
,
301 dwrite_get_font_upem
,
306 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
308 if (fontface
->shaping_cache
)
309 return fontface
->shaping_cache
;
311 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
314 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
316 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
319 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
321 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
324 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
326 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
329 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
331 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
333 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
336 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
338 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
341 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
343 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
346 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
348 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
351 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
353 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
356 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
358 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
361 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
363 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
366 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
368 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
371 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
373 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
376 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
378 static const DWRITE_GLYPH_METRICS nil
;
379 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
381 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
382 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
386 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
388 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
391 /* start new block */
392 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
394 return E_OUTOFMEMORY
;
397 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
401 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
405 if (table
->data
|| !table
->exists
)
408 table
->exists
= FALSE
;
409 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
411 if (FAILED(hr
) || !table
->exists
) {
412 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
419 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
420 struct dwrite_font_propvec
*vec
)
422 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
423 vec
->style
= style
* 7.0f
;
424 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
427 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
429 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
432 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
434 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
437 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
439 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
440 return &fontface
->vdmx
;
443 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
445 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
446 return &fontface
->gasp
;
449 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
451 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
452 return &fontface
->cpal
;
455 static void addref_font_data(struct dwrite_font_data
*data
)
457 InterlockedIncrement(&data
->ref
);
460 static void release_font_data(struct dwrite_font_data
*data
)
464 if (InterlockedDecrement(&data
->ref
) > 0)
467 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
469 if (data
->info_strings
[i
])
470 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
473 IDWriteLocalizedStrings_Release(data
->names
);
475 if (data
->family_names
)
476 IDWriteLocalizedStrings_Release(data
->family_names
);
478 dwrite_cmap_release(&data
->cmap
);
479 IDWriteFontFile_Release(data
->file
);
480 heap_free(data
->facename
);
484 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
488 if (InterlockedDecrement(&data
->refcount
) > 0)
491 for (i
= 0; i
< data
->count
; ++i
)
492 release_font_data(data
->fonts
[i
]);
493 heap_free(data
->fonts
);
494 IDWriteLocalizedStrings_Release(data
->familyname
);
498 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
500 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
501 fontface
->cached
= NULL
;
504 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
506 UINT32 left_key_size
, right_key_size
;
507 const void *left_key
, *right_key
;
513 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
517 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
521 if (left_key_size
!= right_key_size
)
524 return !memcmp(left_key
, right_key
, left_key_size
);
527 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
529 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
531 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
533 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
534 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
535 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
536 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
537 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
538 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
539 IsEqualIID(riid
, &IID_IUnknown
))
543 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
544 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
550 if (InterlockedIncrement(&fontface
->refcount
) == 1)
552 InterlockedDecrement(&fontface
->refcount
);
559 WARN("%s not implemented.\n", debugstr_guid(riid
));
561 return E_NOINTERFACE
;
564 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
566 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
567 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
569 TRACE("%p, refcount %u.\n", iface
, refcount
);
574 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
576 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
577 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
579 TRACE("%p, refcount %u.\n", iface
, refcount
);
585 if (fontface
->cached
)
587 factory_lock(fontface
->factory
);
588 list_remove(&fontface
->cached
->entry
);
589 factory_unlock(fontface
->factory
);
590 heap_free(fontface
->cached
);
592 release_scriptshaping_cache(fontface
->shaping_cache
);
593 if (fontface
->vdmx
.context
)
594 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
595 if (fontface
->gasp
.context
)
596 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
597 if (fontface
->cpal
.context
)
598 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
599 if (fontface
->colr
.context
)
600 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
601 for (i
= 0; i
< fontface
->file_count
; i
++)
603 if (fontface
->files
[i
])
604 IDWriteFontFile_Release(fontface
->files
[i
]);
606 if (fontface
->stream
)
607 IDWriteFontFileStream_Release(fontface
->stream
);
608 heap_free(fontface
->files
);
610 IDWriteLocalizedStrings_Release(fontface
->names
);
611 if (fontface
->family_names
)
612 IDWriteLocalizedStrings_Release(fontface
->family_names
);
613 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
615 if (fontface
->info_strings
[i
])
616 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
619 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
620 heap_free(fontface
->glyphs
[i
]);
622 freetype_notify_cacheremove(iface
);
624 dwrite_cmap_release(&fontface
->cmap
);
625 IDWriteFactory7_Release(fontface
->factory
);
632 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
634 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
636 TRACE("%p.\n", iface
);
638 return fontface
->type
;
641 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
642 IDWriteFontFile
**fontfiles
)
644 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
647 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
649 if (fontfiles
== NULL
)
651 *number_of_files
= fontface
->file_count
;
655 if (*number_of_files
< fontface
->file_count
)
658 for (i
= 0; i
< fontface
->file_count
; i
++)
660 IDWriteFontFile_AddRef(fontface
->files
[i
]);
661 fontfiles
[i
] = fontface
->files
[i
];
667 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
669 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
671 TRACE("%p.\n", iface
);
673 return fontface
->index
;
676 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
678 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
680 TRACE("%p.\n", iface
);
682 return fontface
->simulations
;
685 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
687 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
689 TRACE("%p.\n", iface
);
691 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
694 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
696 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
698 TRACE("%p, %p.\n", iface
, metrics
);
700 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
703 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
705 TRACE("%p.\n", iface
);
707 return freetype_get_glyphcount(iface
);
710 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
711 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
713 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
717 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
723 FIXME("sideways metrics are not supported.\n");
725 for (i
= 0; i
< glyph_count
; i
++) {
726 DWRITE_GLYPH_METRICS metrics
;
728 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
730 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
731 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
741 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
742 UINT32 count
, UINT16
*glyphs
)
744 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
747 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
754 memset(glyphs
, 0, count
* sizeof(*glyphs
));
758 for (i
= 0; i
< count
; ++i
)
759 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
764 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
765 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
767 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
768 struct file_stream_desc stream_desc
;
770 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
772 stream_desc
.stream
= fontface
->stream
;
773 stream_desc
.face_type
= fontface
->type
;
774 stream_desc
.face_index
= fontface
->index
;
775 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
778 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
780 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
782 TRACE("%p, %p.\n", iface
, table_context
);
784 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
787 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
788 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
789 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
791 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
792 count
, is_sideways
, is_rtl
, sink
);
794 if (!glyphs
|| !sink
)
798 FIXME("sideways mode is not supported.\n");
800 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
803 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
804 float ppem
, unsigned int gasp
)
806 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
810 case DWRITE_MEASURING_MODE_NATURAL
:
812 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
813 mode
= DWRITE_RENDERING_MODE_NATURAL
;
815 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
818 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
819 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
821 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
822 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
831 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
832 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
834 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
838 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
841 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
845 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
846 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
849 ppem
= emSize
* ppdip
;
851 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
852 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
856 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
857 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
861 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
862 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
864 DWRITE_FONT_METRICS1 metrics1
;
865 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
866 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
870 static inline int round_metric(FLOAT metric
)
872 return (int)floorf(metric
+ 0.5f
);
875 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
877 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
880 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
883 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
884 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
885 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
887 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
888 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
889 DWRITE_MEASURING_MODE mode
;
894 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
895 glyph_count
, metrics
, is_sideways
);
897 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
898 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
900 size
= emSize
* ppdip
;
901 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
902 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
904 for (i
= 0; i
< glyph_count
; i
++) {
905 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
906 DWRITE_GLYPH_METRICS design
;
909 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
913 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
915 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
917 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
919 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
920 SCALE_METRIC(leftSideBearing
);
921 SCALE_METRIC(rightSideBearing
);
922 SCALE_METRIC(topSideBearing
);
923 SCALE_METRIC(advanceHeight
);
924 SCALE_METRIC(bottomSideBearing
);
925 SCALE_METRIC(verticalOriginY
);
932 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
934 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
936 TRACE("%p, %p.\n", iface
, metrics
);
938 *metrics
= fontface
->metrics
;
941 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
942 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
944 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
945 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
946 UINT16 ascent
, descent
;
949 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
951 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
952 memset(metrics
, 0, sizeof(*metrics
));
956 em_size
*= pixels_per_dip
;
957 if (m
&& m
->m22
!= 0.0f
)
958 em_size
*= fabs(m
->m22
);
960 scale
= em_size
/ design
->designUnitsPerEm
;
961 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
963 ascent
= round_metric(design
->ascent
* scale
);
964 descent
= round_metric(design
->descent
* scale
);
967 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
968 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
969 metrics
->ascent
= round_metric(ascent
/ scale
);
970 metrics
->descent
= round_metric(descent
/ scale
);
972 SCALE_METRIC(lineGap
);
973 SCALE_METRIC(capHeight
);
974 SCALE_METRIC(xHeight
);
975 SCALE_METRIC(underlinePosition
);
976 SCALE_METRIC(underlineThickness
);
977 SCALE_METRIC(strikethroughPosition
);
978 SCALE_METRIC(strikethroughThickness
);
979 SCALE_METRIC(glyphBoxLeft
);
980 SCALE_METRIC(glyphBoxTop
);
981 SCALE_METRIC(glyphBoxRight
);
982 SCALE_METRIC(glyphBoxBottom
);
983 SCALE_METRIC(subscriptPositionX
);
984 SCALE_METRIC(subscriptPositionY
);
985 SCALE_METRIC(subscriptSizeX
);
986 SCALE_METRIC(subscriptSizeY
);
987 SCALE_METRIC(superscriptPositionX
);
988 SCALE_METRIC(superscriptPositionY
);
989 SCALE_METRIC(superscriptSizeX
);
990 SCALE_METRIC(superscriptSizeY
);
992 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
998 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1000 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1002 TRACE("%p, %p.\n", iface
, metrics
);
1004 *metrics
= fontface
->caret
;
1007 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1008 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1010 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1012 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1015 if (max_count
&& !ranges
)
1016 return E_INVALIDARG
;
1018 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1019 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1022 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1024 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1026 TRACE("%p.\n", iface
);
1028 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1031 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1032 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1034 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1039 FIXME("Sideways mode is not supported.\n");
1041 switch (measuring_mode
)
1043 case DWRITE_MEASURING_MODE_NATURAL
:
1044 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1045 glyph
, measuring_mode
, &has_contours
);
1047 advance
+= adjustment
;
1050 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1051 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1056 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1057 FIXME("Transform is not supported.\n");
1059 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1062 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1064 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1068 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1073 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1074 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1076 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1079 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1082 FIXME("sideways mode not supported\n");
1084 for (i
= 0; i
< glyph_count
; ++i
)
1086 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1087 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1093 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1094 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1095 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1097 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1098 DWRITE_MEASURING_MODE measuring_mode
;
1101 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1102 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1104 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1105 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1106 return E_INVALIDARG
;
1109 if (em_size
== 0.0f
) {
1110 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1114 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1115 for (i
= 0; i
< glyph_count
; ++i
)
1117 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1118 glyphs
[i
], is_sideways
);
1124 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1125 const UINT16
*indices
, INT32
*adjustments
)
1127 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1130 TRACE("%p, %u, %p, %p.\n", iface
, count
, indices
, adjustments
);
1132 if (!(indices
|| adjustments
) || !count
)
1133 return E_INVALIDARG
;
1135 if (!indices
|| count
== 1) {
1136 memset(adjustments
, 0, count
*sizeof(INT32
));
1137 return E_INVALIDARG
;
1140 if (!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
))
1142 memset(adjustments
, 0, count
*sizeof(INT32
));
1146 for (i
= 0; i
< count
-1; i
++)
1147 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1148 adjustments
[count
-1] = 0;
1153 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1155 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1157 TRACE("%p.\n", iface
);
1159 return !!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1162 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1163 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1164 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1166 DWRITE_GRID_FIT_MODE gridfitmode
;
1167 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1168 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1171 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1172 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1174 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1176 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1178 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1181 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1183 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1185 TRACE("%p.\n", iface
);
1187 return !!(fontface
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1190 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1192 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1194 TRACE("%p.\n", iface
);
1196 return !!(fontface
->flags
& FONT_IS_COLORED
);
1199 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1201 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1203 TRACE("%p.\n", iface
);
1205 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1208 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1210 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1212 TRACE("%p.\n", iface
);
1214 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1217 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1218 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1220 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1222 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1224 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1227 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1228 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1229 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1230 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1232 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1236 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1237 measuringmode
, params
, renderingmode
, gridfitmode
);
1240 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1243 FIXME("sideways mode not supported\n");
1245 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1247 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1248 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1250 IDWriteRenderingParams2
*params2
;
1253 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1255 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1256 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1257 IDWriteRenderingParams2_Release(params2
);
1260 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1263 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1265 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1267 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1268 if (emSize
>= emthreshold
)
1269 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1271 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1274 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1275 if (emSize
>= emthreshold
)
1276 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1277 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1278 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1280 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1281 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1287 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1288 IDWriteFontFaceReference
**reference
)
1290 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1292 TRACE("%p, %p.\n", iface
, reference
);
1294 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1295 IDWriteFontFaceReference_AddRef(*reference
);
1300 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1302 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1304 TRACE("%p, %p.\n", iface
, panose
);
1306 *panose
= fontface
->panose
;
1309 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1311 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1313 TRACE("%p.\n", iface
);
1315 return fontface
->weight
;
1318 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1320 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1322 TRACE("%p.\n", iface
);
1324 return fontface
->stretch
;
1327 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1329 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1331 TRACE("%p.\n", iface
);
1333 return fontface
->style
;
1336 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1338 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1340 TRACE("%p, %p.\n", iface
, names
);
1342 return clone_localizedstrings(fontface
->family_names
, names
);
1345 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1347 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1349 TRACE("%p, %p.\n", iface
, names
);
1351 return clone_localizedstrings(fontface
->names
, names
);
1354 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1355 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1356 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1363 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1364 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1369 if (!strings_cache
[stringid
])
1371 struct file_stream_desc desc
= *stream_desc
;
1374 hr
= get_filestream_from_file(file
, &desc
.stream
);
1376 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1378 if (!stream_desc
->stream
&& desc
.stream
)
1379 IDWriteFontFileStream_Release(desc
.stream
);
1382 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1384 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1392 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1393 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1395 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1396 struct file_stream_desc stream_desc
;
1398 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1400 stream_desc
.stream
= fontface
->stream
;
1401 stream_desc
.face_index
= fontface
->index
;
1402 stream_desc
.face_type
= fontface
->type
;
1403 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1406 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1408 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1410 TRACE("%p, %#x.\n", iface
, ch
);
1412 return !!dwritefontface_get_glyph(fontface
, ch
);
1415 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1416 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1417 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1419 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1423 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1424 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1427 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1430 FIXME("sideways mode not supported\n");
1432 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1434 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1435 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1437 IDWriteRenderingParams3
*params3
;
1440 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1442 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1443 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1444 IDWriteRenderingParams3_Release(params3
);
1447 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1450 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1452 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1454 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1455 if (emSize
>= emthreshold
)
1456 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1458 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1461 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1462 if (emSize
>= emthreshold
)
1463 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1464 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1465 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1467 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1468 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1474 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1476 FIXME("%p, %#x: stub\n", iface
, ch
);
1481 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1483 FIXME("%p, %u: stub\n", iface
, glyph
);
1488 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1489 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1491 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1496 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1497 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1499 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1504 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1505 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1507 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1512 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1514 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1516 TRACE("%p.\n", iface
);
1518 return fontface
->glyph_image_formats
;
1521 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1522 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1524 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1529 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1531 FIXME("%p, %p: stub\n", iface
, context
);
1534 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1536 FIXME("%p: stub\n", iface
);
1541 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1544 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1549 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1554 FIXME("%p: stub\n", iface
);
1559 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1561 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1563 TRACE("%p, %p.\n", iface
, resource
);
1565 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->files
[0], fontface
->index
, resource
);
1568 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1570 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1572 TRACE("%p, %p.\n", iface
, other
);
1574 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1577 /* TODO: add variations support */
1579 return fontface
->index
== other_face
->index
&&
1580 fontface
->simulations
== other_face
->simulations
&&
1581 is_same_fontfile(fontface
->files
[0], other_face
->files
[0]);
1584 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1586 dwritefontface_QueryInterface
,
1587 dwritefontface_AddRef
,
1588 dwritefontface_Release
,
1589 dwritefontface_GetType
,
1590 dwritefontface_GetFiles
,
1591 dwritefontface_GetIndex
,
1592 dwritefontface_GetSimulations
,
1593 dwritefontface_IsSymbolFont
,
1594 dwritefontface_GetMetrics
,
1595 dwritefontface_GetGlyphCount
,
1596 dwritefontface_GetDesignGlyphMetrics
,
1597 dwritefontface_GetGlyphIndices
,
1598 dwritefontface_TryGetFontTable
,
1599 dwritefontface_ReleaseFontTable
,
1600 dwritefontface_GetGlyphRunOutline
,
1601 dwritefontface_GetRecommendedRenderingMode
,
1602 dwritefontface_GetGdiCompatibleMetrics
,
1603 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1604 dwritefontface1_GetMetrics
,
1605 dwritefontface1_GetGdiCompatibleMetrics
,
1606 dwritefontface1_GetCaretMetrics
,
1607 dwritefontface1_GetUnicodeRanges
,
1608 dwritefontface1_IsMonospacedFont
,
1609 dwritefontface1_GetDesignGlyphAdvances
,
1610 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1611 dwritefontface1_GetKerningPairAdjustments
,
1612 dwritefontface1_HasKerningPairs
,
1613 dwritefontface1_GetRecommendedRenderingMode
,
1614 dwritefontface1_GetVerticalGlyphVariants
,
1615 dwritefontface1_HasVerticalGlyphVariants
,
1616 dwritefontface2_IsColorFont
,
1617 dwritefontface2_GetColorPaletteCount
,
1618 dwritefontface2_GetPaletteEntryCount
,
1619 dwritefontface2_GetPaletteEntries
,
1620 dwritefontface2_GetRecommendedRenderingMode
,
1621 dwritefontface3_GetFontFaceReference
,
1622 dwritefontface3_GetPanose
,
1623 dwritefontface3_GetWeight
,
1624 dwritefontface3_GetStretch
,
1625 dwritefontface3_GetStyle
,
1626 dwritefontface3_GetFamilyNames
,
1627 dwritefontface3_GetFaceNames
,
1628 dwritefontface3_GetInformationalStrings
,
1629 dwritefontface3_HasCharacter
,
1630 dwritefontface3_GetRecommendedRenderingMode
,
1631 dwritefontface3_IsCharacterLocal
,
1632 dwritefontface3_IsGlyphLocal
,
1633 dwritefontface3_AreCharactersLocal
,
1634 dwritefontface3_AreGlyphsLocal
,
1635 dwritefontface4_GetGlyphImageFormats_
,
1636 dwritefontface4_GetGlyphImageFormats
,
1637 dwritefontface4_GetGlyphImageData
,
1638 dwritefontface4_ReleaseGlyphImageData
,
1639 dwritefontface5_GetFontAxisValueCount
,
1640 dwritefontface5_GetFontAxisValues
,
1641 dwritefontface5_HasVariations
,
1642 dwritefontface5_GetFontResource
,
1643 dwritefontface5_Equals
,
1646 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1648 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1649 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1652 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1654 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1655 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1658 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1660 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1661 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1664 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1665 IDWriteFontFace3
**ret
)
1667 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1669 TRACE("%p, %p.\n", iface
, ret
);
1671 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1672 IDWriteFontFace3_AddRef(*ret
);
1677 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1678 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1680 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1681 DWRITE_FONT_FILE_TYPE file_type
;
1682 DWRITE_FONT_FACE_TYPE face_type
;
1683 IDWriteFontFace
*face
;
1688 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1690 hr
= IDWriteFontFile_Analyze(fontface
->files
[0], &is_supported
, &file_type
, &face_type
, &face_num
);
1694 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, fontface
->files
, fontface
->index
,
1695 simulations
, &face
);
1698 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1699 IDWriteFontFace_Release(face
);
1705 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1707 FIXME("%p, %p.\n", iface
, ref
);
1712 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1714 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1716 TRACE("%p.\n", iface
);
1718 return fontface
->index
;
1721 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1723 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1725 TRACE("%p.\n", iface
);
1727 return fontface
->simulations
;
1730 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1732 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1734 TRACE("%p, %p.\n", iface
, file
);
1736 *file
= fontface
->files
[0];
1737 IDWriteFontFile_AddRef(*file
);
1742 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1744 FIXME("%p.\n", iface
);
1749 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1751 FIXME("%p.\n", iface
);
1756 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1758 FIXME("%p, %p.\n", iface
, writetime
);
1763 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1765 FIXME("%p.\n", iface
);
1767 return DWRITE_LOCALITY_LOCAL
;
1770 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1772 FIXME("%p.\n", iface
);
1777 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1778 WCHAR
const *chars
, UINT32 count
)
1780 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1785 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1786 UINT16
const *glyphs
, UINT32 count
)
1788 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1793 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1794 UINT64 offset
, UINT64 size
)
1796 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1801 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1803 dwritefontface_reference_QueryInterface
,
1804 dwritefontface_reference_AddRef
,
1805 dwritefontface_reference_Release
,
1806 dwritefontface_reference_CreateFontFace
,
1807 dwritefontface_reference_CreateFontFaceWithSimulations
,
1808 dwritefontface_reference_Equals
,
1809 dwritefontface_reference_GetFontFaceIndex
,
1810 dwritefontface_reference_GetSimulations
,
1811 dwritefontface_reference_GetFontFile
,
1812 dwritefontface_reference_GetLocalFileSize
,
1813 dwritefontface_reference_GetFileSize
,
1814 dwritefontface_reference_GetFileTime
,
1815 dwritefontface_reference_GetLocality
,
1816 dwritefontface_reference_EnqueueFontDownloadRequest
,
1817 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1818 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1819 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1822 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1824 struct dwrite_font_data
*data
= font
->data
;
1825 struct fontface_desc desc
;
1826 struct list
*cached_list
;
1831 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1832 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1836 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1839 desc
.factory
= font
->family
->collection
->factory
;
1840 desc
.face_type
= data
->face_type
;
1841 desc
.files
= &data
->file
;
1842 desc
.files_number
= 1;
1843 desc
.index
= data
->face_index
;
1844 desc
.simulations
= data
->simulations
;
1845 desc
.font_data
= data
;
1846 hr
= create_fontface(&desc
, cached_list
, fontface
);
1848 IDWriteFontFileStream_Release(desc
.stream
);
1852 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1854 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1856 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1857 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1858 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1859 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1860 IsEqualIID(riid
, &IID_IUnknown
))
1863 IDWriteFont3_AddRef(iface
);
1867 WARN("%s not implemented.\n", debugstr_guid(riid
));
1870 return E_NOINTERFACE
;
1873 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1875 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1876 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
1878 TRACE("%p, refcount %d.\n", iface
, refcount
);
1883 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1885 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1886 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
1888 TRACE("%p, refcount %d.\n", iface
, refcount
);
1892 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
1893 release_font_data(font
->data
);
1900 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1902 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1904 TRACE("%p, %p.\n", iface
, family
);
1906 *family
= (IDWriteFontFamily
*)font
->family
;
1907 IDWriteFontFamily_AddRef(*family
);
1911 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1913 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1915 TRACE("%p.\n", iface
);
1917 return font
->data
->weight
;
1920 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1922 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1924 TRACE("%p.\n", iface
);
1926 return font
->data
->stretch
;
1929 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1931 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1933 TRACE("%p.\n", iface
);
1938 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1940 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1942 TRACE("%p.\n", iface
);
1944 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
1947 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1949 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1951 TRACE("%p, %p.\n", iface
, names
);
1953 return clone_localizedstrings(font
->data
->names
, names
);
1956 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1957 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1959 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1960 struct dwrite_font_data
*data
= font
->data
;
1961 struct file_stream_desc stream_desc
;
1963 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
1965 /* Stream will be created if necessary. */
1966 stream_desc
.stream
= NULL
;
1967 stream_desc
.face_index
= data
->face_index
;
1968 stream_desc
.face_type
= data
->face_type
;
1969 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
1972 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1974 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1976 TRACE("%p.\n", iface
);
1978 return font
->data
->simulations
;
1981 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1983 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1985 TRACE("%p, %p.\n", iface
, metrics
);
1987 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
1990 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
1993 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
1994 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
1998 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2000 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2002 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2004 *exists
= dwritefont_has_character(font
, ch
);
2009 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2011 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2013 TRACE("%p, %p.\n", iface
, fontface
);
2015 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2018 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2020 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2022 TRACE("%p, %p.\n", iface
, metrics
);
2024 *metrics
= font
->data
->metrics
;
2027 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2029 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2031 TRACE("%p, %p.\n", iface
, panose
);
2033 *panose
= font
->data
->panose
;
2036 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2039 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2041 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2044 if (max_count
&& !ranges
)
2045 return E_INVALIDARG
;
2047 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2048 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2051 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2053 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2055 TRACE("%p.\n", iface
);
2057 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2060 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2062 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2064 TRACE("%p.\n", iface
);
2066 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2069 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2071 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2073 TRACE("%p, %p.\n", iface
, fontface
);
2075 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2078 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2080 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2082 TRACE("%p, %p.\n", iface
, other
);
2084 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2087 return font
->data
->face_index
== other_font
->data
->face_index
2088 && font
->data
->simulations
== other_font
->data
->simulations
2089 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2092 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2094 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2096 TRACE("%p, %p.\n", iface
, reference
);
2098 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2099 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2100 (IDWriteFontFaceReference1
**)reference
);
2103 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2105 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2107 TRACE("%p, %#x.\n", iface
, ch
);
2109 return dwritefont_has_character(font
, ch
);
2112 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2114 FIXME("%p: stub.\n", iface
);
2116 return DWRITE_LOCALITY_LOCAL
;
2119 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2120 dwritefont_QueryInterface
,
2123 dwritefont_GetFontFamily
,
2124 dwritefont_GetWeight
,
2125 dwritefont_GetStretch
,
2126 dwritefont_GetStyle
,
2127 dwritefont_IsSymbolFont
,
2128 dwritefont_GetFaceNames
,
2129 dwritefont_GetInformationalStrings
,
2130 dwritefont_GetSimulations
,
2131 dwritefont_GetMetrics
,
2132 dwritefont_HasCharacter
,
2133 dwritefont_CreateFontFace
,
2134 dwritefont1_GetMetrics
,
2135 dwritefont1_GetPanose
,
2136 dwritefont1_GetUnicodeRanges
,
2137 dwritefont1_IsMonospacedFont
,
2138 dwritefont2_IsColorFont
,
2139 dwritefont3_CreateFontFace
,
2141 dwritefont3_GetFontFaceReference
,
2142 dwritefont3_HasCharacter
,
2143 dwritefont3_GetLocality
2146 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2150 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2151 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2154 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2158 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2159 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2162 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2166 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2168 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2169 IDWriteFontFaceReference1_iface
);
2172 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2174 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2175 *lf
= font
->data
->lf
;
2178 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2180 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2184 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2186 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2187 *fontsig
= font
->data
->fontsig
;
2191 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2193 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2194 *fontsig
= fontface
->fontsig
;
2198 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2200 struct dwrite_font
*object
;
2204 if (!(object
= heap_alloc(sizeof(*object
))))
2205 return E_OUTOFMEMORY
;
2207 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2208 object
->refcount
= 1;
2209 object
->family
= family
;
2210 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2211 object
->data
= family
->data
->fonts
[index
];
2212 object
->style
= object
->data
->style
;
2213 addref_font_data(object
->data
);
2215 *font
= &object
->IDWriteFont3_iface
;
2220 /* IDWriteFontList2 */
2221 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2223 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2225 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2226 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2227 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2228 IsEqualIID(riid
, &IID_IUnknown
))
2231 IDWriteFontList2_AddRef(iface
);
2235 WARN("%s not implemented.\n", debugstr_guid(riid
));
2238 return E_NOINTERFACE
;
2241 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2243 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2244 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2246 TRACE("%p, refcount %u.\n", iface
, refcount
);
2251 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2253 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2254 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2256 TRACE("%p, refcount %u.\n", iface
, refcount
);
2262 for (i
= 0; i
< fontlist
->font_count
; i
++)
2263 release_font_data(fontlist
->fonts
[i
]);
2264 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2265 heap_free(fontlist
->fonts
);
2266 heap_free(fontlist
);
2272 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2274 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2275 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2278 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2280 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2282 TRACE("%p.\n", iface
);
2284 return fontlist
->font_count
;
2287 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2289 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2291 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2295 if (fontlist
->font_count
== 0)
2298 if (index
>= fontlist
->font_count
)
2299 return E_INVALIDARG
;
2301 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2304 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2306 FIXME("%p, %u.\n", iface
, index
);
2308 return DWRITE_LOCALITY_LOCAL
;
2311 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2313 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2315 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2319 if (fontlist
->font_count
== 0)
2322 if (index
>= fontlist
->font_count
)
2325 return create_font(fontlist
->family
, index
, font
);
2328 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2329 IDWriteFontFaceReference
**reference
)
2334 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2338 hr
= IDWriteFontList2_GetFont(iface
, index
, &font
);
2342 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2343 IDWriteFont3_Release(font
);
2348 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2350 FIXME("%p, %p.\n", iface
, fontset
);
2355 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2357 dwritefontlist_QueryInterface
,
2358 dwritefontlist_AddRef
,
2359 dwritefontlist_Release
,
2360 dwritefontlist_GetFontCollection
,
2361 dwritefontlist_GetFontCount
,
2362 dwritefontlist_GetFont
,
2363 dwritefontlist1_GetFontLocality
,
2364 dwritefontlist1_GetFont
,
2365 dwritefontlist1_GetFontFaceReference
,
2366 dwritefontlist2_GetFontSet
,
2369 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2371 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2373 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2375 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2376 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2377 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2378 IsEqualIID(riid
, &IID_IUnknown
))
2382 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2383 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2384 IsEqualIID(riid
, &IID_IDWriteFontList
))
2386 *obj
= &family
->IDWriteFontList2_iface
;
2390 WARN("%s not implemented.\n", debugstr_guid(riid
));
2392 return E_NOINTERFACE
;
2395 IUnknown_AddRef((IUnknown
*)*obj
);
2399 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2401 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2402 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2404 TRACE("%p, %u.\n", iface
, refcount
);
2409 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2411 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2412 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2414 TRACE("%p, %u.\n", iface
, refcount
);
2418 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2419 release_fontfamily_data(family
->data
);
2426 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2428 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2430 TRACE("%p, %p.\n", iface
, collection
);
2432 *collection
= (IDWriteFontCollection
*)family
->collection
;
2433 IDWriteFontCollection_AddRef(*collection
);
2437 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2439 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2441 TRACE("%p.\n", iface
);
2443 return family
->data
->count
;
2446 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2448 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2450 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2454 if (!family
->data
->count
)
2457 if (index
>= family
->data
->count
)
2458 return E_INVALIDARG
;
2460 return create_font(family
, index
, (IDWriteFont3
**)font
);
2463 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2465 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2467 TRACE("%p, %p.\n", iface
, names
);
2469 return clone_localizedstrings(family
->data
->familyname
, names
);
2472 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2473 const struct dwrite_font_propvec
*req
)
2475 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2476 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2477 FLOAT cur_req_prod
, next_req_prod
;
2479 if (next_to_req
< cur_to_req
)
2482 if (next_to_req
> cur_to_req
)
2485 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2486 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2488 if (next_req_prod
> cur_req_prod
)
2491 if (next_req_prod
< cur_req_prod
)
2494 if (next
->stretch
> cur
->stretch
)
2496 if (next
->stretch
< cur
->stretch
)
2499 if (next
->style
> cur
->style
)
2501 if (next
->style
< cur
->style
)
2504 if (next
->weight
> cur
->weight
)
2506 if (next
->weight
< cur
->weight
)
2509 /* full match, no reason to prefer new variant */
2513 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2514 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2516 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2517 struct dwrite_font_propvec req
;
2520 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2522 if (!family
->data
->count
)
2525 return DWRITE_E_NOFONT
;
2528 init_font_prop_vec(weight
, stretch
, style
, &req
);
2531 for (i
= 1; i
< family
->data
->count
; ++i
)
2533 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2537 return create_font(family
, match
, (IDWriteFont3
**)font
);
2540 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2542 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2544 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2547 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2549 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2552 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2554 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2559 for (j
= 0; j
< b
; j
++) {
2560 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2561 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2562 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2563 fonts
->fonts
[j
+1] = s
;
2574 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2575 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2577 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2578 matching_filter_func func
= NULL
;
2579 struct dwrite_font_propvec req
;
2580 struct dwrite_fontlist
*fonts
;
2583 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2587 fonts
= heap_alloc(sizeof(*fonts
));
2589 return E_OUTOFMEMORY
;
2591 /* Allocate as many as family has, not all of them will be necessary used. */
2592 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2593 if (!fonts
->fonts
) {
2595 return E_OUTOFMEMORY
;
2598 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2599 fonts
->refcount
= 1;
2600 fonts
->family
= family
;
2601 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2602 fonts
->font_count
= 0;
2604 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2605 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2606 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2607 func
= is_font_acceptable_for_normal
;
2609 else /* requested oblique or italic */ {
2610 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2611 func
= is_font_acceptable_for_oblique_italic
;
2614 for (i
= 0; i
< family
->data
->count
; ++i
)
2616 if (!func
|| func(family
->data
->fonts
[i
]))
2618 fonts
->fonts
[fonts
->font_count
] = family
->data
->fonts
[i
];
2619 addref_font_data(family
->data
->fonts
[i
]);
2620 fonts
->font_count
++;
2624 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2625 init_font_prop_vec(weight
, stretch
, style
, &req
);
2626 matchingfonts_sort(fonts
, &req
);
2628 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2632 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2634 FIXME("%p, %u.\n", iface
, index
);
2636 return DWRITE_LOCALITY_LOCAL
;
2639 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2641 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2643 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2647 if (!family
->data
->count
)
2650 if (index
>= family
->data
->count
)
2653 return create_font(family
, index
, font
);
2656 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2657 IDWriteFontFaceReference
**reference
)
2659 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2660 const struct dwrite_font_data
*font
;
2662 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2666 if (index
>= family
->data
->count
)
2669 font
= family
->data
->fonts
[index
];
2670 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2671 font
->file
, font
->face_index
, font
->simulations
, reference
);
2674 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2675 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2677 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2682 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2684 FIXME("%p, %p.\n", iface
, fontset
);
2689 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2691 dwritefontfamily_QueryInterface
,
2692 dwritefontfamily_AddRef
,
2693 dwritefontfamily_Release
,
2694 dwritefontfamily_GetFontCollection
,
2695 dwritefontfamily_GetFontCount
,
2696 dwritefontfamily_GetFont
,
2697 dwritefontfamily_GetFamilyNames
,
2698 dwritefontfamily_GetFirstMatchingFont
,
2699 dwritefontfamily_GetMatchingFonts
,
2700 dwritefontfamily1_GetFontLocality
,
2701 dwritefontfamily1_GetFont
,
2702 dwritefontfamily1_GetFontFaceReference
,
2703 dwritefontfamily2_GetMatchingFonts
,
2704 dwritefontfamily2_GetFontSet
,
2707 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2709 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2710 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2713 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2715 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2716 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2719 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2721 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2722 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2725 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2726 IDWriteFontCollection
**collection
)
2728 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2729 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2732 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2734 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2735 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2738 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2740 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2741 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2744 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2746 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2747 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2750 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2752 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2753 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2756 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2757 IDWriteFontFaceReference
**reference
)
2759 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2760 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2763 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2765 FIXME("%p, %p.\n", iface
, fontset
);
2770 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2772 dwritefontfamilylist_QueryInterface
,
2773 dwritefontfamilylist_AddRef
,
2774 dwritefontfamilylist_Release
,
2775 dwritefontfamilylist_GetFontCollection
,
2776 dwritefontfamilylist_GetFontCount
,
2777 dwritefontfamilylist_GetFont
,
2778 dwritefontfamilylist1_GetFontLocality
,
2779 dwritefontfamilylist1_GetFont
,
2780 dwritefontfamilylist1_GetFontFaceReference
,
2781 dwritefontfamilylist2_GetFontSet
,
2784 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2785 struct dwrite_fontfamily
**family
)
2787 struct dwrite_fontfamily
*object
;
2791 object
= heap_alloc(sizeof(*object
));
2793 return E_OUTOFMEMORY
;
2795 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2796 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2797 object
->refcount
= 1;
2798 object
->collection
= collection
;
2799 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2800 object
->data
= collection
->family_data
[index
];
2801 InterlockedIncrement(&object
->data
->refcount
);
2808 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2811 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2814 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2816 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2818 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2820 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2821 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2822 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2823 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2824 IsEqualIID(riid
, &IID_IUnknown
))
2827 IDWriteFontCollection3_AddRef(iface
);
2833 if (IsEqualIID(riid
, &IID_issystemcollection
))
2836 WARN("%s not implemented.\n", debugstr_guid(riid
));
2838 return E_NOINTERFACE
;
2841 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2843 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2845 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2846 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2847 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2848 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2849 IsEqualIID(riid
, &IID_IUnknown
))
2852 IDWriteFontCollection3_AddRef(iface
);
2856 WARN("%s not implemented.\n", debugstr_guid(riid
));
2860 return E_NOINTERFACE
;
2863 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2865 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2866 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2868 TRACE("%p, refcount %d.\n", collection
, refcount
);
2873 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2875 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2876 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2879 TRACE("%p, refcount %d.\n", iface
, refcount
);
2883 factory_detach_fontcollection(collection
->factory
, iface
);
2884 for (i
= 0; i
< collection
->count
; ++i
)
2885 release_fontfamily_data(collection
->family_data
[i
]);
2886 heap_free(collection
->family_data
);
2887 heap_free(collection
);
2893 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2895 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2897 TRACE("%p.\n", iface
);
2899 return collection
->count
;
2902 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2903 IDWriteFontFamily
**ret
)
2905 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2906 struct dwrite_fontfamily
*family
;
2909 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2913 if (index
>= collection
->count
)
2916 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2917 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2922 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2926 for (i
= 0; i
< collection
->count
; ++i
)
2928 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2929 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2932 for (j
= 0; j
< count
; j
++) {
2934 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
2935 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2943 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
2944 UINT32
*index
, BOOL
*exists
)
2946 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2948 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
2950 *index
= collection_find_family(collection
, name
);
2951 *exists
= *index
!= ~0u;
2955 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
2958 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2959 struct dwrite_fontfamily
*family
;
2960 BOOL found_font
= FALSE
;
2961 IDWriteFontFile
*file
;
2962 UINT32 face_index
, count
;
2966 TRACE("%p, %p, %p.\n", iface
, face
, font
);
2971 return E_INVALIDARG
;
2974 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
2977 face_index
= IDWriteFontFace_GetIndex(face
);
2980 for (i
= 0; i
< collection
->count
; ++i
)
2982 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
2984 for (j
= 0; j
< family_data
->count
; ++j
)
2986 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2988 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2997 IDWriteFontFile_Release(file
);
3000 return DWRITE_E_NOFONT
;
3002 hr
= create_fontfamily(collection
, i
, &family
);
3006 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3007 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3011 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3013 FIXME("%p, %p.\n", iface
, fontset
);
3018 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3019 IDWriteFontFamily1
**ret
)
3021 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3022 struct dwrite_fontfamily
*family
;
3025 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3029 if (index
>= collection
->count
)
3032 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3033 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3038 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3039 UINT32 index
, IDWriteFontFamily2
**ret
)
3041 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3042 struct dwrite_fontfamily
*family
;
3045 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3049 if (index
>= collection
->count
)
3052 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3053 *ret
= &family
->IDWriteFontFamily2_iface
;
3058 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3059 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3060 IDWriteFontList2
**fontlist
)
3062 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3067 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3069 FIXME("%p.\n", iface
);
3071 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3074 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3076 FIXME("%p, %p.\n", iface
, fontset
);
3081 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3083 FIXME("%p.\n", iface
);
3088 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3090 dwritefontcollection_QueryInterface
,
3091 dwritefontcollection_AddRef
,
3092 dwritefontcollection_Release
,
3093 dwritefontcollection_GetFontFamilyCount
,
3094 dwritefontcollection_GetFontFamily
,
3095 dwritefontcollection_FindFamilyName
,
3096 dwritefontcollection_GetFontFromFontFace
,
3097 dwritefontcollection1_GetFontSet
,
3098 dwritefontcollection1_GetFontFamily
,
3099 dwritefontcollection2_GetFontFamily
,
3100 dwritefontcollection2_GetMatchingFonts
,
3101 dwritefontcollection2_GetFontFamilyModel
,
3102 dwritefontcollection2_GetFontSet
,
3103 dwritefontcollection3_GetExpirationEvent
,
3106 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3108 dwritesystemfontcollection_QueryInterface
,
3109 dwritefontcollection_AddRef
,
3110 dwritefontcollection_Release
,
3111 dwritefontcollection_GetFontFamilyCount
,
3112 dwritefontcollection_GetFontFamily
,
3113 dwritefontcollection_FindFamilyName
,
3114 dwritefontcollection_GetFontFromFontFace
,
3115 dwritefontcollection1_GetFontSet
,
3116 dwritefontcollection1_GetFontFamily
,
3117 dwritefontcollection2_GetFontFamily
,
3118 dwritefontcollection2_GetMatchingFonts
,
3119 dwritefontcollection2_GetFontFamilyModel
,
3120 dwritefontcollection2_GetFontSet
,
3121 dwritefontcollection3_GetExpirationEvent
,
3124 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3126 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3127 sizeof(*family_data
->fonts
)))
3129 return E_OUTOFMEMORY
;
3132 family_data
->fonts
[family_data
->count
++] = font_data
;
3133 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3134 family_data
->has_normal_face
= 1;
3135 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3136 family_data
->has_oblique_face
= 1;
3138 family_data
->has_italic_face
= 1;
3142 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3143 struct dwrite_fontfamily_data
*family
)
3145 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3146 sizeof(*collection
->family_data
)))
3148 return E_OUTOFMEMORY
;
3151 collection
->family_data
[collection
->count
++] = family
;
3155 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3157 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3158 collection
->refcount
= 1;
3159 collection
->count
= 0;
3160 collection
->size
= 0;
3161 collection
->family_data
= NULL
;
3166 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3168 IDWriteFontFileLoader
*loader
;
3175 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3179 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3183 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3184 IDWriteFontFileLoader_Release(loader
);
3191 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3193 BOOL exists
= FALSE
;
3198 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3199 if (FAILED(hr
) || !exists
)
3202 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3205 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3209 while (isspaceW(*in
))
3213 if (!(len
= strlenW(in
)))
3216 while (isspaceW(in
[len
-1]))
3219 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3228 INT len
; /* token length */
3229 INT fulllen
; /* full length including following separators */
3232 static inline BOOL
is_name_separator_char(WCHAR ch
)
3234 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3237 struct name_pattern
{
3238 const WCHAR
*part1
; /* NULL indicates end of list */
3239 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3242 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3244 const struct name_pattern
*pattern
;
3245 struct name_token
*token
;
3248 while ((pattern
= &patterns
[i
++])->part1
) {
3249 int len_part1
= strlenW(pattern
->part1
);
3250 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3252 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3253 if (len_part2
== 0) {
3254 /* simple case with single part pattern */
3255 if (token
->len
!= len_part1
)
3258 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3259 if (match
) *match
= *token
;
3260 list_remove(&token
->entry
);
3266 struct name_token
*next_token
;
3267 struct list
*next_entry
;
3269 /* pattern parts are stored in reading order, tokens list is reversed */
3270 if (token
->len
< len_part2
)
3273 /* it's possible to have combined string as a token, like ExtraCondensed */
3274 if (token
->len
== len_part1
+ len_part2
) {
3275 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3278 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3281 /* combined string match */
3282 if (match
) *match
= *token
;
3283 list_remove(&token
->entry
);
3288 /* now it's only possible to have two tokens matched to respective pattern parts */
3289 if (token
->len
!= len_part2
)
3292 next_entry
= list_next(tokens
, &token
->entry
);
3294 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3295 if (next_token
->len
!= len_part1
)
3298 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3301 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3304 /* both parts matched, remove tokens */
3306 match
->ptr
= next_token
->ptr
;
3307 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3309 list_remove(&token
->entry
);
3310 list_remove(&next_token
->entry
);
3311 heap_free(next_token
);
3326 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3328 static const WCHAR itaW
[] = {'i','t','a',0};
3329 static const WCHAR italW
[] = {'i','t','a','l',0};
3330 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3331 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3333 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3334 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3335 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3336 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3338 static const struct name_pattern italic_patterns
[] = {
3347 static const struct name_pattern oblique_patterns
[] = {
3356 /* italic patterns first */
3357 if (match_pattern_list(tokens
, italic_patterns
, match
))
3358 return DWRITE_FONT_STYLE_ITALIC
;
3360 /* oblique patterns */
3361 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3362 return DWRITE_FONT_STYLE_OBLIQUE
;
3367 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3368 struct name_token
*match
)
3370 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3371 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3372 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3373 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3374 static const WCHAR wideW
[] = {'w','i','d','e',0};
3375 static const WCHAR condW
[] = {'c','o','n','d',0};
3377 static const struct name_pattern ultracondensed_patterns
[] = {
3378 { extraW
, compressedW
},
3379 { extW
, compressedW
},
3380 { ultraW
, compressedW
},
3381 { ultraW
, condensedW
},
3386 static const struct name_pattern extracondensed_patterns
[] = {
3388 { extraW
, condensedW
},
3389 { extW
, condensedW
},
3395 static const struct name_pattern semicondensed_patterns
[] = {
3398 { semiW
, condensedW
},
3403 static const struct name_pattern semiexpanded_patterns
[] = {
3405 { semiW
, expandedW
},
3406 { semiW
, extendedW
},
3410 static const struct name_pattern extraexpanded_patterns
[] = {
3411 { extraW
, expandedW
},
3412 { extW
, expandedW
},
3413 { extraW
, extendedW
},
3414 { extW
, extendedW
},
3418 static const struct name_pattern ultraexpanded_patterns
[] = {
3419 { ultraW
, expandedW
},
3420 { ultraW
, extendedW
},
3424 static const struct name_pattern condensed_patterns
[] = {
3430 static const struct name_pattern expanded_patterns
[] = {
3436 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3437 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3439 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3440 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3442 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3443 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3445 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3446 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3448 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3449 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3451 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3452 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3454 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3455 return DWRITE_FONT_STRETCH_CONDENSED
;
3457 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3458 return DWRITE_FONT_STRETCH_EXPANDED
;
3463 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3464 struct name_token
*match
)
3466 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3467 static const WCHAR nordW
[] = {'n','o','r','d',0};
3469 static const struct name_pattern thin_patterns
[] = {
3476 static const struct name_pattern extralight_patterns
[] = {
3483 static const struct name_pattern semilight_patterns
[] = {
3488 static const struct name_pattern demibold_patterns
[] = {
3494 static const struct name_pattern extrabold_patterns
[] = {
3501 static const struct name_pattern extrablack_patterns
[] = {
3508 static const struct name_pattern bold_patterns
[] = {
3513 static const struct name_pattern thin2_patterns
[] = {
3518 static const struct name_pattern light_patterns
[] = {
3523 static const struct name_pattern medium_patterns
[] = {
3528 static const struct name_pattern black_patterns
[] = {
3535 static const struct name_pattern demibold2_patterns
[] = {
3540 static const struct name_pattern extrabold2_patterns
[] = {
3545 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3546 matching pattern. */
3548 if (match_pattern_list(tokens
, thin_patterns
, match
))
3549 return DWRITE_FONT_WEIGHT_THIN
;
3551 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3552 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3554 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3555 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3557 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3558 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3560 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3561 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3563 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3564 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3566 if (match_pattern_list(tokens
, bold_patterns
, match
))
3567 return DWRITE_FONT_WEIGHT_BOLD
;
3569 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3570 return DWRITE_FONT_WEIGHT_THIN
;
3572 if (match_pattern_list(tokens
, light_patterns
, match
))
3573 return DWRITE_FONT_WEIGHT_LIGHT
;
3575 if (match_pattern_list(tokens
, medium_patterns
, match
))
3576 return DWRITE_FONT_WEIGHT_MEDIUM
;
3578 if (match_pattern_list(tokens
, black_patterns
, match
))
3579 return DWRITE_FONT_WEIGHT_BLACK
;
3581 if (match_pattern_list(tokens
, black_patterns
, match
))
3582 return DWRITE_FONT_WEIGHT_BLACK
;
3584 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3585 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3587 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3588 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3590 /* FIXME: use abbreviated names to extract weight */
3595 struct knownweight_entry
{
3597 DWRITE_FONT_WEIGHT weight
;
3600 static int compare_knownweights(const void *a
, const void* b
)
3602 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3603 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3606 if (target
> entry
->weight
)
3608 else if (target
< entry
->weight
)
3614 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3616 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3617 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3618 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3619 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3620 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3621 const struct knownweight_entry
*ptr
;
3623 static const struct knownweight_entry knownweights
[] = {
3624 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3625 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3626 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3627 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3628 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3629 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3630 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3631 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3632 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3633 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3636 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3637 compare_knownweights
);
3643 strcpyW(nameW
, ptr
->nameW
);
3647 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3649 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3650 strW
[name
->len
] = 0;
3653 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3654 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3656 static const WCHAR bookW
[] = {'B','o','o','k',0};
3657 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3658 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3659 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3660 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3662 static const WCHAR
*regular_patterns
[] = {
3671 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3675 len
= strlenW(facenameW
);
3677 /* remove rightmost regular variant from face name */
3678 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3679 int pattern_len
= strlenW(ptr
);
3682 if (pattern_len
> len
)
3685 src
= facenameW
+ len
- pattern_len
;
3686 while (src
>= facenameW
) {
3687 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3688 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3689 len
= strlenW(facenameW
);
3701 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3709 struct name_token
*token
= heap_alloc(sizeof(*token
));
3714 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3720 /* skip separators */
3721 while (is_name_separator_char(*ptr
)) {
3726 list_add_head(tokens
, &token
->entry
);
3730 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3732 struct name_token
*token
, *token2
;
3733 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3736 list_remove(&token
->entry
);
3738 /* don't include last separator */
3739 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3740 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3748 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3750 struct name_token stretch_name
, weight_name
, style_name
;
3751 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3752 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3753 const WCHAR
*regular_ptr
= NULL
;
3754 DWRITE_FONT_STRETCH stretch
;
3755 DWRITE_FONT_WEIGHT weight
;
3759 /* remove leading and trailing spaces from family and face name */
3760 trim_spaces(familyW
, familynameW
);
3761 len
= trim_spaces(faceW
, facenameW
);
3763 /* remove rightmost regular variant from face name */
3764 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3766 /* append face name to family name, FIXME check if face name is a substring of family name */
3768 strcatW(familynameW
, spaceW
);
3769 strcatW(familynameW
, facenameW
);
3772 /* tokenize with " .-_" */
3773 fontname_tokenize(&tokens
, familynameW
);
3775 /* extract and resolve style */
3776 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3778 /* extract stretch */
3779 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3781 /* extract weight */
3782 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3784 /* resolve weight */
3785 if (weight
!= font
->weight
) {
3786 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3787 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3788 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3789 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3790 !(abs(weight
- font
->weight
) <= 150 &&
3791 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3792 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3793 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3795 font
->weight
= weight
;
3799 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3800 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3801 stretch itself is normal (extracted stretch is never normal). */
3802 if (stretch
!= font
->stretch
) {
3803 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3804 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3805 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3807 font
->stretch
= stretch
;
3811 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3813 /* get final combined string from what's left in token list, list is released */
3814 fontname_tokens_to_str(&tokens
, finalW
);
3816 if (!strcmpW(familyW
, finalW
))
3819 /* construct face name */
3820 strcpyW(familyW
, finalW
);
3822 /* resolved weight name */
3823 if (weight_name
.ptr
)
3824 font_name_token_to_str(&weight_name
, weightW
);
3825 /* ignore normal weight */
3826 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3828 /* for known weight values use appropriate names */
3829 else if (is_known_weight_value(font
->weight
, weightW
)) {
3831 /* use Wnnn format as a fallback in case weight is not one of known values */
3833 static const WCHAR fmtW
[] = {'W','%','d',0};
3834 sprintfW(weightW
, fmtW
, font
->weight
);
3837 /* resolved stretch name */
3838 if (stretch_name
.ptr
)
3839 font_name_token_to_str(&stretch_name
, stretchW
);
3840 /* ignore normal stretch */
3841 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3843 /* use predefined stretch names */
3845 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3846 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3847 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3848 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3849 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3850 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3852 static const WCHAR
*stretchnamesW
[] = {
3853 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3858 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3864 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3867 /* resolved style name */
3869 font_name_token_to_str(&style_name
, styleW
);
3870 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3872 /* use predefined names */
3874 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3875 strcpyW(styleW
, italicW
);
3877 strcpyW(styleW
, obliqueW
);
3880 /* use Regular match if it was found initially */
3881 if (!*weightW
&& !*stretchW
&& !*styleW
)
3882 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3886 strcpyW(faceW
, stretchW
);
3889 strcatW(faceW
, spaceW
);
3890 strcatW(faceW
, weightW
);
3894 strcatW(faceW
, spaceW
);
3895 strcatW(faceW
, styleW
);
3899 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3903 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3905 static const float width_axis_values
[] =
3907 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3908 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
3909 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
3910 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
3911 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
3912 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
3913 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
3914 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
3915 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
3916 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
3919 struct file_stream_desc stream_desc
;
3920 struct dwrite_font_props props
;
3921 struct dwrite_font_data
*data
;
3922 WCHAR familyW
[255], faceW
[255];
3927 data
= heap_alloc_zero(sizeof(*data
));
3929 return E_OUTOFMEMORY
;
3932 data
->file
= desc
->files
[0];
3933 data
->face_index
= desc
->index
;
3934 data
->face_type
= desc
->face_type
;
3935 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3936 data
->bold_sim_tested
= 0;
3937 data
->oblique_sim_tested
= 0;
3938 IDWriteFontFile_AddRef(data
->file
);
3940 stream_desc
.stream
= desc
->stream
;
3941 stream_desc
.face_type
= desc
->face_type
;
3942 stream_desc
.face_index
= desc
->index
;
3943 opentype_get_font_properties(&stream_desc
, &props
);
3944 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3945 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3947 /* get family name from font file */
3948 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
3950 WARN("unable to get family name from font\n");
3951 release_font_data(data
);
3955 data
->style
= props
.style
;
3956 data
->stretch
= props
.stretch
;
3957 data
->weight
= props
.weight
;
3958 data
->panose
= props
.panose
;
3959 data
->fontsig
= props
.fontsig
;
3960 data
->lf
= props
.lf
;
3961 data
->flags
= props
.flags
;
3963 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
3964 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
3965 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3966 set_en_localizedstring(data
->family_names
, familyW
);
3967 set_en_localizedstring(data
->names
, faceW
);
3970 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3972 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
3973 data
->axis
[0].value
= props
.weight
;
3974 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
3975 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
3976 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
3977 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
3983 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3984 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3986 struct dwrite_font_data
*data
;
3990 data
= heap_alloc_zero(sizeof(*data
));
3992 return E_OUTOFMEMORY
;
3996 data
->simulations
|= sim
;
3997 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3998 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3999 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4000 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4001 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4003 IDWriteFontFile_AddRef(data
->file
);
4004 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4006 create_localizedstrings(&data
->names
);
4007 add_localizedstring(data
->names
, enusW
, facenameW
);
4009 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4015 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4017 struct dwrite_fontfamily_data
*data
;
4019 data
= heap_alloc_zero(sizeof(*data
));
4021 return E_OUTOFMEMORY
;
4024 data
->familyname
= familyname
;
4025 IDWriteLocalizedStrings_AddRef(familyname
);
4032 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4034 size_t i
, j
, heaviest
;
4036 for (i
= 0; i
< family
->count
; ++i
)
4038 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4041 if (family
->fonts
[i
]->bold_sim_tested
)
4044 family
->fonts
[i
]->bold_sim_tested
= 1;
4045 for (j
= i
; j
< family
->count
; ++j
)
4047 if (family
->fonts
[j
]->bold_sim_tested
)
4050 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4051 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4052 if (family
->fonts
[j
]->weight
> weight
) {
4053 weight
= family
->fonts
[j
]->weight
;
4056 family
->fonts
[j
]->bold_sim_tested
= 1;
4060 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4061 static const struct name_pattern weightsim_patterns
[] = {
4076 WCHAR facenameW
[255], initialW
[255];
4077 struct dwrite_font_data
*boldface
;
4080 /* add Bold simulation based on heaviest face data */
4082 /* Simulated face name should only contain Bold as weight term,
4083 so remove existing regular and weight terms. */
4084 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4085 facename_remove_regular_term(initialW
, -1);
4087 /* remove current weight pattern */
4088 fontname_tokenize(&tokens
, initialW
);
4089 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4090 fontname_tokens_to_str(&tokens
, facenameW
);
4092 /* Bold suffix for new name */
4094 strcatW(facenameW
, spaceW
);
4095 strcatW(facenameW
, boldW
);
4097 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4098 boldface
->bold_sim_tested
= 1;
4099 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4100 fontfamily_add_font(family
, boldface
);
4106 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4110 for (i
= 0; i
< family
->count
; ++i
)
4112 UINT32 regular
= ~0u, oblique
= ~0u;
4113 struct dwrite_font_data
*obliqueface
;
4114 WCHAR facenameW
[255];
4116 if (family
->fonts
[i
]->oblique_sim_tested
)
4119 family
->fonts
[i
]->oblique_sim_tested
= 1;
4120 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4122 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4125 /* find regular style with same weight/stretch values */
4126 for (j
= i
; j
< family
->count
; ++j
)
4128 if (family
->fonts
[j
]->oblique_sim_tested
)
4131 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4132 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4134 family
->fonts
[j
]->oblique_sim_tested
= 1;
4135 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4138 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4142 if (regular
!= ~0u && oblique
!= ~0u)
4146 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4150 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4154 /* add oblique simulation based on this regular face */
4156 /* remove regular term if any, append 'Oblique' */
4157 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4158 facename_remove_regular_term(facenameW
, -1);
4161 strcatW(facenameW
, spaceW
);
4162 strcatW(facenameW
, obliqueW
);
4164 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4165 obliqueface
->oblique_sim_tested
= 1;
4166 obliqueface
->lf
.lfItalic
= 1;
4167 fontfamily_add_font(family
, obliqueface
);
4172 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4173 const WCHAR
*replacement_name
)
4175 UINT32 i
= collection_find_family(collection
, replacement_name
);
4176 struct dwrite_fontfamily_data
*target
;
4177 IDWriteLocalizedStrings
*strings
;
4180 /* replacement does not exist */
4184 hr
= create_localizedstrings(&strings
);
4188 /* add a new family with target name, reuse font data from replacement */
4189 add_localizedstring(strings
, enusW
, target_name
);
4190 hr
= init_fontfamily_data(strings
, &target
);
4192 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4195 for (i
= 0; i
< replacement
->count
; ++i
)
4197 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4198 addref_font_data(replacement
->fonts
[i
]);
4201 fontcollection_add_family(collection
, target
);
4202 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4203 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4205 IDWriteLocalizedStrings_Release(strings
);
4209 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4210 system font collections. */
4211 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4213 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4218 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4221 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4226 max_namelen
++; /* returned value doesn't include room for '\0' */
4227 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4228 data
= heap_alloc(max_datalen
);
4230 datalen
= max_datalen
;
4231 namelen
= max_namelen
;
4232 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4233 if (collection_find_family(collection
, name
) == ~0u) {
4234 if (type
== REG_MULTI_SZ
) {
4235 WCHAR
*replacement
= data
;
4236 while (*replacement
) {
4237 if (fontcollection_add_replacement(collection
, name
, replacement
))
4239 replacement
+= strlenW(replacement
) + 1;
4242 else if (type
== REG_SZ
)
4243 fontcollection_add_replacement(collection
, name
, data
);
4246 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4248 datalen
= max_datalen
;
4249 namelen
= max_namelen
;
4257 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4258 IDWriteFontCollection3
**ret
)
4260 struct fontfile_enum
{
4262 IDWriteFontFile
*file
;
4264 struct fontfile_enum
*fileenum
, *fileenum2
;
4265 struct dwrite_fontcollection
*collection
;
4266 struct list scannedfiles
;
4267 BOOL current
= FALSE
;
4273 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4274 if (!collection
) return E_OUTOFMEMORY
;
4276 hr
= init_font_collection(collection
, is_system
);
4278 heap_free(collection
);
4282 *ret
= &collection
->IDWriteFontCollection3_iface
;
4284 TRACE("building font collection:\n");
4286 list_init(&scannedfiles
);
4287 while (hr
== S_OK
) {
4288 DWRITE_FONT_FACE_TYPE face_type
;
4289 DWRITE_FONT_FILE_TYPE file_type
;
4290 BOOL supported
, same
= FALSE
;
4291 IDWriteFontFileStream
*stream
;
4292 IDWriteFontFile
*file
;
4296 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4297 if (FAILED(hr
) || !current
)
4300 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4304 /* check if we've scanned this file already */
4305 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4306 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4311 IDWriteFontFile_Release(file
);
4315 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4316 IDWriteFontFile_Release(file
);
4320 /* Unsupported formats are skipped. */
4321 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4322 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4323 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4324 IDWriteFontFileStream_Release(stream
);
4325 IDWriteFontFile_Release(file
);
4330 /* add to scanned list */
4331 fileenum
= heap_alloc(sizeof(*fileenum
));
4332 fileenum
->file
= file
;
4333 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4335 for (i
= 0; i
< face_count
; ++i
)
4337 struct dwrite_font_data
*font_data
;
4338 struct fontface_desc desc
;
4342 desc
.factory
= factory
;
4343 desc
.face_type
= face_type
;
4345 desc
.stream
= stream
;
4346 desc
.files_number
= 1;
4348 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4349 desc
.font_data
= NULL
;
4351 /* Allocate an initialize new font data structure. */
4352 hr
= init_font_data(&desc
, &font_data
);
4355 /* move to next one */
4360 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4362 /* ignore dot named faces */
4363 if (familyW
[0] == '.')
4365 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4366 release_font_data(font_data
);
4370 index
= collection_find_family(collection
, familyW
);
4372 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4374 struct dwrite_fontfamily_data
*family_data
;
4376 /* create and init new family */
4377 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4379 /* add font to family, family - to collection */
4380 hr
= fontfamily_add_font(family_data
, font_data
);
4382 hr
= fontcollection_add_family(collection
, family_data
);
4385 release_fontfamily_data(family_data
);
4393 IDWriteFontFileStream_Release(stream
);
4396 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4397 IDWriteFontFile_Release(fileenum
->file
);
4398 list_remove(&fileenum
->entry
);
4399 heap_free(fileenum
);
4402 for (i
= 0; i
< collection
->count
; ++i
)
4404 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4405 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4409 fontcollection_add_replacements(collection
);
4411 collection
->factory
= factory
;
4412 IDWriteFactory7_AddRef(factory
);
4417 struct system_fontfile_enumerator
4419 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4422 IDWriteFactory7
*factory
;
4427 DWORD filename_size
;
4430 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4432 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4435 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4437 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4438 IDWriteFontFileEnumerator_AddRef(iface
);
4443 WARN("%s not implemented.\n", debugstr_guid(riid
));
4447 return E_NOINTERFACE
;
4450 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4452 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4453 return InterlockedIncrement(&enumerator
->ref
);
4456 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4458 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4459 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
4463 IDWriteFactory7_Release(enumerator
->factory
);
4464 RegCloseKey(enumerator
->hkey
);
4465 heap_free(enumerator
->filename
);
4466 heap_free(enumerator
);
4472 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4476 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4477 if (!strchrW(filename
, '\\')) {
4478 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4479 WCHAR fullpathW
[MAX_PATH
];
4481 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4482 strcatW(fullpathW
, fontsW
);
4483 strcatW(fullpathW
, filename
);
4485 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4488 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4493 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4495 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4499 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4502 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4505 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4507 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4508 WCHAR name_buf
[256], *name
= name_buf
;
4509 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4514 enumerator
->index
++;
4516 /* iterate until we find next string value */
4519 name_count
= max_name_count
;
4520 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4522 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4523 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4524 if (r
== ERROR_MORE_DATA
) {
4525 if (name_count
>= max_name_count
) {
4526 if (name
!= name_buf
) heap_free(name
);
4527 max_name_count
*= 2;
4528 name
= heap_alloc(max_name_count
* sizeof(*name
));
4529 if (!name
) return E_OUTOFMEMORY
;
4531 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4532 heap_free(enumerator
->filename
);
4533 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4534 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4535 if (!enumerator
->filename
) {
4541 } while (r
== ERROR_MORE_DATA
);
4543 if (r
!= ERROR_SUCCESS
) {
4544 enumerator
->filename
[0] = 0;
4547 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4548 if (type
== REG_SZ
&& *name
!= '@') {
4552 enumerator
->index
++;
4554 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4557 if (name
!= name_buf
) heap_free(name
);
4561 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4563 systemfontfileenumerator_QueryInterface
,
4564 systemfontfileenumerator_AddRef
,
4565 systemfontfileenumerator_Release
,
4566 systemfontfileenumerator_MoveNext
,
4567 systemfontfileenumerator_GetCurrentFontFile
4570 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4572 struct system_fontfile_enumerator
*enumerator
;
4573 static const WCHAR fontslistW
[] = {
4574 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4575 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4576 'F','o','n','t','s',0
4581 enumerator
= heap_alloc(sizeof(*enumerator
));
4583 return E_OUTOFMEMORY
;
4585 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4586 enumerator
->ref
= 1;
4587 enumerator
->factory
= factory
;
4588 enumerator
->index
= -1;
4589 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4590 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4591 if (!enumerator
->filename
) {
4592 heap_free(enumerator
);
4593 return E_OUTOFMEMORY
;
4596 IDWriteFactory7_AddRef(factory
);
4598 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4600 ERR("failed to open fonts list key\n");
4601 IDWriteFactory7_Release(factory
);
4602 heap_free(enumerator
->filename
);
4603 heap_free(enumerator
);
4607 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4612 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4614 IDWriteFontFileEnumerator
*enumerator
;
4619 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4623 TRACE("building system font collection for factory %p\n", factory
);
4624 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4625 IDWriteFontFileEnumerator_Release(enumerator
);
4629 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4630 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4632 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};
4633 static const WCHAR emptyW
[] = {0};
4634 struct dwrite_fontfamily_data
*family_data
;
4635 IDWriteLocalizedStrings
*names
;
4636 DWRITE_FONT_FACE_TYPE face_type
;
4637 DWRITE_FONT_FILE_TYPE file_type
;
4638 IDWriteFontFileStream
*stream
;
4639 IDWriteFontFile
*file
;
4640 UINT32 face_count
, i
;
4644 /* create font file from this path */
4645 hr
= create_local_file_reference(factory
, pathW
, &file
);
4649 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4650 IDWriteFontFile_Release(file
);
4654 /* Unsupported formats are skipped. */
4655 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4656 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4657 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4658 IDWriteFontFileStream_Release(stream
);
4659 IDWriteFontFile_Release(file
);
4663 /* create and init new family */
4665 /* Family names are added for non-specific locale, represented with empty string.
4666 Default family appears with empty family name. */
4667 create_localizedstrings(&names
);
4668 if (!strcmpiW(keynameW
, defaultfontW
))
4669 add_localizedstring(names
, emptyW
, emptyW
);
4671 add_localizedstring(names
, emptyW
, keynameW
);
4673 hr
= init_fontfamily_data(names
, &family_data
);
4674 IDWriteLocalizedStrings_Release(names
);
4676 IDWriteFontFile_Release(file
);
4680 /* fill with faces */
4681 for (i
= 0; i
< face_count
; i
++) {
4682 struct dwrite_font_data
*font_data
;
4683 struct fontface_desc desc
;
4685 /* alloc and init new font data structure */
4686 desc
.factory
= factory
;
4687 desc
.face_type
= face_type
;
4690 desc
.stream
= stream
;
4691 desc
.files_number
= 1;
4692 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4693 desc
.font_data
= NULL
;
4695 hr
= init_font_data(&desc
, &font_data
);
4699 /* add font to family */
4700 hr
= fontfamily_add_font(family_data
, font_data
);
4702 release_font_data(font_data
);
4705 /* add family to collection */
4706 hr
= fontcollection_add_family(collection
, family_data
);
4708 release_fontfamily_data(family_data
);
4709 IDWriteFontFileStream_Release(stream
);
4710 IDWriteFontFile_Release(file
);
4715 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4717 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4718 struct dwrite_fontcollection
*collection
;
4719 static const WCHAR emptyW
[] = {0};
4720 WCHAR eudckeypathW
[16];
4728 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4732 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4733 if (!collection
) return E_OUTOFMEMORY
;
4735 hr
= init_font_collection(collection
, FALSE
);
4737 heap_free(collection
);
4741 *ret
= &collection
->IDWriteFontCollection3_iface
;
4742 collection
->factory
= factory
;
4743 IDWriteFactory7_AddRef(factory
);
4745 /* return empty collection if EUDC fonts are not configured */
4746 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4747 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4750 retval
= ERROR_SUCCESS
;
4752 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4753 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4754 DWORD type
, path_len
, name_len
;
4756 path_len
= ARRAY_SIZE(pathW
);
4757 name_len
= ARRAY_SIZE(keynameW
);
4758 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4759 if (retval
|| type
!= REG_SZ
)
4762 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4764 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4766 RegCloseKey(eudckey
);
4768 /* try to add global default if not defined for specific codepage */
4770 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4772 if (FAILED(hr
) || !exists
) {
4773 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4774 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4776 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4779 /* EUDC collection offers simulated faces too */
4780 for (i
= 0; i
< collection
->count
; ++i
)
4782 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4783 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4789 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4791 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
4793 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4796 IDWriteFontFile_AddRef(iface
);
4800 WARN("%s not implemented.\n", debugstr_guid(riid
));
4803 return E_NOINTERFACE
;
4806 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4808 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4809 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
4811 TRACE("%p, refcount %d.\n", iface
, refcount
);
4816 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4818 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4819 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
4821 TRACE("%p, refcount %d.\n", iface
, refcount
);
4825 IDWriteFontFileLoader_Release(file
->loader
);
4827 IDWriteFontFileStream_Release(file
->stream
);
4828 heap_free(file
->reference_key
);
4835 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
4837 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4839 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
4841 *key
= file
->reference_key
;
4842 *key_size
= file
->key_size
;
4847 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
4849 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4851 TRACE("%p, %p.\n", iface
, loader
);
4853 *loader
= file
->loader
;
4854 IDWriteFontFileLoader_AddRef(*loader
);
4859 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4860 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4862 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4863 IDWriteFontFileStream
*stream
;
4866 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
4868 *is_supported
= FALSE
;
4869 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4871 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4874 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
4878 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4880 /* TODO: Further Analysis */
4881 IDWriteFontFileStream_Release(stream
);
4885 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
4887 dwritefontfile_QueryInterface
,
4888 dwritefontfile_AddRef
,
4889 dwritefontfile_Release
,
4890 dwritefontfile_GetReferenceKey
,
4891 dwritefontfile_GetLoader
,
4892 dwritefontfile_Analyze
,
4895 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4896 IDWriteFontFile
**ret
)
4898 struct dwrite_fontfile
*file
;
4903 file
= heap_alloc(sizeof(*file
));
4904 key
= heap_alloc(key_size
);
4905 if (!file
|| !key
) {
4908 return E_OUTOFMEMORY
;
4911 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4913 IDWriteFontFileLoader_AddRef(loader
);
4914 file
->loader
= loader
;
4915 file
->stream
= NULL
;
4916 file
->reference_key
= key
;
4917 memcpy(file
->reference_key
, reference_key
, key_size
);
4918 file
->key_size
= key_size
;
4920 *ret
= &file
->IDWriteFontFile_iface
;
4925 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
4927 struct file_stream_desc stream_desc
;
4928 struct dwrite_font_data
*font_data
;
4929 struct dwrite_fontface
*fontface
;
4935 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4937 return E_OUTOFMEMORY
;
4939 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4940 if (!fontface
->files
) {
4941 heap_free(fontface
);
4942 return E_OUTOFMEMORY
;
4945 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
4946 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
4947 fontface
->refcount
= 1;
4948 fontface
->type
= desc
->face_type
;
4949 fontface
->file_count
= desc
->files_number
;
4950 fontface
->vdmx
.exists
= TRUE
;
4951 fontface
->gasp
.exists
= TRUE
;
4952 fontface
->cpal
.exists
= TRUE
;
4953 fontface
->colr
.exists
= TRUE
;
4954 fontface
->index
= desc
->index
;
4955 fontface
->simulations
= desc
->simulations
;
4956 fontface
->factory
= desc
->factory
;
4957 IDWriteFactory7_AddRef(fontface
->factory
);
4959 for (i
= 0; i
< fontface
->file_count
; i
++) {
4960 fontface
->files
[i
] = desc
->files
[i
];
4961 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4963 fontface
->stream
= desc
->stream
;
4964 IDWriteFontFileStream_AddRef(fontface
->stream
);
4966 stream_desc
.stream
= fontface
->stream
;
4967 stream_desc
.face_type
= desc
->face_type
;
4968 stream_desc
.face_index
= desc
->index
;
4969 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4970 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
4971 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4972 /* TODO: test what happens if caret is already slanted */
4973 if (fontface
->caret
.slopeRise
== 1) {
4974 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4975 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4979 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace5_iface
))
4980 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4981 if (opentype_has_vertical_variants(fontface
))
4982 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4983 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
4985 /* Font properties are reused from font object when 'normal' face creation path is used:
4986 collection -> family -> matching font -> fontface.
4988 If face is created directly from factory we have to go through properties resolution.
4990 if (desc
->font_data
)
4992 font_data
= desc
->font_data
;
4993 addref_font_data(font_data
);
4997 hr
= init_font_data(desc
, &font_data
);
5000 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5005 fontface
->weight
= font_data
->weight
;
5006 fontface
->style
= font_data
->style
;
5007 fontface
->stretch
= font_data
->stretch
;
5008 fontface
->panose
= font_data
->panose
;
5009 fontface
->fontsig
= font_data
->fontsig
;
5010 fontface
->lf
= font_data
->lf
;
5011 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5012 fontface
->names
= font_data
->names
;
5013 if (fontface
->names
)
5014 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5015 fontface
->family_names
= font_data
->family_names
;
5016 if (fontface
->family_names
)
5017 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5018 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5019 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5021 if (fontface
->info_strings
[i
])
5022 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5024 fontface
->cmap
.stream
= fontface
->stream
;
5025 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5026 release_font_data(font_data
);
5028 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5030 *ret
= &fontface
->IDWriteFontFace5_iface
;
5035 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5042 struct local_cached_stream
5045 IDWriteFontFileStream
*stream
;
5046 struct local_refkey
*key
;
5050 struct dwrite_localfontfilestream
5052 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5055 struct local_cached_stream
*entry
;
5056 const void *file_ptr
;
5060 struct dwrite_localfontfileloader
5062 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5065 struct list streams
;
5066 CRITICAL_SECTION cs
;
5069 static struct dwrite_localfontfileloader local_fontfile_loader
;
5071 struct dwrite_inmemory_stream_data
5079 struct dwrite_inmemory_filestream
5081 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5084 struct dwrite_inmemory_stream_data
*data
;
5087 struct dwrite_inmemory_fileloader
5089 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5092 struct dwrite_inmemory_stream_data
**streams
;
5097 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5099 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5102 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5104 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5107 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5109 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5112 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5114 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5117 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5119 if (InterlockedDecrement(&stream
->ref
) == 0) {
5121 IUnknown_Release(stream
->owner
);
5123 heap_free(stream
->data
);
5128 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5130 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5132 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5134 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5135 IsEqualIID(riid
, &IID_IUnknown
))
5138 if (InterlockedIncrement(&stream
->refcount
) == 1)
5140 InterlockedDecrement(&stream
->refcount
);
5147 WARN("%s not implemented.\n", debugstr_guid(riid
));
5150 return E_NOINTERFACE
;
5153 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5155 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5156 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5158 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5163 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5165 list_remove(&stream
->entry
);
5166 heap_free(stream
->key
);
5170 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5172 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5173 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5175 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5179 UnmapViewOfFile(stream
->file_ptr
);
5181 EnterCriticalSection(&local_fontfile_loader
.cs
);
5182 release_cached_stream(stream
->entry
);
5183 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5191 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5192 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5194 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5196 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5197 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5199 *fragment_context
= NULL
;
5201 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5203 *fragment_start
= NULL
;
5207 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5211 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5213 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5216 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5218 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5220 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5222 *size
= stream
->size
;
5226 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5228 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5231 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5233 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5234 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5235 *last_writetime
= li
.QuadPart
;
5240 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5242 localfontfilestream_QueryInterface
,
5243 localfontfilestream_AddRef
,
5244 localfontfilestream_Release
,
5245 localfontfilestream_ReadFileFragment
,
5246 localfontfilestream_ReleaseFileFragment
,
5247 localfontfilestream_GetFileSize
,
5248 localfontfilestream_GetLastWriteTime
5251 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5252 IDWriteFontFileStream
**ret
)
5254 struct dwrite_localfontfilestream
*object
;
5258 if (!(object
= heap_alloc(sizeof(*object
))))
5259 return E_OUTOFMEMORY
;
5261 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5262 object
->refcount
= 1;
5264 object
->file_ptr
= file_ptr
;
5265 object
->size
= size
;
5266 object
->entry
= entry
;
5268 *ret
= &object
->IDWriteFontFileStream_iface
;
5273 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5275 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5277 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5278 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5279 IsEqualIID(riid
, &IID_IUnknown
))
5282 IDWriteLocalFontFileLoader_AddRef(iface
);
5286 WARN("%s not implemented.\n", debugstr_guid(riid
));
5289 return E_NOINTERFACE
;
5292 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5294 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5295 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5297 TRACE("%p, refcount %d.\n", iface
, refcount
);
5302 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5304 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5305 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5307 TRACE("%p, refcount %d.\n", iface
, refcount
);
5312 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5314 const struct local_refkey
*refkey
= key
;
5315 struct local_cached_stream
*stream
;
5316 IDWriteFontFileStream
*filestream
;
5317 HANDLE file
, mapping
;
5324 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5325 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5326 if (file
== INVALID_HANDLE_VALUE
) {
5327 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5331 GetFileSizeEx(file
, &size
);
5332 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5337 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5338 CloseHandle(mapping
);
5340 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5344 stream
= heap_alloc(sizeof(*stream
));
5346 UnmapViewOfFile(file_ptr
);
5347 return E_OUTOFMEMORY
;
5350 stream
->key
= heap_alloc(key_size
);
5352 UnmapViewOfFile(file_ptr
);
5354 return E_OUTOFMEMORY
;
5357 stream
->key_size
= key_size
;
5358 memcpy(stream
->key
, key
, key_size
);
5360 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5362 UnmapViewOfFile(file_ptr
);
5363 heap_free(stream
->key
);
5368 stream
->stream
= filestream
;
5375 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5376 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5378 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5379 struct local_cached_stream
*stream
;
5382 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5384 EnterCriticalSection(&loader
->cs
);
5388 /* search cache first */
5389 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5391 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5392 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5397 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5399 list_add_head(&loader
->streams
, &stream
->entry
);
5400 *ret
= stream
->stream
;
5403 LeaveCriticalSection(&loader
->cs
);
5408 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5409 UINT32 key_size
, UINT32
*length
)
5411 const struct local_refkey
*refkey
= key
;
5413 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5415 *length
= strlenW(refkey
->name
);
5419 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5420 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5422 const struct local_refkey
*refkey
= key
;
5424 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5426 if (length
< strlenW(refkey
->name
))
5427 return E_INVALIDARG
;
5429 strcpyW(path
, refkey
->name
);
5433 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5434 UINT32 key_size
, FILETIME
*writetime
)
5436 const struct local_refkey
*refkey
= key
;
5438 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5440 *writetime
= refkey
->writetime
;
5444 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5446 localfontfileloader_QueryInterface
,
5447 localfontfileloader_AddRef
,
5448 localfontfileloader_Release
,
5449 localfontfileloader_CreateStreamFromKey
,
5450 localfontfileloader_GetFilePathLengthFromKey
,
5451 localfontfileloader_GetFilePathFromKey
,
5452 localfontfileloader_GetLastWriteTimeFromKey
5455 void init_local_fontfile_loader(void)
5457 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5458 local_fontfile_loader
.refcount
= 1;
5459 list_init(&local_fontfile_loader
.streams
);
5460 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5461 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5464 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5466 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5469 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5471 struct local_refkey
*refkey
;
5474 return E_INVALIDARG
;
5476 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5479 refkey
= heap_alloc(*size
);
5481 return E_OUTOFMEMORY
;
5484 refkey
->writetime
= *writetime
;
5486 WIN32_FILE_ATTRIBUTE_DATA info
;
5488 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5489 refkey
->writetime
= info
.ftLastWriteTime
;
5491 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5493 strcpyW(refkey
->name
, path
);
5500 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5502 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5504 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5505 IsEqualIID(riid
, &IID_IUnknown
))
5508 IDWriteGlyphRunAnalysis_AddRef(iface
);
5512 WARN("%s not implemented.\n", debugstr_guid(riid
));
5515 return E_NOINTERFACE
;
5518 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5520 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5521 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
5523 TRACE("%p, refcount %d.\n", iface
, refcount
);
5528 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5530 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5531 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
5533 TRACE("%p, refcount %d.\n", iface
, refcount
);
5537 if (analysis
->run
.fontFace
)
5538 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5539 heap_free(analysis
->glyphs
);
5540 heap_free(analysis
->origins
);
5541 heap_free(analysis
->bitmap
);
5542 heap_free(analysis
);
5548 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5552 case DWRITE_RENDERING_MODE1_NATURAL
:
5553 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5554 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5561 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5563 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5566 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5568 struct dwrite_glyphbitmap glyph_bitmap
;
5569 IDWriteFontFace4
*fontface
;
5573 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5574 *bounds
= analysis
->bounds
;
5578 if (analysis
->run
.isSideways
)
5579 FIXME("sideways runs are not supported.\n");
5581 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5583 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5585 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5586 glyph_bitmap
.fontface
= fontface
;
5587 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5588 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5589 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5590 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5591 glyph_bitmap
.m
= &analysis
->m
;
5593 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5594 RECT
*bbox
= &glyph_bitmap
.bbox
;
5597 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5598 freetype_get_glyph_bbox(&glyph_bitmap
);
5600 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5601 (bbox
->bottom
- bbox
->top
);
5602 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5603 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5605 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5606 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5609 IDWriteFontFace4_Release(fontface
);
5611 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5612 *bounds
= analysis
->bounds
;
5615 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
5616 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5618 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5620 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
5622 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5623 SetRectEmpty(bounds
);
5624 return E_INVALIDARG
;
5627 if (type
!= analysis
->texture_type
)
5629 SetRectEmpty(bounds
);
5633 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
5637 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5639 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5640 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5641 (runbounds
->left
- bounds
->left
) * 3;
5643 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5644 runbounds
->left
- bounds
->left
;
5647 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5649 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5650 struct dwrite_glyphbitmap glyph_bitmap
;
5651 IDWriteFontFace4
*fontface
;
5652 D2D_POINT_2F origin
;
5657 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5659 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5663 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5664 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5666 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5667 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5668 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5669 IDWriteFontFace4_Release(fontface
);
5670 return E_OUTOFMEMORY
;
5673 origin
.x
= origin
.y
= 0.0f
;
5675 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5676 glyph_bitmap
.fontface
= fontface
;
5677 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5678 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5679 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5680 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5681 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5682 glyph_bitmap
.m
= &analysis
->m
;
5683 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5684 IDWriteFontFace4_Release(fontface
);
5685 return E_OUTOFMEMORY
;
5688 bbox
= &glyph_bitmap
.bbox
;
5690 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5691 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5692 int x
, y
, width
, height
;
5695 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5696 freetype_get_glyph_bbox(&glyph_bitmap
);
5698 if (IsRectEmpty(bbox
))
5701 width
= bbox
->right
- bbox
->left
;
5702 height
= bbox
->bottom
- bbox
->top
;
5704 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5705 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5706 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5708 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5710 /* blit to analysis bitmap */
5711 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5714 /* convert 1bpp to 8bpp/24bpp */
5715 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5716 for (y
= 0; y
< height
; y
++) {
5717 for (x
= 0; x
< width
; x
++)
5718 if (src
[x
/ 8] & masks
[x
% 8])
5719 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5720 src
+= glyph_bitmap
.pitch
;
5721 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5725 for (y
= 0; y
< height
; y
++) {
5726 for (x
= 0; x
< width
; x
++)
5727 if (src
[x
/ 8] & masks
[x
% 8])
5728 dst
[x
] = DWRITE_ALPHA_MAX
;
5729 src
+= glyph_bitmap
.pitch
;
5730 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5735 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5736 for (y
= 0; y
< height
; y
++) {
5737 for (x
= 0; x
< width
; x
++)
5738 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5739 src
+= glyph_bitmap
.pitch
;
5740 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5744 for (y
= 0; y
< height
; y
++) {
5745 for (x
= 0; x
< width
; x
++)
5747 src
+= glyph_bitmap
.pitch
;
5748 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5753 heap_free(glyph_bitmap
.buf
);
5755 IDWriteFontFace4_Release(fontface
);
5757 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5759 /* we don't need this anymore */
5760 heap_free(analysis
->glyphs
);
5761 heap_free(analysis
->origins
);
5762 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5764 analysis
->glyphs
= NULL
;
5765 analysis
->origins
= NULL
;
5766 analysis
->run
.glyphIndices
= NULL
;
5767 analysis
->run
.fontFace
= NULL
;
5772 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5773 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5775 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5779 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5781 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5782 return E_INVALIDARG
;
5784 /* make sure buffer is large enough for requested texture type */
5785 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5786 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5789 if (size
< required
)
5790 return E_NOT_SUFFICIENT_BUFFER
;
5792 /* validate requested texture type */
5793 if (analysis
->texture_type
!= type
)
5794 return DWRITE_E_UNSUPPORTEDOPERATION
;
5796 memset(bitmap
, 0, size
);
5797 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
5798 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
5800 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5801 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
5802 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5803 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5807 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
5811 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
5815 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
5816 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5818 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5819 memcpy(dst
, src
, draw_width
);
5828 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5829 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5831 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5833 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
5836 return E_INVALIDARG
;
5838 switch (analysis
->rendering_mode
)
5840 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5841 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5844 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5845 *gamma
= (FLOAT
)value
/ 1000.0f
;
5847 *cleartypelevel
= 1.0f
;
5850 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5851 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5853 case DWRITE_RENDERING_MODE1_ALIASED
:
5854 case DWRITE_RENDERING_MODE1_NATURAL
:
5855 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5856 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5857 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5858 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5867 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
5869 glyphrunanalysis_QueryInterface
,
5870 glyphrunanalysis_AddRef
,
5871 glyphrunanalysis_Release
,
5872 glyphrunanalysis_GetAlphaTextureBounds
,
5873 glyphrunanalysis_CreateAlphaTexture
,
5874 glyphrunanalysis_GetAlphaBlendParams
5877 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5880 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5881 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5885 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5886 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5888 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5892 FIXME("Sideways mode is not supported.\n");
5894 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5896 switch (measuring_mode
)
5898 case DWRITE_MEASURING_MODE_NATURAL
:
5899 return (float)advance
* emsize
/ (float)upem
;
5900 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5901 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5902 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5904 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5909 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5911 struct dwrite_glyphrunanalysis
*analysis
;
5912 struct dwrite_fontface
*fontface
;
5913 D2D_POINT_2F origin
;
5919 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5920 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5921 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5922 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5923 return E_INVALIDARG
;
5925 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5926 return E_INVALIDARG
;
5928 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5929 return E_INVALIDARG
;
5931 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5932 return E_INVALIDARG
;
5934 analysis
= heap_alloc(sizeof(*analysis
));
5936 return E_OUTOFMEMORY
;
5938 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5939 analysis
->refcount
= 1;
5940 analysis
->rendering_mode
= desc
->rendering_mode
;
5942 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5943 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5944 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5946 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5948 analysis
->flags
= 0;
5949 analysis
->bitmap
= NULL
;
5950 analysis
->max_glyph_bitmap_size
= 0;
5951 SetRectEmpty(&analysis
->bounds
);
5952 analysis
->run
= *desc
->run
;
5953 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5954 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
5955 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
5957 if (!analysis
->glyphs
|| !analysis
->origins
) {
5958 heap_free(analysis
->glyphs
);
5959 heap_free(analysis
->origins
);
5961 analysis
->glyphs
= NULL
;
5962 analysis
->origins
= NULL
;
5964 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5965 return E_OUTOFMEMORY
;
5968 /* check if transform is usable */
5969 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5970 analysis
->m
= *desc
->transform
;
5971 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5974 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5976 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5977 analysis
->run
.glyphAdvances
= NULL
;
5978 analysis
->run
.glyphOffsets
= NULL
;
5980 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5982 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5984 fontface
= unsafe_impl_from_IDWriteFontFace(desc
->run
->fontFace
);
5986 origin
.x
= desc
->origin
.x
;
5987 origin
.y
= desc
->origin
.y
;
5988 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
5992 /* Use nominal advances if not provided by caller. */
5993 if (desc
->run
->glyphAdvances
)
5994 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
];
5996 advance
= rtl_factor
* fontface_get_scaled_design_advance(fontface
, desc
->measuring_mode
,
5997 desc
->run
->fontEmSize
, 1.0f
, desc
->transform
, desc
->run
->glyphIndices
[i
], desc
->run
->isSideways
);
5999 analysis
->origins
[i
] = origin
;
6000 if (desc
->run
->bidiLevel
& 1)
6002 if (desc
->run
->isSideways
)
6003 analysis
->origins
[i
].y
+= advance
;
6005 analysis
->origins
[i
].x
+= advance
;
6008 /* Offsets are optional, appled to pre-transformed origin. */
6009 if (desc
->run
->glyphOffsets
) {
6010 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
;
6011 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
;
6013 if (desc
->run
->isSideways
) {
6014 analysis
->origins
[i
].x
+= ascenderoffset
;
6015 analysis
->origins
[i
].y
+= advanceoffset
;
6018 analysis
->origins
[i
].x
+= advanceoffset
;
6019 analysis
->origins
[i
].y
+= ascenderoffset
;
6023 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6024 transform_point(analysis
->origins
+ i
, &analysis
->m
);
6026 if (desc
->run
->isSideways
)
6027 origin
.y
+= advance
;
6029 origin
.x
+= advance
;
6032 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6036 /* IDWriteColorGlyphRunEnumerator1 */
6037 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6039 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6041 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6042 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6043 IsEqualIID(riid
, &IID_IUnknown
))
6046 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6050 WARN("%s not implemented.\n", debugstr_guid(riid
));
6053 return E_NOINTERFACE
;
6056 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6058 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6059 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6061 TRACE("%p, refcount %u.\n", iface
, refcount
);
6066 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6068 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6069 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6071 TRACE("%p, refcount %u.\n", iface
, refcount
);
6075 heap_free(glyphenum
->advances
);
6076 heap_free(glyphenum
->color_advances
);
6077 heap_free(glyphenum
->offsets
);
6078 heap_free(glyphenum
->color_offsets
);
6079 heap_free(glyphenum
->glyphindices
);
6080 heap_free(glyphenum
->glyphs
);
6081 if (glyphenum
->colr
.context
)
6082 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6083 IDWriteFontFace5_Release(glyphenum
->fontface
);
6084 heap_free(glyphenum
);
6090 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6092 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6093 FLOAT origin
= 0.0f
;
6099 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6103 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6105 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6106 FLOAT advance_adj
= 0.0f
;
6107 BOOL got_palette_index
;
6110 /* start with regular glyphs */
6111 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6112 UINT32 first_glyph
= 0;
6114 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6115 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6116 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6117 first_glyph
= min(first_glyph
, g
);
6120 glyphenum
->glyphindices
[g
] = 1;
6121 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6122 if (glyphenum
->color_offsets
)
6123 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6126 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6127 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6128 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6129 colorrun
->paletteIndex
= 0xffff;
6130 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6131 glyphenum
->has_regular_glyphs
= FALSE
;
6135 colorrun
->glyphRun
.glyphCount
= 0;
6136 got_palette_index
= FALSE
;
6140 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6142 glyphenum
->glyphindices
[g
] = 1;
6144 /* all glyph layers were returned */
6145 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6146 advance_adj
+= glyphenum
->advances
[g
];
6150 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6151 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6152 if (!got_palette_index
) {
6153 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6154 /* use foreground color or request one from the font */
6155 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6156 if (colorrun
->paletteIndex
!= 0xffff)
6158 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6159 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6161 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6162 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6164 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6165 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6166 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6167 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6168 got_palette_index
= TRUE
;
6171 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6172 /* offsets are relative to glyph origin, nothing to fix up */
6173 if (glyphenum
->color_offsets
)
6174 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6175 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6177 glyphenum
->color_advances
[index
-1] += advance_adj
;
6178 colorrun
->glyphRun
.glyphCount
++;
6182 advance_adj
+= glyphenum
->advances
[g
];
6185 /* reset last advance */
6186 if (colorrun
->glyphRun
.glyphCount
)
6187 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6189 return colorrun
->glyphRun
.glyphCount
> 0;
6192 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6194 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6196 TRACE("%p, %p.\n", iface
, has_run
);
6200 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6201 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6203 if (colorglyphenum_build_color_run(glyphenum
))
6206 glyphenum
->current_layer
++;
6209 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6214 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6215 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6217 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6220 return E_NOT_VALID_STATE
;
6223 *run
= &glyphenum
->colorrun
;
6227 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6228 DWRITE_COLOR_GLYPH_RUN
const **run
)
6230 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6232 TRACE("%p, %p.\n", iface
, run
);
6234 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6237 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6238 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6240 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6242 TRACE("%p, %p.\n", iface
, run
);
6244 return colorglyphenum_get_current_run(glyphenum
, run
);
6247 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6249 colorglyphenum_QueryInterface
,
6250 colorglyphenum_AddRef
,
6251 colorglyphenum_Release
,
6252 colorglyphenum_MoveNext
,
6253 colorglyphenum_GetCurrentRun
,
6254 colorglyphenum1_GetCurrentRun
,
6257 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6258 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6259 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6261 struct dwrite_colorglyphenum
*colorglyphenum
;
6262 BOOL colorfont
, has_colored_glyph
;
6263 struct dwrite_fontface
*fontface
;
6268 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6270 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6271 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6273 return DWRITE_E_NOCOLOR
;
6275 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6276 if (!colorglyphenum
)
6277 return E_OUTOFMEMORY
;
6279 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6280 colorglyphenum
->refcount
= 1;
6281 colorglyphenum
->origin_x
= originX
;
6282 colorglyphenum
->origin_y
= originY
;
6283 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6284 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6285 colorglyphenum
->glyphs
= NULL
;
6286 colorglyphenum
->run
= *run
;
6287 colorglyphenum
->run
.glyphIndices
= NULL
;
6288 colorglyphenum
->run
.glyphAdvances
= NULL
;
6289 colorglyphenum
->run
.glyphOffsets
= NULL
;
6290 colorglyphenum
->palette
= palette
;
6291 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6292 colorglyphenum
->colr
.exists
= TRUE
;
6293 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6294 colorglyphenum
->current_layer
= 0;
6295 colorglyphenum
->max_layer_num
= 0;
6297 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6299 has_colored_glyph
= FALSE
;
6300 colorglyphenum
->has_regular_glyphs
= FALSE
;
6301 for (i
= 0; i
< run
->glyphCount
; i
++) {
6302 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6303 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6304 has_colored_glyph
= TRUE
;
6306 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6307 colorglyphenum
->has_regular_glyphs
= TRUE
;
6310 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6311 is supposed to proceed normally, like if font had no color info at all. */
6312 if (!has_colored_glyph
) {
6313 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6314 return DWRITE_E_NOCOLOR
;
6317 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6318 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6319 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6320 if (run
->glyphOffsets
) {
6321 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6322 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6323 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6326 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6327 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6328 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6329 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6330 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6331 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6332 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6333 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6335 if (run
->glyphAdvances
)
6336 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6339 for (i
= 0; i
< run
->glyphCount
; ++i
)
6340 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6341 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6344 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6349 /* IDWriteFontFaceReference */
6350 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6352 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6354 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6355 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6356 IsEqualIID(riid
, &IID_IUnknown
))
6359 IDWriteFontFaceReference1_AddRef(iface
);
6363 WARN("%s not implemented.\n", debugstr_guid(riid
));
6367 return E_NOINTERFACE
;
6370 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6372 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6373 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6375 TRACE("%p, refcount %u.\n", iface
, refcount
);
6380 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6382 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6383 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6385 TRACE("%p, refcount %u.\n", iface
, refcount
);
6389 IDWriteFontFile_Release(reference
->file
);
6390 IDWriteFactory7_Release(reference
->factory
);
6391 heap_free(reference
->axis_values
);
6392 heap_free(reference
);
6398 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6400 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6402 TRACE("%p, %p.\n", iface
, fontface
);
6404 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6407 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6408 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6410 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6411 DWRITE_FONT_FILE_TYPE file_type
;
6412 DWRITE_FONT_FACE_TYPE face_type
;
6413 IDWriteFontFace
*fontface
;
6418 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6420 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6424 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6425 simulations
, &fontface
);
6428 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6429 IDWriteFontFace_Release(fontface
);
6435 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6437 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6438 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6441 TRACE("%p, %p.\n", iface
, ref
);
6443 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6444 reference
->simulations
== other
->simulations
;
6445 if (reference
->axis_values_count
)
6447 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6448 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6454 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6456 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6458 TRACE("%p.\n", iface
);
6460 return reference
->index
;
6463 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6465 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6467 TRACE("%p.\n", iface
);
6469 return reference
->simulations
;
6472 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6474 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6475 IDWriteFontFileLoader
*loader
;
6480 TRACE("%p, %p.\n", iface
, file
);
6482 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6486 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6490 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6491 IDWriteFontFileLoader_Release(loader
);
6496 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6498 FIXME("%p.\n", iface
);
6503 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6505 FIXME("%p.\n", iface
);
6510 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6512 FIXME("%p, %p.\n", iface
, writetime
);
6517 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6519 FIXME("%p.\n", iface
);
6521 return DWRITE_LOCALITY_LOCAL
;
6524 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6526 FIXME("%p.\n", iface
);
6531 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6532 WCHAR
const *chars
, UINT32 count
)
6534 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6539 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6540 UINT16
const *glyphs
, UINT32 count
)
6542 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6547 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6548 UINT64 offset
, UINT64 size
)
6550 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6555 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6557 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6558 IDWriteFontFace3
*fontface3
;
6561 TRACE("%p, %p.\n", iface
, fontface
);
6563 /* FIXME: created instance should likely respect given axis. */
6564 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6567 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6568 IDWriteFontFace3_Release(fontface3
);
6574 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6576 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6578 TRACE("%p.\n", iface
);
6580 return reference
->axis_values_count
;
6583 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6584 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6586 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6588 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6590 if (value_count
< reference
->axis_values_count
)
6591 return E_NOT_SUFFICIENT_BUFFER
;
6593 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6598 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6600 fontfacereference_QueryInterface
,
6601 fontfacereference_AddRef
,
6602 fontfacereference_Release
,
6603 fontfacereference_CreateFontFace
,
6604 fontfacereference_CreateFontFaceWithSimulations
,
6605 fontfacereference_Equals
,
6606 fontfacereference_GetFontFaceIndex
,
6607 fontfacereference_GetSimulations
,
6608 fontfacereference_GetFontFile
,
6609 fontfacereference_GetLocalFileSize
,
6610 fontfacereference_GetFileSize
,
6611 fontfacereference_GetFileTime
,
6612 fontfacereference_GetLocality
,
6613 fontfacereference_EnqueueFontDownloadRequest
,
6614 fontfacereference_EnqueueCharacterDownloadRequest
,
6615 fontfacereference_EnqueueGlyphDownloadRequest
,
6616 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6617 fontfacereference1_CreateFontFace
,
6618 fontfacereference1_GetFontAxisValueCount
,
6619 fontfacereference1_GetFontAxisValues
,
6622 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6623 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6624 IDWriteFontFaceReference1
**ret
)
6626 struct dwrite_fontfacereference
*object
;
6630 if (!is_simulation_valid(simulations
))
6631 return E_INVALIDARG
;
6633 object
= heap_alloc_zero(sizeof(*object
));
6635 return E_OUTOFMEMORY
;
6637 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6638 object
->refcount
= 1;
6640 object
->factory
= factory
;
6641 IDWriteFactory7_AddRef(object
->factory
);
6642 object
->file
= file
;
6643 IDWriteFontFile_AddRef(object
->file
);
6644 object
->index
= index
;
6645 object
->simulations
= simulations
;
6646 if (axis_values_count
)
6648 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6650 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6651 return E_OUTOFMEMORY
;
6653 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6654 object
->axis_values_count
= axis_values_count
;
6657 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6662 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6664 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6666 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6668 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6670 IDWriteFontFileStream_AddRef(iface
);
6676 WARN("%s not implemented.\n", debugstr_guid(riid
));
6677 return E_NOINTERFACE
;
6680 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6682 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6683 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6684 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6688 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6690 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6691 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6693 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6696 release_inmemory_stream(stream
->data
);
6703 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6704 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6706 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6708 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6709 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6711 *fragment_context
= NULL
;
6713 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6714 *fragment_start
= NULL
;
6718 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6722 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6724 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6726 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6729 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6731 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6733 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6735 *size
= stream
->data
->size
;
6740 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6742 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6744 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6746 *last_writetime
= 0;
6751 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6752 inmemoryfilestream_QueryInterface
,
6753 inmemoryfilestream_AddRef
,
6754 inmemoryfilestream_Release
,
6755 inmemoryfilestream_ReadFileFragment
,
6756 inmemoryfilestream_ReleaseFileFragment
,
6757 inmemoryfilestream_GetFileSize
,
6758 inmemoryfilestream_GetLastWriteTime
,
6761 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6762 REFIID riid
, void **obj
)
6764 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6766 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6768 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6769 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6770 IsEqualIID(riid
, &IID_IUnknown
))
6773 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6777 WARN("%s not implemented.\n", debugstr_guid(riid
));
6781 return E_NOINTERFACE
;
6784 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6786 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6787 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6788 TRACE("(%p)->(%u)\n", loader
, ref
);
6792 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6794 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6795 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6798 TRACE("(%p)->(%u)\n", loader
, ref
);
6801 for (i
= 0; i
< loader
->count
; ++i
)
6802 release_inmemory_stream(loader
->streams
[i
]);
6803 heap_free(loader
->streams
);
6810 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6811 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6813 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6814 struct dwrite_inmemory_filestream
*stream
;
6817 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6821 if (key_size
!= sizeof(DWORD
))
6822 return E_INVALIDARG
;
6824 index
= *(DWORD
*)key
;
6826 if (index
>= loader
->count
)
6827 return E_INVALIDARG
;
6829 if (!(stream
= heap_alloc(sizeof(*stream
))))
6830 return E_OUTOFMEMORY
;
6832 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6834 stream
->data
= loader
->streams
[index
];
6835 InterlockedIncrement(&stream
->data
->ref
);
6837 *ret
= &stream
->IDWriteFontFileStream_iface
;
6842 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6843 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6845 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6846 struct dwrite_inmemory_stream_data
*stream
;
6849 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6853 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6854 return E_OUTOFMEMORY
;
6856 if (!(stream
= heap_alloc(sizeof(*stream
))))
6857 return E_OUTOFMEMORY
;
6860 stream
->size
= data_size
;
6861 stream
->owner
= owner
;
6862 if (stream
->owner
) {
6863 IUnknown_AddRef(stream
->owner
);
6864 stream
->data
= (void *)data
;
6867 if (!(stream
->data
= heap_alloc(data_size
))) {
6869 return E_OUTOFMEMORY
;
6871 memcpy(stream
->data
, data
, data_size
);
6874 key
= loader
->count
;
6875 loader
->streams
[loader
->count
++] = stream
;
6877 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6878 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6881 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6883 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6885 TRACE("%p.\n", iface
);
6887 return loader
->count
;
6890 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6892 inmemoryfontfileloader_QueryInterface
,
6893 inmemoryfontfileloader_AddRef
,
6894 inmemoryfontfileloader_Release
,
6895 inmemoryfontfileloader_CreateStreamFromKey
,
6896 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6897 inmemoryfontfileloader_GetFileCount
,
6900 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6902 struct dwrite_inmemory_fileloader
*loader
;
6906 loader
= heap_alloc_zero(sizeof(*loader
));
6908 return E_OUTOFMEMORY
;
6910 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6913 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6918 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6920 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6922 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6923 IsEqualIID(riid
, &IID_IUnknown
))
6926 IDWriteFontResource_AddRef(iface
);
6930 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6932 return E_NOINTERFACE
;
6935 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6937 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6938 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6940 TRACE("%p, refcount %u.\n", iface
, refcount
);
6945 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6947 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6948 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6950 TRACE("%p, refcount %u.\n", iface
, refcount
);
6954 IDWriteFactory7_Release(resource
->factory
);
6955 IDWriteFontFile_Release(resource
->file
);
6956 heap_free(resource
);
6962 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6964 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6966 TRACE("%p, %p.\n", iface
, fontfile
);
6968 *fontfile
= resource
->file
;
6969 IDWriteFontFile_AddRef(*fontfile
);
6974 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6976 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6978 TRACE("%p.\n", iface
);
6980 return resource
->face_index
;
6983 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6985 FIXME("%p.\n", iface
);
6990 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6991 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6993 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
6998 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
6999 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
7001 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
7006 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7009 FIXME("%p, %u.\n", iface
, axis
);
7011 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
7014 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7015 IDWriteLocalizedStrings
**names
)
7017 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7022 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7024 FIXME("%p, %u.\n", iface
, axis
);
7029 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7030 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7032 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7037 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7039 FIXME("%p.\n", iface
);
7044 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7045 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7046 IDWriteFontFace5
**fontface
)
7048 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7049 IDWriteFontFaceReference1
*reference
;
7052 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7054 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7055 simulations
, axis_values
, num_values
, &reference
);
7058 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7059 IDWriteFontFaceReference1_Release(reference
);
7065 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7066 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7067 IDWriteFontFaceReference1
**reference
)
7069 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7071 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7073 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7074 simulations
, axis_values
, num_values
, reference
);
7077 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7079 dwritefontresource_QueryInterface
,
7080 dwritefontresource_AddRef
,
7081 dwritefontresource_Release
,
7082 dwritefontresource_GetFontFile
,
7083 dwritefontresource_GetFontFaceIndex
,
7084 dwritefontresource_GetFontAxisCount
,
7085 dwritefontresource_GetDefaultFontAxisValues
,
7086 dwritefontresource_GetFontAxisRanges
,
7087 dwritefontresource_GetFontAxisAttributes
,
7088 dwritefontresource_GetAxisNames
,
7089 dwritefontresource_GetAxisValueNameCount
,
7090 dwritefontresource_GetAxisValueNames
,
7091 dwritefontresource_HasVariations
,
7092 dwritefontresource_CreateFontFace
,
7093 dwritefontresource_CreateFontFaceReference
,
7096 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7097 IDWriteFontResource
**ret
)
7099 struct dwrite_fontresource
*resource
;
7103 resource
= heap_alloc_zero(sizeof(*resource
));
7105 return E_OUTOFMEMORY
;
7107 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7108 resource
->refcount
= 1;
7109 resource
->face_index
= face_index
;
7110 resource
->file
= file
;
7111 IDWriteFontFile_AddRef(resource
->file
);
7112 resource
->factory
= factory
;
7113 IDWriteFactory7_AddRef(resource
->factory
);
7115 *ret
= &resource
->IDWriteFontResource_iface
;