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 /* Static axis for weight/width/italic. */
84 DWRITE_FONT_AXIS_VALUE axis
[3];
86 DWRITE_FONT_METRICS1 metrics
;
87 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
88 IDWriteLocalizedStrings
*family_names
;
89 IDWriteLocalizedStrings
*names
;
91 /* data needed to create fontface instance */
92 DWRITE_FONT_FACE_TYPE face_type
;
93 IDWriteFontFile
*file
;
102 /* used to mark font as tested when scanning for simulation candidate */
103 BOOL bold_sim_tested
: 1;
104 BOOL oblique_sim_tested
: 1;
107 struct dwrite_fontfamily_data
111 IDWriteLocalizedStrings
*familyname
;
113 struct dwrite_font_data
**fonts
;
117 BOOL has_normal_face
: 1;
118 BOOL has_oblique_face
: 1;
119 BOOL has_italic_face
: 1;
122 struct dwrite_fontcollection
124 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
127 IDWriteFactory7
*factory
;
128 struct dwrite_fontfamily_data
**family_data
;
133 struct dwrite_fontfamily
135 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
136 IDWriteFontList2 IDWriteFontList2_iface
;
139 struct dwrite_fontfamily_data
*data
;
140 struct dwrite_fontcollection
*collection
;
143 struct dwrite_fontlist
145 IDWriteFontList2 IDWriteFontList2_iface
;
148 struct dwrite_font_data
**fonts
;
150 struct dwrite_fontfamily
*family
;
154 IDWriteFont3 IDWriteFont3_iface
;
157 DWRITE_FONT_STYLE style
;
158 struct dwrite_font_data
*data
;
159 struct dwrite_fontfamily
*family
;
162 enum runanalysis_flags
{
163 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
164 RUNANALYSIS_BITMAP_READY
= 1 << 1,
165 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
168 struct dwrite_glyphrunanalysis
{
169 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
172 DWRITE_RENDERING_MODE1 rendering_mode
;
173 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
174 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
177 D2D_POINT_2F
*origins
;
182 UINT32 max_glyph_bitmap_size
;
185 struct dwrite_colorglyphenum
187 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
190 FLOAT origin_x
; /* original run origin */
193 IDWriteFontFace5
*fontface
; /* for convenience */
194 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
195 DWRITE_GLYPH_RUN run
; /* base run */
196 UINT32 palette
; /* palette index to get layer color from */
197 FLOAT
*advances
; /* original or measured advances for base glyphs */
198 FLOAT
*color_advances
; /* returned color run points to this */
199 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
200 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
201 UINT16
*glyphindices
; /* returned color run points to this */
202 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
203 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
204 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
205 UINT16 max_layer_num
; /* max number of layers for this run */
206 struct dwrite_fonttable colr
; /* used to access layers */
209 #define GLYPH_BLOCK_SHIFT 8
210 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
211 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
212 #define GLYPH_MAX 65536
214 struct dwrite_fontfile
{
215 IDWriteFontFile IDWriteFontFile_iface
;
218 IDWriteFontFileLoader
*loader
;
221 IDWriteFontFileStream
*stream
;
224 struct dwrite_fontfacereference
226 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
229 IDWriteFontFile
*file
;
232 DWRITE_FONT_AXIS_VALUE
*axis_values
;
233 UINT32 axis_values_count
;
234 IDWriteFactory7
*factory
;
237 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
239 struct dwrite_fontresource
241 IDWriteFontResource IDWriteFontResource_iface
;
244 IDWriteFontFile
*file
;
246 IDWriteFactory7
*factory
;
249 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
251 struct dwrite_fontface
*fontface
= context
;
254 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
255 size
, data_context
, &exists
)) || !exists
)
259 *data_context
= NULL
;
263 static void dwrite_release_font_table(void *context
, void *data_context
)
265 struct dwrite_fontface
*fontface
= context
;
266 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
269 static UINT16
dwrite_get_font_upem(void *context
)
271 struct dwrite_fontface
*fontface
= context
;
272 return fontface
->metrics
.designUnitsPerEm
;
275 static const struct shaping_font_ops dwrite_font_ops
=
277 dwrite_grab_font_table
,
278 dwrite_release_font_table
,
279 dwrite_get_font_upem
,
282 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
284 if (fontface
->shaping_cache
)
285 return fontface
->shaping_cache
;
287 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
290 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
292 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
295 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
297 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
300 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
302 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
305 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
307 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
309 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
312 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
314 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
317 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
319 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
322 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
324 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
327 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
329 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
332 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
334 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
337 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
339 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
342 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
344 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
347 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
349 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
352 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
354 static const DWRITE_GLYPH_METRICS nil
;
355 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
357 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
358 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
362 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
364 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
367 /* start new block */
368 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
370 return E_OUTOFMEMORY
;
373 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
377 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
381 if (table
->data
|| !table
->exists
)
384 table
->exists
= FALSE
;
385 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
387 if (FAILED(hr
) || !table
->exists
) {
388 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
395 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
396 struct dwrite_font_propvec
*vec
)
398 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
399 vec
->style
= style
* 7.0f
;
400 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
403 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
405 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
408 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
410 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
413 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
415 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
416 return &fontface
->vdmx
;
419 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
421 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
422 return &fontface
->gasp
;
425 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
427 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
428 return &fontface
->cpal
;
431 static void addref_font_data(struct dwrite_font_data
*data
)
433 InterlockedIncrement(&data
->ref
);
436 static void release_font_data(struct dwrite_font_data
*data
)
440 if (InterlockedDecrement(&data
->ref
) > 0)
443 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
445 if (data
->info_strings
[i
])
446 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
449 IDWriteLocalizedStrings_Release(data
->names
);
451 if (data
->family_names
)
452 IDWriteLocalizedStrings_Release(data
->family_names
);
454 IDWriteFontFile_Release(data
->file
);
455 heap_free(data
->facename
);
459 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
463 if (InterlockedDecrement(&data
->refcount
) > 0)
466 for (i
= 0; i
< data
->count
; ++i
)
467 release_font_data(data
->fonts
[i
]);
468 heap_free(data
->fonts
);
469 IDWriteLocalizedStrings_Release(data
->familyname
);
473 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
475 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
476 fontface
->cached
= NULL
;
479 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
481 UINT32 left_key_size
, right_key_size
;
482 const void *left_key
, *right_key
;
488 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
492 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
496 if (left_key_size
!= right_key_size
)
499 return !memcmp(left_key
, right_key
, left_key_size
);
502 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
504 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
506 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
508 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
509 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
510 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
511 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
512 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
513 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
514 IsEqualIID(riid
, &IID_IUnknown
))
518 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
519 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
525 if (InterlockedIncrement(&fontface
->refcount
) == 1)
527 InterlockedDecrement(&fontface
->refcount
);
534 WARN("%s not implemented.\n", debugstr_guid(riid
));
536 return E_NOINTERFACE
;
539 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
541 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
542 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
544 TRACE("%p, refcount %u.\n", iface
, refcount
);
549 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
551 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
552 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
554 TRACE("%p, refcount %u.\n", iface
, refcount
);
560 if (fontface
->cached
)
562 factory_lock(fontface
->factory
);
563 list_remove(&fontface
->cached
->entry
);
564 factory_unlock(fontface
->factory
);
565 heap_free(fontface
->cached
);
567 release_scriptshaping_cache(fontface
->shaping_cache
);
568 if (fontface
->cmap
.context
)
569 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cmap
.context
);
570 if (fontface
->vdmx
.context
)
571 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
572 if (fontface
->gasp
.context
)
573 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
574 if (fontface
->cpal
.context
)
575 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
576 if (fontface
->colr
.context
)
577 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
578 for (i
= 0; i
< fontface
->file_count
; i
++)
580 if (fontface
->files
[i
])
581 IDWriteFontFile_Release(fontface
->files
[i
]);
583 if (fontface
->stream
)
584 IDWriteFontFileStream_Release(fontface
->stream
);
585 heap_free(fontface
->files
);
587 IDWriteLocalizedStrings_Release(fontface
->names
);
588 if (fontface
->family_names
)
589 IDWriteLocalizedStrings_Release(fontface
->family_names
);
590 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
592 if (fontface
->info_strings
[i
])
593 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
596 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
597 heap_free(fontface
->glyphs
[i
]);
599 freetype_notify_cacheremove(iface
);
601 IDWriteFactory7_Release(fontface
->factory
);
608 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
610 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
612 TRACE("%p.\n", iface
);
614 return fontface
->type
;
617 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
618 IDWriteFontFile
**fontfiles
)
620 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
623 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
625 if (fontfiles
== NULL
)
627 *number_of_files
= fontface
->file_count
;
631 if (*number_of_files
< fontface
->file_count
)
634 for (i
= 0; i
< fontface
->file_count
; i
++)
636 IDWriteFontFile_AddRef(fontface
->files
[i
]);
637 fontfiles
[i
] = fontface
->files
[i
];
643 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
645 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
647 TRACE("%p.\n", iface
);
649 return fontface
->index
;
652 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
654 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
656 TRACE("%p.\n", iface
);
658 return fontface
->simulations
;
661 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
663 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
665 TRACE("%p.\n", iface
);
667 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
670 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
672 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
674 TRACE("%p, %p.\n", iface
, metrics
);
676 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
679 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
681 TRACE("%p.\n", iface
);
683 return freetype_get_glyphcount(iface
);
686 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
687 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
689 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
693 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
699 FIXME("sideways metrics are not supported.\n");
701 for (i
= 0; i
< glyph_count
; i
++) {
702 DWRITE_GLYPH_METRICS metrics
;
704 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
706 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
707 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
717 static HRESULT
fontface_get_glyphs(struct dwrite_fontface
*fontface
, UINT32
const *codepoints
,
718 UINT32 count
, UINT16
*glyphs
)
724 memset(glyphs
, 0, count
* sizeof(*glyphs
));
728 freetype_get_glyphs(&fontface
->IDWriteFontFace5_iface
, fontface
->charmap
, codepoints
, count
, glyphs
);
732 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
733 UINT32 count
, UINT16
*glyphs
)
735 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
737 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
739 return fontface_get_glyphs(fontface
, codepoints
, count
, glyphs
);
742 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
743 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
745 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
746 struct file_stream_desc stream_desc
;
748 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
750 stream_desc
.stream
= fontface
->stream
;
751 stream_desc
.face_type
= fontface
->type
;
752 stream_desc
.face_index
= fontface
->index
;
753 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
756 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
758 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
760 TRACE("%p, %p.\n", iface
, table_context
);
762 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
765 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
766 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
767 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
769 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
770 count
, is_sideways
, is_rtl
, sink
);
772 if (!glyphs
|| !sink
)
776 FIXME("sideways mode is not supported.\n");
778 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
781 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
782 float ppem
, unsigned int gasp
)
784 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
788 case DWRITE_MEASURING_MODE_NATURAL
:
790 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
791 mode
= DWRITE_RENDERING_MODE_NATURAL
;
793 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
796 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
797 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
799 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
800 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
809 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
810 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
812 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
816 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
819 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
823 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
824 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
827 ppem
= emSize
* ppdip
;
829 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
830 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
834 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
835 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
839 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
840 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
842 DWRITE_FONT_METRICS1 metrics1
;
843 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
844 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
848 static inline int round_metric(FLOAT metric
)
850 return (int)floorf(metric
+ 0.5f
);
853 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
855 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
858 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
861 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
862 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
863 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
865 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
866 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
867 DWRITE_MEASURING_MODE mode
;
872 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
873 glyph_count
, metrics
, is_sideways
);
875 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
876 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
878 size
= emSize
* ppdip
;
879 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
880 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
882 for (i
= 0; i
< glyph_count
; i
++) {
883 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
884 DWRITE_GLYPH_METRICS design
;
887 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
891 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
893 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
895 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
897 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
898 SCALE_METRIC(leftSideBearing
);
899 SCALE_METRIC(rightSideBearing
);
900 SCALE_METRIC(topSideBearing
);
901 SCALE_METRIC(advanceHeight
);
902 SCALE_METRIC(bottomSideBearing
);
903 SCALE_METRIC(verticalOriginY
);
910 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
912 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
914 TRACE("%p, %p.\n", iface
, metrics
);
916 *metrics
= fontface
->metrics
;
919 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
920 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
922 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
923 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
924 UINT16 ascent
, descent
;
927 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
929 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
930 memset(metrics
, 0, sizeof(*metrics
));
934 em_size
*= pixels_per_dip
;
935 if (m
&& m
->m22
!= 0.0f
)
936 em_size
*= fabs(m
->m22
);
938 scale
= em_size
/ design
->designUnitsPerEm
;
939 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
941 ascent
= round_metric(design
->ascent
* scale
);
942 descent
= round_metric(design
->descent
* scale
);
945 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
946 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
947 metrics
->ascent
= round_metric(ascent
/ scale
);
948 metrics
->descent
= round_metric(descent
/ scale
);
950 SCALE_METRIC(lineGap
);
951 SCALE_METRIC(capHeight
);
952 SCALE_METRIC(xHeight
);
953 SCALE_METRIC(underlinePosition
);
954 SCALE_METRIC(underlineThickness
);
955 SCALE_METRIC(strikethroughPosition
);
956 SCALE_METRIC(strikethroughThickness
);
957 SCALE_METRIC(glyphBoxLeft
);
958 SCALE_METRIC(glyphBoxTop
);
959 SCALE_METRIC(glyphBoxRight
);
960 SCALE_METRIC(glyphBoxBottom
);
961 SCALE_METRIC(subscriptPositionX
);
962 SCALE_METRIC(subscriptPositionY
);
963 SCALE_METRIC(subscriptSizeX
);
964 SCALE_METRIC(subscriptSizeY
);
965 SCALE_METRIC(superscriptPositionX
);
966 SCALE_METRIC(superscriptPositionY
);
967 SCALE_METRIC(superscriptSizeX
);
968 SCALE_METRIC(superscriptSizeY
);
970 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
976 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
978 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
980 TRACE("%p, %p.\n", iface
, metrics
);
982 *metrics
= fontface
->caret
;
985 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
986 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
988 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
989 struct file_stream_desc stream_desc
;
991 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
994 if (max_count
&& !ranges
)
997 stream_desc
.stream
= fontface
->stream
;
998 stream_desc
.face_index
= fontface
->index
;
999 stream_desc
.face_type
= fontface
->type
;
1000 return opentype_cmap_get_unicode_ranges(&stream_desc
, max_count
, ranges
, count
);
1003 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1005 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1007 TRACE("%p.\n", iface
);
1009 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1012 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1013 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1015 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1020 FIXME("Sideways mode is not supported.\n");
1022 switch (measuring_mode
)
1024 case DWRITE_MEASURING_MODE_NATURAL
:
1025 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1026 glyph
, measuring_mode
, &has_contours
);
1028 advance
+= adjustment
;
1031 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1032 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1037 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1038 FIXME("Transform is not supported.\n");
1040 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1043 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1045 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1049 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1054 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1055 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1057 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1060 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1063 FIXME("sideways mode not supported\n");
1065 for (i
= 0; i
< glyph_count
; ++i
)
1067 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1068 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1074 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1075 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1076 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1078 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1079 DWRITE_MEASURING_MODE measuring_mode
;
1082 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1083 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1085 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1086 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1087 return E_INVALIDARG
;
1090 if (em_size
== 0.0f
) {
1091 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1095 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1096 for (i
= 0; i
< glyph_count
; ++i
)
1098 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1099 glyphs
[i
], is_sideways
);
1105 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1106 const UINT16
*indices
, INT32
*adjustments
)
1108 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1111 TRACE("%p, %u, %p, %p.\n", iface
, count
, indices
, adjustments
);
1113 if (!(indices
|| adjustments
) || !count
)
1114 return E_INVALIDARG
;
1116 if (!indices
|| count
== 1) {
1117 memset(adjustments
, 0, count
*sizeof(INT32
));
1118 return E_INVALIDARG
;
1121 if (!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
))
1123 memset(adjustments
, 0, count
*sizeof(INT32
));
1127 for (i
= 0; i
< count
-1; i
++)
1128 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1129 adjustments
[count
-1] = 0;
1134 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1136 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1138 TRACE("%p.\n", iface
);
1140 return !!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1143 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1144 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1145 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1147 DWRITE_GRID_FIT_MODE gridfitmode
;
1148 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1149 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1152 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1153 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
1155 FIXME("%p, %u, %p, %p: stub\n", iface
, glyph_count
, nominal_indices
, vertical_indices
);
1160 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1162 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1164 TRACE("%p.\n", iface
);
1166 return !!(fontface
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1169 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1171 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1173 TRACE("%p.\n", iface
);
1175 return !!(fontface
->flags
& FONT_IS_COLORED
);
1178 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1180 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1182 TRACE("%p.\n", iface
);
1184 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1187 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1189 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1191 TRACE("%p.\n", iface
);
1193 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1196 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1197 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1199 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1201 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1203 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1206 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1207 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1208 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1209 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1211 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1215 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1216 measuringmode
, params
, renderingmode
, gridfitmode
);
1219 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1222 FIXME("sideways mode not supported\n");
1224 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1226 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1227 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1229 IDWriteRenderingParams2
*params2
;
1232 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1234 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1235 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1236 IDWriteRenderingParams2_Release(params2
);
1239 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1242 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1244 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1246 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1247 if (emSize
>= emthreshold
)
1248 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1250 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1253 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1254 if (emSize
>= emthreshold
)
1255 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1256 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1257 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1259 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1260 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1266 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1267 IDWriteFontFaceReference
**reference
)
1269 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1271 TRACE("%p, %p.\n", iface
, reference
);
1273 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1274 IDWriteFontFaceReference_AddRef(*reference
);
1279 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1281 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1283 TRACE("%p, %p.\n", iface
, panose
);
1285 *panose
= fontface
->panose
;
1288 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1290 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1292 TRACE("%p.\n", iface
);
1294 return fontface
->weight
;
1297 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1299 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1301 TRACE("%p.\n", iface
);
1303 return fontface
->stretch
;
1306 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1308 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1310 TRACE("%p.\n", iface
);
1312 return fontface
->style
;
1315 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1317 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1319 TRACE("%p, %p.\n", iface
, names
);
1321 return clone_localizedstrings(fontface
->family_names
, names
);
1324 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1326 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1328 TRACE("%p, %p.\n", iface
, names
);
1330 return clone_localizedstrings(fontface
->names
, names
);
1333 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1334 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1335 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1342 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1343 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1348 if (!strings_cache
[stringid
])
1350 struct file_stream_desc desc
= *stream_desc
;
1353 hr
= get_filestream_from_file(file
, &desc
.stream
);
1355 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1357 if (!stream_desc
->stream
&& desc
.stream
)
1358 IDWriteFontFileStream_Release(desc
.stream
);
1361 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1363 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1371 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1372 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1374 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1375 struct file_stream_desc stream_desc
;
1377 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1379 stream_desc
.stream
= fontface
->stream
;
1380 stream_desc
.face_index
= fontface
->index
;
1381 stream_desc
.face_type
= fontface
->type
;
1382 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1385 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1387 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1390 TRACE("%p, %#x.\n", iface
, ch
);
1393 if (FAILED(fontface_get_glyphs(fontface
, &ch
, 1, &index
)))
1399 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1400 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1401 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1403 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1407 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1408 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1411 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1414 FIXME("sideways mode not supported\n");
1416 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1418 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1419 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1421 IDWriteRenderingParams3
*params3
;
1424 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1426 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1427 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1428 IDWriteRenderingParams3_Release(params3
);
1431 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1434 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1436 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1438 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1439 if (emSize
>= emthreshold
)
1440 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1442 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1445 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1446 if (emSize
>= emthreshold
)
1447 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1448 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1449 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1451 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1452 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1458 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1460 FIXME("%p, %#x: stub\n", iface
, ch
);
1465 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1467 FIXME("%p, %u: stub\n", iface
, glyph
);
1472 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1473 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1475 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1480 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1481 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1483 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1488 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1489 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1491 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1496 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1498 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1500 TRACE("%p.\n", iface
);
1502 return fontface
->glyph_image_formats
;
1505 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1506 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1508 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1513 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1515 FIXME("%p, %p: stub\n", iface
, context
);
1518 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1520 FIXME("%p: stub\n", iface
);
1525 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1528 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1533 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1535 FIXME("%p: stub\n", iface
);
1540 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1542 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1544 TRACE("%p, %p.\n", iface
, resource
);
1546 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->files
[0], fontface
->index
, resource
);
1549 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1551 dwritefontface_QueryInterface
,
1552 dwritefontface_AddRef
,
1553 dwritefontface_Release
,
1554 dwritefontface_GetType
,
1555 dwritefontface_GetFiles
,
1556 dwritefontface_GetIndex
,
1557 dwritefontface_GetSimulations
,
1558 dwritefontface_IsSymbolFont
,
1559 dwritefontface_GetMetrics
,
1560 dwritefontface_GetGlyphCount
,
1561 dwritefontface_GetDesignGlyphMetrics
,
1562 dwritefontface_GetGlyphIndices
,
1563 dwritefontface_TryGetFontTable
,
1564 dwritefontface_ReleaseFontTable
,
1565 dwritefontface_GetGlyphRunOutline
,
1566 dwritefontface_GetRecommendedRenderingMode
,
1567 dwritefontface_GetGdiCompatibleMetrics
,
1568 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1569 dwritefontface1_GetMetrics
,
1570 dwritefontface1_GetGdiCompatibleMetrics
,
1571 dwritefontface1_GetCaretMetrics
,
1572 dwritefontface1_GetUnicodeRanges
,
1573 dwritefontface1_IsMonospacedFont
,
1574 dwritefontface1_GetDesignGlyphAdvances
,
1575 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1576 dwritefontface1_GetKerningPairAdjustments
,
1577 dwritefontface1_HasKerningPairs
,
1578 dwritefontface1_GetRecommendedRenderingMode
,
1579 dwritefontface1_GetVerticalGlyphVariants
,
1580 dwritefontface1_HasVerticalGlyphVariants
,
1581 dwritefontface2_IsColorFont
,
1582 dwritefontface2_GetColorPaletteCount
,
1583 dwritefontface2_GetPaletteEntryCount
,
1584 dwritefontface2_GetPaletteEntries
,
1585 dwritefontface2_GetRecommendedRenderingMode
,
1586 dwritefontface3_GetFontFaceReference
,
1587 dwritefontface3_GetPanose
,
1588 dwritefontface3_GetWeight
,
1589 dwritefontface3_GetStretch
,
1590 dwritefontface3_GetStyle
,
1591 dwritefontface3_GetFamilyNames
,
1592 dwritefontface3_GetFaceNames
,
1593 dwritefontface3_GetInformationalStrings
,
1594 dwritefontface3_HasCharacter
,
1595 dwritefontface3_GetRecommendedRenderingMode
,
1596 dwritefontface3_IsCharacterLocal
,
1597 dwritefontface3_IsGlyphLocal
,
1598 dwritefontface3_AreCharactersLocal
,
1599 dwritefontface3_AreGlyphsLocal
,
1600 dwritefontface4_GetGlyphImageFormats_
,
1601 dwritefontface4_GetGlyphImageFormats
,
1602 dwritefontface4_GetGlyphImageData
,
1603 dwritefontface4_ReleaseGlyphImageData
,
1604 dwritefontface5_GetFontAxisValueCount
,
1605 dwritefontface5_GetFontAxisValues
,
1606 dwritefontface5_HasVariations
,
1607 dwritefontface5_GetFontResource
,
1610 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1612 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1613 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1616 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1618 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1619 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1622 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1624 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1625 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1628 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1629 IDWriteFontFace3
**ret
)
1631 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1633 TRACE("%p, %p.\n", iface
, ret
);
1635 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1636 IDWriteFontFace3_AddRef(*ret
);
1641 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1642 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1644 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1645 DWRITE_FONT_FILE_TYPE file_type
;
1646 DWRITE_FONT_FACE_TYPE face_type
;
1647 IDWriteFontFace
*face
;
1652 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1654 hr
= IDWriteFontFile_Analyze(fontface
->files
[0], &is_supported
, &file_type
, &face_type
, &face_num
);
1658 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, fontface
->files
, fontface
->index
,
1659 simulations
, &face
);
1662 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1663 IDWriteFontFace_Release(face
);
1669 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1671 FIXME("%p, %p.\n", iface
, ref
);
1676 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1678 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1680 TRACE("%p.\n", iface
);
1682 return fontface
->index
;
1685 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1687 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1689 TRACE("%p.\n", iface
);
1691 return fontface
->simulations
;
1694 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1696 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1698 TRACE("%p, %p.\n", iface
, file
);
1700 *file
= fontface
->files
[0];
1701 IDWriteFontFile_AddRef(*file
);
1706 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1708 FIXME("%p.\n", iface
);
1713 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1715 FIXME("%p.\n", iface
);
1720 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1722 FIXME("%p, %p.\n", iface
, writetime
);
1727 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1729 FIXME("%p.\n", iface
);
1731 return DWRITE_LOCALITY_LOCAL
;
1734 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1736 FIXME("%p.\n", iface
);
1741 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1742 WCHAR
const *chars
, UINT32 count
)
1744 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1749 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1750 UINT16
const *glyphs
, UINT32 count
)
1752 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1757 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1758 UINT64 offset
, UINT64 size
)
1760 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1765 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1767 dwritefontface_reference_QueryInterface
,
1768 dwritefontface_reference_AddRef
,
1769 dwritefontface_reference_Release
,
1770 dwritefontface_reference_CreateFontFace
,
1771 dwritefontface_reference_CreateFontFaceWithSimulations
,
1772 dwritefontface_reference_Equals
,
1773 dwritefontface_reference_GetFontFaceIndex
,
1774 dwritefontface_reference_GetSimulations
,
1775 dwritefontface_reference_GetFontFile
,
1776 dwritefontface_reference_GetLocalFileSize
,
1777 dwritefontface_reference_GetFileSize
,
1778 dwritefontface_reference_GetFileTime
,
1779 dwritefontface_reference_GetLocality
,
1780 dwritefontface_reference_EnqueueFontDownloadRequest
,
1781 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1782 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1783 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1786 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1788 struct dwrite_font_data
*data
= font
->data
;
1789 struct fontface_desc desc
;
1790 struct list
*cached_list
;
1795 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1796 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1800 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1803 desc
.factory
= font
->family
->collection
->factory
;
1804 desc
.face_type
= data
->face_type
;
1805 desc
.files
= &data
->file
;
1806 desc
.files_number
= 1;
1807 desc
.index
= data
->face_index
;
1808 desc
.simulations
= data
->simulations
;
1809 desc
.font_data
= data
;
1810 hr
= create_fontface(&desc
, cached_list
, fontface
);
1812 IDWriteFontFileStream_Release(desc
.stream
);
1816 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1818 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1820 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1822 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1823 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1824 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1825 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1826 IsEqualIID(riid
, &IID_IUnknown
))
1829 IDWriteFont3_AddRef(iface
);
1833 WARN("%s not implemented.\n", debugstr_guid(riid
));
1836 return E_NOINTERFACE
;
1839 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1841 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1842 ULONG ref
= InterlockedIncrement(&This
->ref
);
1843 TRACE("(%p)->(%d)\n", This
, ref
);
1847 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1849 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1850 ULONG ref
= InterlockedDecrement(&This
->ref
);
1852 TRACE("(%p)->(%d)\n", This
, ref
);
1855 IDWriteFontFamily2_Release(&This
->family
->IDWriteFontFamily2_iface
);
1856 release_font_data(This
->data
);
1863 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1865 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1866 TRACE("(%p)->(%p)\n", This
, family
);
1868 *family
= (IDWriteFontFamily
*)This
->family
;
1869 IDWriteFontFamily_AddRef(*family
);
1873 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1875 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1876 TRACE("(%p)\n", This
);
1877 return This
->data
->weight
;
1880 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1882 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1883 TRACE("(%p)\n", This
);
1884 return This
->data
->stretch
;
1887 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1889 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1890 TRACE("(%p)\n", This
);
1894 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1896 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1898 TRACE("%p.\n", iface
);
1900 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
1903 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1905 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1907 TRACE("%p, %p.\n", iface
, names
);
1909 return clone_localizedstrings(font
->data
->names
, names
);
1912 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1913 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1915 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1916 struct dwrite_font_data
*data
= font
->data
;
1917 struct file_stream_desc stream_desc
;
1919 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
1921 /* Stream will be created if necessary. */
1922 stream_desc
.stream
= NULL
;
1923 stream_desc
.face_index
= data
->face_index
;
1924 stream_desc
.face_type
= data
->face_type
;
1925 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
1928 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1930 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1931 TRACE("(%p)\n", This
);
1932 return This
->data
->simulations
;
1935 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1937 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1939 TRACE("(%p)->(%p)\n", This
, metrics
);
1940 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1943 static HRESULT
font_has_character(struct dwrite_font
*font
, UINT32 ch
, BOOL
*exists
)
1945 IDWriteFontFace5
*fontface
;
1951 hr
= get_fontface_from_font(font
, &fontface
);
1956 hr
= IDWriteFontFace5_GetGlyphIndices(fontface
, &ch
, 1, &index
);
1957 IDWriteFontFace5_Release(fontface
);
1961 *exists
= index
!= 0;
1965 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
1967 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1969 TRACE("(%p)->(%#x %p)\n", This
, ch
, exists
);
1971 return font_has_character(This
, ch
, exists
);
1974 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1976 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1978 TRACE("%p, %p.\n", iface
, fontface
);
1980 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
1983 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1985 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1986 TRACE("(%p)->(%p)\n", This
, metrics
);
1987 *metrics
= This
->data
->metrics
;
1990 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1992 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1993 TRACE("(%p)->(%p)\n", This
, panose
);
1994 *panose
= This
->data
->panose
;
1997 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2000 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2001 struct file_stream_desc stream_desc
;
2004 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2007 if (max_count
&& !ranges
)
2008 return E_INVALIDARG
;
2010 if (FAILED(hr
= get_filestream_from_file(font
->data
->file
, &stream_desc
.stream
)))
2012 stream_desc
.face_index
= font
->data
->face_index
;
2013 stream_desc
.face_type
= font
->data
->face_type
;
2014 hr
= opentype_cmap_get_unicode_ranges(&stream_desc
, max_count
, ranges
, count
);
2015 IDWriteFontFileStream_Release(stream_desc
.stream
);
2019 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2021 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2023 TRACE("%p.\n", iface
);
2025 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2028 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2030 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2032 TRACE("%p.\n", iface
);
2034 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2037 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2039 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2041 TRACE("%p, %p.\n", iface
, fontface
);
2043 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2046 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2048 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2050 TRACE("%p, %p.\n", iface
, other
);
2052 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2055 return font
->data
->face_index
== other_font
->data
->face_index
2056 && font
->data
->simulations
== other_font
->data
->simulations
2057 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2060 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2062 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2064 TRACE("%p, %p.\n", iface
, reference
);
2066 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2067 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2068 (IDWriteFontFaceReference1
**)reference
);
2071 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2073 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
2076 TRACE("(%p)->(%#x)\n", This
, ch
);
2078 return font_has_character(This
, ch
, &ret
) == S_OK
&& ret
;
2081 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2083 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
2084 FIXME("(%p): stub\n", This
);
2085 return DWRITE_LOCALITY_LOCAL
;
2088 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2089 dwritefont_QueryInterface
,
2092 dwritefont_GetFontFamily
,
2093 dwritefont_GetWeight
,
2094 dwritefont_GetStretch
,
2095 dwritefont_GetStyle
,
2096 dwritefont_IsSymbolFont
,
2097 dwritefont_GetFaceNames
,
2098 dwritefont_GetInformationalStrings
,
2099 dwritefont_GetSimulations
,
2100 dwritefont_GetMetrics
,
2101 dwritefont_HasCharacter
,
2102 dwritefont_CreateFontFace
,
2103 dwritefont1_GetMetrics
,
2104 dwritefont1_GetPanose
,
2105 dwritefont1_GetUnicodeRanges
,
2106 dwritefont1_IsMonospacedFont
,
2107 dwritefont2_IsColorFont
,
2108 dwritefont3_CreateFontFace
,
2110 dwritefont3_GetFontFaceReference
,
2111 dwritefont3_HasCharacter
,
2112 dwritefont3_GetLocality
2115 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2119 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2120 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2123 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2127 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2128 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2131 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2135 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2137 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2138 IDWriteFontFaceReference1_iface
);
2141 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2143 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2144 *lf
= font
->data
->lf
;
2147 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2149 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2153 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2155 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2156 *fontsig
= font
->data
->fontsig
;
2160 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2162 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2163 *fontsig
= fontface
->fontsig
;
2167 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2169 struct dwrite_font
*This
;
2173 This
= heap_alloc(sizeof(*This
));
2175 return E_OUTOFMEMORY
;
2177 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2179 This
->family
= family
;
2180 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2181 This
->data
= family
->data
->fonts
[index
];
2182 This
->style
= This
->data
->style
;
2183 addref_font_data(This
->data
);
2185 *font
= &This
->IDWriteFont3_iface
;
2190 /* IDWriteFontList2 */
2191 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2193 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2195 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2196 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2197 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2198 IsEqualIID(riid
, &IID_IUnknown
))
2201 IDWriteFontList2_AddRef(iface
);
2205 WARN("%s not implemented.\n", debugstr_guid(riid
));
2208 return E_NOINTERFACE
;
2211 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2213 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2214 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2216 TRACE("%p, refcount %u.\n", iface
, refcount
);
2221 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2223 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2224 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2226 TRACE("%p, refcount %u.\n", iface
, refcount
);
2232 for (i
= 0; i
< fontlist
->font_count
; i
++)
2233 release_font_data(fontlist
->fonts
[i
]);
2234 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2235 heap_free(fontlist
->fonts
);
2236 heap_free(fontlist
);
2242 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2244 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2245 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2248 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2250 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2252 TRACE("%p.\n", iface
);
2254 return fontlist
->font_count
;
2257 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2259 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2261 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2265 if (fontlist
->font_count
== 0)
2268 if (index
>= fontlist
->font_count
)
2269 return E_INVALIDARG
;
2271 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2274 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2276 FIXME("%p, %u.\n", iface
, index
);
2278 return DWRITE_LOCALITY_LOCAL
;
2281 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2283 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2285 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2289 if (fontlist
->font_count
== 0)
2292 if (index
>= fontlist
->font_count
)
2295 return create_font(fontlist
->family
, index
, font
);
2298 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2299 IDWriteFontFaceReference
**reference
)
2304 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2308 hr
= IDWriteFontList2_GetFont(iface
, index
, &font
);
2312 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2313 IDWriteFont3_Release(font
);
2318 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2320 FIXME("%p, %p.\n", iface
, fontset
);
2325 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2327 dwritefontlist_QueryInterface
,
2328 dwritefontlist_AddRef
,
2329 dwritefontlist_Release
,
2330 dwritefontlist_GetFontCollection
,
2331 dwritefontlist_GetFontCount
,
2332 dwritefontlist_GetFont
,
2333 dwritefontlist1_GetFontLocality
,
2334 dwritefontlist1_GetFont
,
2335 dwritefontlist1_GetFontFaceReference
,
2336 dwritefontlist2_GetFontSet
,
2339 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2341 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2343 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2345 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2346 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2347 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2348 IsEqualIID(riid
, &IID_IUnknown
))
2352 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2353 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2354 IsEqualIID(riid
, &IID_IDWriteFontList
))
2356 *obj
= &family
->IDWriteFontList2_iface
;
2360 WARN("%s not implemented.\n", debugstr_guid(riid
));
2362 return E_NOINTERFACE
;
2365 IUnknown_AddRef((IUnknown
*)*obj
);
2369 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2371 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2372 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2374 TRACE("%p, %u.\n", iface
, refcount
);
2379 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2381 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2382 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2384 TRACE("%p, %u.\n", iface
, refcount
);
2388 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2389 release_fontfamily_data(family
->data
);
2396 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2398 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2400 TRACE("%p, %p.\n", iface
, collection
);
2402 *collection
= (IDWriteFontCollection
*)family
->collection
;
2403 IDWriteFontCollection_AddRef(*collection
);
2407 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2409 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2411 TRACE("%p.\n", iface
);
2413 return family
->data
->count
;
2416 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2418 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2420 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2424 if (!family
->data
->count
)
2427 if (index
>= family
->data
->count
)
2428 return E_INVALIDARG
;
2430 return create_font(family
, index
, (IDWriteFont3
**)font
);
2433 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2435 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2437 TRACE("%p, %p.\n", iface
, names
);
2439 return clone_localizedstrings(family
->data
->familyname
, names
);
2442 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2443 const struct dwrite_font_propvec
*req
)
2445 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2446 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2447 FLOAT cur_req_prod
, next_req_prod
;
2449 if (next_to_req
< cur_to_req
)
2452 if (next_to_req
> cur_to_req
)
2455 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2456 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2458 if (next_req_prod
> cur_req_prod
)
2461 if (next_req_prod
< cur_req_prod
)
2464 if (next
->stretch
> cur
->stretch
)
2466 if (next
->stretch
< cur
->stretch
)
2469 if (next
->style
> cur
->style
)
2471 if (next
->style
< cur
->style
)
2474 if (next
->weight
> cur
->weight
)
2476 if (next
->weight
< cur
->weight
)
2479 /* full match, no reason to prefer new variant */
2483 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2484 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2486 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2487 struct dwrite_font_propvec req
;
2490 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2492 if (!family
->data
->count
)
2495 return DWRITE_E_NOFONT
;
2498 init_font_prop_vec(weight
, stretch
, style
, &req
);
2501 for (i
= 1; i
< family
->data
->count
; ++i
)
2503 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2507 return create_font(family
, match
, (IDWriteFont3
**)font
);
2510 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2512 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2514 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2517 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2519 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2522 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2524 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2529 for (j
= 0; j
< b
; j
++) {
2530 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2531 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2532 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2533 fonts
->fonts
[j
+1] = s
;
2544 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2545 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2547 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2548 matching_filter_func func
= NULL
;
2549 struct dwrite_font_propvec req
;
2550 struct dwrite_fontlist
*fonts
;
2553 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2557 fonts
= heap_alloc(sizeof(*fonts
));
2559 return E_OUTOFMEMORY
;
2561 /* Allocate as many as family has, not all of them will be necessary used. */
2562 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2563 if (!fonts
->fonts
) {
2565 return E_OUTOFMEMORY
;
2568 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2569 fonts
->refcount
= 1;
2570 fonts
->family
= family
;
2571 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2572 fonts
->font_count
= 0;
2574 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2575 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2576 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2577 func
= is_font_acceptable_for_normal
;
2579 else /* requested oblique or italic */ {
2580 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2581 func
= is_font_acceptable_for_oblique_italic
;
2584 for (i
= 0; i
< family
->data
->count
; ++i
)
2586 if (!func
|| func(family
->data
->fonts
[i
]))
2588 fonts
->fonts
[fonts
->font_count
] = family
->data
->fonts
[i
];
2589 addref_font_data(family
->data
->fonts
[i
]);
2590 fonts
->font_count
++;
2594 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2595 init_font_prop_vec(weight
, stretch
, style
, &req
);
2596 matchingfonts_sort(fonts
, &req
);
2598 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2602 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2604 FIXME("%p, %u.\n", iface
, index
);
2606 return DWRITE_LOCALITY_LOCAL
;
2609 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2611 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2613 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2617 if (!family
->data
->count
)
2620 if (index
>= family
->data
->count
)
2623 return create_font(family
, index
, font
);
2626 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2627 IDWriteFontFaceReference
**reference
)
2629 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2630 const struct dwrite_font_data
*font
;
2632 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2636 if (index
>= family
->data
->count
)
2639 font
= family
->data
->fonts
[index
];
2640 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2641 font
->file
, font
->face_index
, font
->simulations
, reference
);
2644 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2645 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2647 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2652 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2654 FIXME("%p, %p.\n", iface
, fontset
);
2659 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2661 dwritefontfamily_QueryInterface
,
2662 dwritefontfamily_AddRef
,
2663 dwritefontfamily_Release
,
2664 dwritefontfamily_GetFontCollection
,
2665 dwritefontfamily_GetFontCount
,
2666 dwritefontfamily_GetFont
,
2667 dwritefontfamily_GetFamilyNames
,
2668 dwritefontfamily_GetFirstMatchingFont
,
2669 dwritefontfamily_GetMatchingFonts
,
2670 dwritefontfamily1_GetFontLocality
,
2671 dwritefontfamily1_GetFont
,
2672 dwritefontfamily1_GetFontFaceReference
,
2673 dwritefontfamily2_GetMatchingFonts
,
2674 dwritefontfamily2_GetFontSet
,
2677 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2679 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2680 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2683 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2685 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2686 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2689 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2691 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2692 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2695 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2696 IDWriteFontCollection
**collection
)
2698 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2699 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2702 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2704 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2705 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2708 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2710 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2711 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2714 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2716 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2717 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2720 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2722 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2723 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2726 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2727 IDWriteFontFaceReference
**reference
)
2729 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2730 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2733 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2735 FIXME("%p, %p.\n", iface
, fontset
);
2740 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2742 dwritefontfamilylist_QueryInterface
,
2743 dwritefontfamilylist_AddRef
,
2744 dwritefontfamilylist_Release
,
2745 dwritefontfamilylist_GetFontCollection
,
2746 dwritefontfamilylist_GetFontCount
,
2747 dwritefontfamilylist_GetFont
,
2748 dwritefontfamilylist1_GetFontLocality
,
2749 dwritefontfamilylist1_GetFont
,
2750 dwritefontfamilylist1_GetFontFaceReference
,
2751 dwritefontfamilylist2_GetFontSet
,
2754 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2755 struct dwrite_fontfamily
**family
)
2757 struct dwrite_fontfamily
*object
;
2761 object
= heap_alloc(sizeof(*object
));
2763 return E_OUTOFMEMORY
;
2765 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2766 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2767 object
->refcount
= 1;
2768 object
->collection
= collection
;
2769 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2770 object
->data
= collection
->family_data
[index
];
2771 InterlockedIncrement(&object
->data
->refcount
);
2778 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2781 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2784 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2786 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2788 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2790 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2791 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2792 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2793 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2794 IsEqualIID(riid
, &IID_IUnknown
))
2797 IDWriteFontCollection3_AddRef(iface
);
2803 if (IsEqualIID(riid
, &IID_issystemcollection
))
2806 WARN("%s not implemented.\n", debugstr_guid(riid
));
2808 return E_NOINTERFACE
;
2811 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2813 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2815 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2816 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2817 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2818 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2819 IsEqualIID(riid
, &IID_IUnknown
))
2822 IDWriteFontCollection3_AddRef(iface
);
2826 WARN("%s not implemented.\n", debugstr_guid(riid
));
2830 return E_NOINTERFACE
;
2833 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2835 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2836 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2838 TRACE("%p, refcount %d.\n", collection
, refcount
);
2843 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2845 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2846 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2849 TRACE("%p, refcount %d.\n", iface
, refcount
);
2853 factory_detach_fontcollection(collection
->factory
, iface
);
2854 for (i
= 0; i
< collection
->count
; ++i
)
2855 release_fontfamily_data(collection
->family_data
[i
]);
2856 heap_free(collection
->family_data
);
2857 heap_free(collection
);
2863 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2865 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2867 TRACE("%p.\n", iface
);
2869 return collection
->count
;
2872 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2873 IDWriteFontFamily
**ret
)
2875 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2876 struct dwrite_fontfamily
*family
;
2879 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2883 if (index
>= collection
->count
)
2886 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2887 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2892 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2896 for (i
= 0; i
< collection
->count
; ++i
)
2898 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2899 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2902 for (j
= 0; j
< count
; j
++) {
2904 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
2905 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2913 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
2914 UINT32
*index
, BOOL
*exists
)
2916 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2918 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
2920 *index
= collection_find_family(collection
, name
);
2921 *exists
= *index
!= ~0u;
2925 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
2928 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2929 struct dwrite_fontfamily
*family
;
2930 BOOL found_font
= FALSE
;
2931 IDWriteFontFile
*file
;
2932 UINT32 face_index
, count
;
2936 TRACE("%p, %p, %p.\n", iface
, face
, font
);
2941 return E_INVALIDARG
;
2944 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
2947 face_index
= IDWriteFontFace_GetIndex(face
);
2950 for (i
= 0; i
< collection
->count
; ++i
)
2952 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
2954 for (j
= 0; j
< family_data
->count
; ++j
)
2956 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2958 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2967 IDWriteFontFile_Release(file
);
2970 return DWRITE_E_NOFONT
;
2972 hr
= create_fontfamily(collection
, i
, &family
);
2976 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
2977 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
2981 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
2983 FIXME("%p, %p.\n", iface
, fontset
);
2988 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2989 IDWriteFontFamily1
**ret
)
2991 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2992 struct dwrite_fontfamily
*family
;
2995 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2999 if (index
>= collection
->count
)
3002 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3003 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3008 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3009 UINT32 index
, IDWriteFontFamily2
**family
)
3011 FIXME("%p, %u, %p.\n", iface
, index
, family
);
3016 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3017 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3018 IDWriteFontList2
**fontlist
)
3020 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3025 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3027 FIXME("%p.\n", iface
);
3029 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3032 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3034 FIXME("%p, %p.\n", iface
, fontset
);
3039 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3041 FIXME("%p.\n", iface
);
3046 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3048 dwritefontcollection_QueryInterface
,
3049 dwritefontcollection_AddRef
,
3050 dwritefontcollection_Release
,
3051 dwritefontcollection_GetFontFamilyCount
,
3052 dwritefontcollection_GetFontFamily
,
3053 dwritefontcollection_FindFamilyName
,
3054 dwritefontcollection_GetFontFromFontFace
,
3055 dwritefontcollection1_GetFontSet
,
3056 dwritefontcollection1_GetFontFamily
,
3057 dwritefontcollection2_GetFontFamily
,
3058 dwritefontcollection2_GetMatchingFonts
,
3059 dwritefontcollection2_GetFontFamilyModel
,
3060 dwritefontcollection2_GetFontSet
,
3061 dwritefontcollection3_GetExpirationEvent
,
3064 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3066 dwritesystemfontcollection_QueryInterface
,
3067 dwritefontcollection_AddRef
,
3068 dwritefontcollection_Release
,
3069 dwritefontcollection_GetFontFamilyCount
,
3070 dwritefontcollection_GetFontFamily
,
3071 dwritefontcollection_FindFamilyName
,
3072 dwritefontcollection_GetFontFromFontFace
,
3073 dwritefontcollection1_GetFontSet
,
3074 dwritefontcollection1_GetFontFamily
,
3075 dwritefontcollection2_GetFontFamily
,
3076 dwritefontcollection2_GetMatchingFonts
,
3077 dwritefontcollection2_GetFontFamilyModel
,
3078 dwritefontcollection2_GetFontSet
,
3079 dwritefontcollection3_GetExpirationEvent
,
3082 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3084 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3085 sizeof(*family_data
->fonts
)))
3087 return E_OUTOFMEMORY
;
3090 family_data
->fonts
[family_data
->count
++] = font_data
;
3091 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3092 family_data
->has_normal_face
= 1;
3093 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3094 family_data
->has_oblique_face
= 1;
3096 family_data
->has_italic_face
= 1;
3100 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3101 struct dwrite_fontfamily_data
*family
)
3103 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3104 sizeof(*collection
->family_data
)))
3106 return E_OUTOFMEMORY
;
3109 collection
->family_data
[collection
->count
++] = family
;
3113 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3115 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3116 collection
->refcount
= 1;
3117 collection
->count
= 0;
3118 collection
->size
= 0;
3119 collection
->family_data
= NULL
;
3124 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3126 IDWriteFontFileLoader
*loader
;
3133 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3137 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3141 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3142 IDWriteFontFileLoader_Release(loader
);
3149 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3151 BOOL exists
= FALSE
;
3156 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3157 if (FAILED(hr
) || !exists
)
3160 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3163 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3167 while (isspaceW(*in
))
3171 if (!(len
= strlenW(in
)))
3174 while (isspaceW(in
[len
-1]))
3177 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3186 INT len
; /* token length */
3187 INT fulllen
; /* full length including following separators */
3190 static inline BOOL
is_name_separator_char(WCHAR ch
)
3192 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3195 struct name_pattern
{
3196 const WCHAR
*part1
; /* NULL indicates end of list */
3197 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3200 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3202 const struct name_pattern
*pattern
;
3203 struct name_token
*token
;
3206 while ((pattern
= &patterns
[i
++])->part1
) {
3207 int len_part1
= strlenW(pattern
->part1
);
3208 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3210 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3211 if (len_part2
== 0) {
3212 /* simple case with single part pattern */
3213 if (token
->len
!= len_part1
)
3216 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3217 if (match
) *match
= *token
;
3218 list_remove(&token
->entry
);
3224 struct name_token
*next_token
;
3225 struct list
*next_entry
;
3227 /* pattern parts are stored in reading order, tokens list is reversed */
3228 if (token
->len
< len_part2
)
3231 /* it's possible to have combined string as a token, like ExtraCondensed */
3232 if (token
->len
== len_part1
+ len_part2
) {
3233 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3236 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3239 /* combined string match */
3240 if (match
) *match
= *token
;
3241 list_remove(&token
->entry
);
3246 /* now it's only possible to have two tokens matched to respective pattern parts */
3247 if (token
->len
!= len_part2
)
3250 next_entry
= list_next(tokens
, &token
->entry
);
3252 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3253 if (next_token
->len
!= len_part1
)
3256 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3259 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3262 /* both parts matched, remove tokens */
3264 match
->ptr
= next_token
->ptr
;
3265 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3267 list_remove(&token
->entry
);
3268 list_remove(&next_token
->entry
);
3269 heap_free(next_token
);
3284 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3286 static const WCHAR itaW
[] = {'i','t','a',0};
3287 static const WCHAR italW
[] = {'i','t','a','l',0};
3288 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3289 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3291 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3292 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3293 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3294 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3296 static const struct name_pattern italic_patterns
[] = {
3305 static const struct name_pattern oblique_patterns
[] = {
3314 /* italic patterns first */
3315 if (match_pattern_list(tokens
, italic_patterns
, match
))
3316 return DWRITE_FONT_STYLE_ITALIC
;
3318 /* oblique patterns */
3319 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3320 return DWRITE_FONT_STYLE_OBLIQUE
;
3325 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3326 struct name_token
*match
)
3328 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3329 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3330 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3331 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3332 static const WCHAR wideW
[] = {'w','i','d','e',0};
3333 static const WCHAR condW
[] = {'c','o','n','d',0};
3335 static const struct name_pattern ultracondensed_patterns
[] = {
3336 { extraW
, compressedW
},
3337 { extW
, compressedW
},
3338 { ultraW
, compressedW
},
3339 { ultraW
, condensedW
},
3344 static const struct name_pattern extracondensed_patterns
[] = {
3346 { extraW
, condensedW
},
3347 { extW
, condensedW
},
3353 static const struct name_pattern semicondensed_patterns
[] = {
3356 { semiW
, condensedW
},
3361 static const struct name_pattern semiexpanded_patterns
[] = {
3363 { semiW
, expandedW
},
3364 { semiW
, extendedW
},
3368 static const struct name_pattern extraexpanded_patterns
[] = {
3369 { extraW
, expandedW
},
3370 { extW
, expandedW
},
3371 { extraW
, extendedW
},
3372 { extW
, extendedW
},
3376 static const struct name_pattern ultraexpanded_patterns
[] = {
3377 { ultraW
, expandedW
},
3378 { ultraW
, extendedW
},
3382 static const struct name_pattern condensed_patterns
[] = {
3388 static const struct name_pattern expanded_patterns
[] = {
3394 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3395 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3397 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3398 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3400 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3401 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3403 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3404 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3406 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3407 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3409 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3410 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3412 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3413 return DWRITE_FONT_STRETCH_CONDENSED
;
3415 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3416 return DWRITE_FONT_STRETCH_EXPANDED
;
3421 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3422 struct name_token
*match
)
3424 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3425 static const WCHAR nordW
[] = {'n','o','r','d',0};
3427 static const struct name_pattern thin_patterns
[] = {
3434 static const struct name_pattern extralight_patterns
[] = {
3441 static const struct name_pattern semilight_patterns
[] = {
3446 static const struct name_pattern demibold_patterns
[] = {
3452 static const struct name_pattern extrabold_patterns
[] = {
3459 static const struct name_pattern extrablack_patterns
[] = {
3466 static const struct name_pattern bold_patterns
[] = {
3471 static const struct name_pattern thin2_patterns
[] = {
3476 static const struct name_pattern light_patterns
[] = {
3481 static const struct name_pattern medium_patterns
[] = {
3486 static const struct name_pattern black_patterns
[] = {
3493 static const struct name_pattern demibold2_patterns
[] = {
3498 static const struct name_pattern extrabold2_patterns
[] = {
3503 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3504 matching pattern. */
3506 if (match_pattern_list(tokens
, thin_patterns
, match
))
3507 return DWRITE_FONT_WEIGHT_THIN
;
3509 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3510 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3512 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3513 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3515 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3516 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3518 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3519 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3521 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3522 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3524 if (match_pattern_list(tokens
, bold_patterns
, match
))
3525 return DWRITE_FONT_WEIGHT_BOLD
;
3527 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3528 return DWRITE_FONT_WEIGHT_THIN
;
3530 if (match_pattern_list(tokens
, light_patterns
, match
))
3531 return DWRITE_FONT_WEIGHT_LIGHT
;
3533 if (match_pattern_list(tokens
, medium_patterns
, match
))
3534 return DWRITE_FONT_WEIGHT_MEDIUM
;
3536 if (match_pattern_list(tokens
, black_patterns
, match
))
3537 return DWRITE_FONT_WEIGHT_BLACK
;
3539 if (match_pattern_list(tokens
, black_patterns
, match
))
3540 return DWRITE_FONT_WEIGHT_BLACK
;
3542 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3543 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3545 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3546 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3548 /* FIXME: use abbreviated names to extract weight */
3553 struct knownweight_entry
{
3555 DWRITE_FONT_WEIGHT weight
;
3558 static int compare_knownweights(const void *a
, const void* b
)
3560 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3561 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3564 if (target
> entry
->weight
)
3566 else if (target
< entry
->weight
)
3572 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3574 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3575 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3576 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3577 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3578 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3579 const struct knownweight_entry
*ptr
;
3581 static const struct knownweight_entry knownweights
[] = {
3582 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3583 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3584 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3585 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3586 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3587 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3588 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3589 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3590 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3591 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3594 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3595 compare_knownweights
);
3601 strcpyW(nameW
, ptr
->nameW
);
3605 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3607 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3608 strW
[name
->len
] = 0;
3611 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3612 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3614 static const WCHAR bookW
[] = {'B','o','o','k',0};
3615 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3616 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3617 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3618 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3620 static const WCHAR
*regular_patterns
[] = {
3629 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3633 len
= strlenW(facenameW
);
3635 /* remove rightmost regular variant from face name */
3636 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3637 int pattern_len
= strlenW(ptr
);
3640 if (pattern_len
> len
)
3643 src
= facenameW
+ len
- pattern_len
;
3644 while (src
>= facenameW
) {
3645 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3646 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3647 len
= strlenW(facenameW
);
3659 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3667 struct name_token
*token
= heap_alloc(sizeof(*token
));
3672 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3678 /* skip separators */
3679 while (is_name_separator_char(*ptr
)) {
3684 list_add_head(tokens
, &token
->entry
);
3688 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3690 struct name_token
*token
, *token2
;
3691 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3694 list_remove(&token
->entry
);
3696 /* don't include last separator */
3697 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3698 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3706 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3708 struct name_token stretch_name
, weight_name
, style_name
;
3709 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3710 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3711 const WCHAR
*regular_ptr
= NULL
;
3712 DWRITE_FONT_STRETCH stretch
;
3713 DWRITE_FONT_WEIGHT weight
;
3717 /* remove leading and trailing spaces from family and face name */
3718 trim_spaces(familyW
, familynameW
);
3719 len
= trim_spaces(faceW
, facenameW
);
3721 /* remove rightmost regular variant from face name */
3722 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3724 /* append face name to family name, FIXME check if face name is a substring of family name */
3726 strcatW(familynameW
, spaceW
);
3727 strcatW(familynameW
, facenameW
);
3730 /* tokenize with " .-_" */
3731 fontname_tokenize(&tokens
, familynameW
);
3733 /* extract and resolve style */
3734 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3736 /* extract stretch */
3737 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3739 /* extract weight */
3740 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3742 /* resolve weight */
3743 if (weight
!= font
->weight
) {
3744 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3745 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3746 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3747 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3748 !(abs(weight
- font
->weight
) <= 150 &&
3749 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3750 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3751 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3753 font
->weight
= weight
;
3757 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3758 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3759 stretch itself is normal (extracted stretch is never normal). */
3760 if (stretch
!= font
->stretch
) {
3761 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3762 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3763 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3765 font
->stretch
= stretch
;
3769 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3771 /* get final combined string from what's left in token list, list is released */
3772 fontname_tokens_to_str(&tokens
, finalW
);
3774 if (!strcmpW(familyW
, finalW
))
3777 /* construct face name */
3778 strcpyW(familyW
, finalW
);
3780 /* resolved weight name */
3781 if (weight_name
.ptr
)
3782 font_name_token_to_str(&weight_name
, weightW
);
3783 /* ignore normal weight */
3784 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3786 /* for known weight values use appropriate names */
3787 else if (is_known_weight_value(font
->weight
, weightW
)) {
3789 /* use Wnnn format as a fallback in case weight is not one of known values */
3791 static const WCHAR fmtW
[] = {'W','%','d',0};
3792 sprintfW(weightW
, fmtW
, font
->weight
);
3795 /* resolved stretch name */
3796 if (stretch_name
.ptr
)
3797 font_name_token_to_str(&stretch_name
, stretchW
);
3798 /* ignore normal stretch */
3799 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3801 /* use predefined stretch names */
3803 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3804 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3805 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3806 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3807 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3808 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3810 static const WCHAR
*stretchnamesW
[] = {
3811 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3816 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3822 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3825 /* resolved style name */
3827 font_name_token_to_str(&style_name
, styleW
);
3828 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3830 /* use predefined names */
3832 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3833 strcpyW(styleW
, italicW
);
3835 strcpyW(styleW
, obliqueW
);
3838 /* use Regular match if it was found initially */
3839 if (!*weightW
&& !*stretchW
&& !*styleW
)
3840 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3844 strcpyW(faceW
, stretchW
);
3847 strcatW(faceW
, spaceW
);
3848 strcatW(faceW
, weightW
);
3852 strcatW(faceW
, spaceW
);
3853 strcatW(faceW
, styleW
);
3857 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3861 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3863 static const float width_axis_values
[] =
3865 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3866 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
3867 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
3868 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
3869 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
3870 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
3871 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
3872 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
3873 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
3874 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
3877 struct file_stream_desc stream_desc
;
3878 struct dwrite_font_props props
;
3879 struct dwrite_font_data
*data
;
3880 WCHAR familyW
[255], faceW
[255];
3885 data
= heap_alloc_zero(sizeof(*data
));
3887 return E_OUTOFMEMORY
;
3890 data
->file
= desc
->files
[0];
3891 data
->face_index
= desc
->index
;
3892 data
->face_type
= desc
->face_type
;
3893 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3894 data
->bold_sim_tested
= 0;
3895 data
->oblique_sim_tested
= 0;
3896 IDWriteFontFile_AddRef(data
->file
);
3898 stream_desc
.stream
= desc
->stream
;
3899 stream_desc
.face_type
= desc
->face_type
;
3900 stream_desc
.face_index
= desc
->index
;
3901 opentype_get_font_properties(&stream_desc
, &props
);
3902 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3903 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3905 /* get family name from font file */
3906 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
3908 WARN("unable to get family name from font\n");
3909 release_font_data(data
);
3913 data
->style
= props
.style
;
3914 data
->stretch
= props
.stretch
;
3915 data
->weight
= props
.weight
;
3916 data
->panose
= props
.panose
;
3917 data
->fontsig
= props
.fontsig
;
3918 data
->lf
= props
.lf
;
3919 data
->flags
= props
.flags
;
3921 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
3922 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
3923 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3924 set_en_localizedstring(data
->family_names
, familyW
);
3925 set_en_localizedstring(data
->names
, faceW
);
3928 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3930 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
3931 data
->axis
[0].value
= props
.weight
;
3932 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
3933 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
3934 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
3935 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
3941 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3942 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3944 struct dwrite_font_data
*data
;
3948 data
= heap_alloc_zero(sizeof(*data
));
3950 return E_OUTOFMEMORY
;
3954 data
->simulations
|= sim
;
3955 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3956 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3957 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3958 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3959 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3961 IDWriteFontFile_AddRef(data
->file
);
3962 IDWriteLocalizedStrings_AddRef(data
->family_names
);
3964 create_localizedstrings(&data
->names
);
3965 add_localizedstring(data
->names
, enusW
, facenameW
);
3967 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3973 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3975 struct dwrite_fontfamily_data
*data
;
3977 data
= heap_alloc_zero(sizeof(*data
));
3979 return E_OUTOFMEMORY
;
3982 data
->familyname
= familyname
;
3983 IDWriteLocalizedStrings_AddRef(familyname
);
3990 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3992 size_t i
, j
, heaviest
;
3994 for (i
= 0; i
< family
->count
; ++i
)
3996 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3999 if (family
->fonts
[i
]->bold_sim_tested
)
4002 family
->fonts
[i
]->bold_sim_tested
= 1;
4003 for (j
= i
; j
< family
->count
; ++j
)
4005 if (family
->fonts
[j
]->bold_sim_tested
)
4008 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4009 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4010 if (family
->fonts
[j
]->weight
> weight
) {
4011 weight
= family
->fonts
[j
]->weight
;
4014 family
->fonts
[j
]->bold_sim_tested
= 1;
4018 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4019 static const struct name_pattern weightsim_patterns
[] = {
4034 WCHAR facenameW
[255], initialW
[255];
4035 struct dwrite_font_data
*boldface
;
4038 /* add Bold simulation based on heaviest face data */
4040 /* Simulated face name should only contain Bold as weight term,
4041 so remove existing regular and weight terms. */
4042 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4043 facename_remove_regular_term(initialW
, -1);
4045 /* remove current weight pattern */
4046 fontname_tokenize(&tokens
, initialW
);
4047 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4048 fontname_tokens_to_str(&tokens
, facenameW
);
4050 /* Bold suffix for new name */
4052 strcatW(facenameW
, spaceW
);
4053 strcatW(facenameW
, boldW
);
4055 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4056 boldface
->bold_sim_tested
= 1;
4057 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4058 fontfamily_add_font(family
, boldface
);
4064 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4068 for (i
= 0; i
< family
->count
; ++i
)
4070 UINT32 regular
= ~0u, oblique
= ~0u;
4071 struct dwrite_font_data
*obliqueface
;
4072 WCHAR facenameW
[255];
4074 if (family
->fonts
[i
]->oblique_sim_tested
)
4077 family
->fonts
[i
]->oblique_sim_tested
= 1;
4078 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4080 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4083 /* find regular style with same weight/stretch values */
4084 for (j
= i
; j
< family
->count
; ++j
)
4086 if (family
->fonts
[j
]->oblique_sim_tested
)
4089 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4090 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4092 family
->fonts
[j
]->oblique_sim_tested
= 1;
4093 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4096 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4100 if (regular
!= ~0u && oblique
!= ~0u)
4104 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4108 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4112 /* add oblique simulation based on this regular face */
4114 /* remove regular term if any, append 'Oblique' */
4115 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4116 facename_remove_regular_term(facenameW
, -1);
4119 strcatW(facenameW
, spaceW
);
4120 strcatW(facenameW
, obliqueW
);
4122 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4123 obliqueface
->oblique_sim_tested
= 1;
4124 obliqueface
->lf
.lfItalic
= 1;
4125 fontfamily_add_font(family
, obliqueface
);
4130 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4131 const WCHAR
*replacement_name
)
4133 UINT32 i
= collection_find_family(collection
, replacement_name
);
4134 struct dwrite_fontfamily_data
*target
;
4135 IDWriteLocalizedStrings
*strings
;
4138 /* replacement does not exist */
4142 hr
= create_localizedstrings(&strings
);
4146 /* add a new family with target name, reuse font data from replacement */
4147 add_localizedstring(strings
, enusW
, target_name
);
4148 hr
= init_fontfamily_data(strings
, &target
);
4150 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4153 for (i
= 0; i
< replacement
->count
; ++i
)
4155 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4156 addref_font_data(replacement
->fonts
[i
]);
4159 fontcollection_add_family(collection
, target
);
4160 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4161 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4163 IDWriteLocalizedStrings_Release(strings
);
4167 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4168 system font collections. */
4169 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4171 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4176 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4179 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4184 max_namelen
++; /* returned value doesn't include room for '\0' */
4185 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4186 data
= heap_alloc(max_datalen
);
4188 datalen
= max_datalen
;
4189 namelen
= max_namelen
;
4190 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4191 if (collection_find_family(collection
, name
) == ~0u) {
4192 if (type
== REG_MULTI_SZ
) {
4193 WCHAR
*replacement
= data
;
4194 while (*replacement
) {
4195 if (fontcollection_add_replacement(collection
, name
, replacement
))
4197 replacement
+= strlenW(replacement
) + 1;
4200 else if (type
== REG_SZ
)
4201 fontcollection_add_replacement(collection
, name
, data
);
4204 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4206 datalen
= max_datalen
;
4207 namelen
= max_namelen
;
4215 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4216 IDWriteFontCollection3
**ret
)
4218 struct fontfile_enum
{
4220 IDWriteFontFile
*file
;
4222 struct fontfile_enum
*fileenum
, *fileenum2
;
4223 struct dwrite_fontcollection
*collection
;
4224 struct list scannedfiles
;
4225 BOOL current
= FALSE
;
4231 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4232 if (!collection
) return E_OUTOFMEMORY
;
4234 hr
= init_font_collection(collection
, is_system
);
4236 heap_free(collection
);
4240 *ret
= &collection
->IDWriteFontCollection3_iface
;
4242 TRACE("building font collection:\n");
4244 list_init(&scannedfiles
);
4245 while (hr
== S_OK
) {
4246 DWRITE_FONT_FACE_TYPE face_type
;
4247 DWRITE_FONT_FILE_TYPE file_type
;
4248 BOOL supported
, same
= FALSE
;
4249 IDWriteFontFileStream
*stream
;
4250 IDWriteFontFile
*file
;
4254 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4255 if (FAILED(hr
) || !current
)
4258 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4262 /* check if we've scanned this file already */
4263 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4264 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4269 IDWriteFontFile_Release(file
);
4273 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4274 IDWriteFontFile_Release(file
);
4278 /* Unsupported formats are skipped. */
4279 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4280 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4281 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4282 IDWriteFontFileStream_Release(stream
);
4283 IDWriteFontFile_Release(file
);
4288 /* add to scanned list */
4289 fileenum
= heap_alloc(sizeof(*fileenum
));
4290 fileenum
->file
= file
;
4291 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4293 for (i
= 0; i
< face_count
; ++i
)
4295 struct dwrite_font_data
*font_data
;
4296 struct fontface_desc desc
;
4300 desc
.factory
= factory
;
4301 desc
.face_type
= face_type
;
4303 desc
.stream
= stream
;
4304 desc
.files_number
= 1;
4306 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4307 desc
.font_data
= NULL
;
4309 /* Allocate an initialize new font data structure. */
4310 hr
= init_font_data(&desc
, &font_data
);
4313 /* move to next one */
4318 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4320 /* ignore dot named faces */
4321 if (familyW
[0] == '.')
4323 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4324 release_font_data(font_data
);
4328 index
= collection_find_family(collection
, familyW
);
4330 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4332 struct dwrite_fontfamily_data
*family_data
;
4334 /* create and init new family */
4335 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4337 /* add font to family, family - to collection */
4338 hr
= fontfamily_add_font(family_data
, font_data
);
4340 hr
= fontcollection_add_family(collection
, family_data
);
4343 release_fontfamily_data(family_data
);
4351 IDWriteFontFileStream_Release(stream
);
4354 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4355 IDWriteFontFile_Release(fileenum
->file
);
4356 list_remove(&fileenum
->entry
);
4357 heap_free(fileenum
);
4360 for (i
= 0; i
< collection
->count
; ++i
)
4362 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4363 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4367 fontcollection_add_replacements(collection
);
4369 collection
->factory
= factory
;
4370 IDWriteFactory7_AddRef(factory
);
4375 struct system_fontfile_enumerator
4377 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4380 IDWriteFactory7
*factory
;
4385 DWORD filename_size
;
4388 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4390 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4393 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4395 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4396 IDWriteFontFileEnumerator_AddRef(iface
);
4401 WARN("%s not implemented.\n", debugstr_guid(riid
));
4405 return E_NOINTERFACE
;
4408 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4410 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4411 return InterlockedIncrement(&enumerator
->ref
);
4414 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4416 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4417 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
4421 IDWriteFactory7_Release(enumerator
->factory
);
4422 RegCloseKey(enumerator
->hkey
);
4423 heap_free(enumerator
->filename
);
4424 heap_free(enumerator
);
4430 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4434 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4435 if (!strchrW(filename
, '\\')) {
4436 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4437 WCHAR fullpathW
[MAX_PATH
];
4439 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4440 strcatW(fullpathW
, fontsW
);
4441 strcatW(fullpathW
, filename
);
4443 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4446 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4451 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4453 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4457 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4460 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4463 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4465 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4466 WCHAR name_buf
[256], *name
= name_buf
;
4467 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4472 enumerator
->index
++;
4474 /* iterate until we find next string value */
4477 name_count
= max_name_count
;
4478 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4480 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4481 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4482 if (r
== ERROR_MORE_DATA
) {
4483 if (name_count
>= max_name_count
) {
4484 if (name
!= name_buf
) heap_free(name
);
4485 max_name_count
*= 2;
4486 name
= heap_alloc(max_name_count
* sizeof(*name
));
4487 if (!name
) return E_OUTOFMEMORY
;
4489 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4490 heap_free(enumerator
->filename
);
4491 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4492 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4493 if (!enumerator
->filename
) {
4499 } while (r
== ERROR_MORE_DATA
);
4501 if (r
!= ERROR_SUCCESS
) {
4502 enumerator
->filename
[0] = 0;
4505 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4506 if (type
== REG_SZ
&& *name
!= '@') {
4510 enumerator
->index
++;
4512 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4515 if (name
!= name_buf
) heap_free(name
);
4519 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4521 systemfontfileenumerator_QueryInterface
,
4522 systemfontfileenumerator_AddRef
,
4523 systemfontfileenumerator_Release
,
4524 systemfontfileenumerator_MoveNext
,
4525 systemfontfileenumerator_GetCurrentFontFile
4528 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4530 struct system_fontfile_enumerator
*enumerator
;
4531 static const WCHAR fontslistW
[] = {
4532 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4533 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4534 'F','o','n','t','s',0
4539 enumerator
= heap_alloc(sizeof(*enumerator
));
4541 return E_OUTOFMEMORY
;
4543 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4544 enumerator
->ref
= 1;
4545 enumerator
->factory
= factory
;
4546 enumerator
->index
= -1;
4547 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4548 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4549 if (!enumerator
->filename
) {
4550 heap_free(enumerator
);
4551 return E_OUTOFMEMORY
;
4554 IDWriteFactory7_AddRef(factory
);
4556 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4558 ERR("failed to open fonts list key\n");
4559 IDWriteFactory7_Release(factory
);
4560 heap_free(enumerator
->filename
);
4561 heap_free(enumerator
);
4565 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4570 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4572 IDWriteFontFileEnumerator
*enumerator
;
4577 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4581 TRACE("building system font collection for factory %p\n", factory
);
4582 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4583 IDWriteFontFileEnumerator_Release(enumerator
);
4587 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4588 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4590 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};
4591 static const WCHAR emptyW
[] = {0};
4592 struct dwrite_fontfamily_data
*family_data
;
4593 IDWriteLocalizedStrings
*names
;
4594 DWRITE_FONT_FACE_TYPE face_type
;
4595 DWRITE_FONT_FILE_TYPE file_type
;
4596 IDWriteFontFileStream
*stream
;
4597 IDWriteFontFile
*file
;
4598 UINT32 face_count
, i
;
4602 /* create font file from this path */
4603 hr
= create_local_file_reference(factory
, pathW
, &file
);
4607 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4608 IDWriteFontFile_Release(file
);
4612 /* Unsupported formats are skipped. */
4613 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4614 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4615 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4616 IDWriteFontFileStream_Release(stream
);
4617 IDWriteFontFile_Release(file
);
4621 /* create and init new family */
4623 /* Family names are added for non-specific locale, represented with empty string.
4624 Default family appears with empty family name. */
4625 create_localizedstrings(&names
);
4626 if (!strcmpiW(keynameW
, defaultfontW
))
4627 add_localizedstring(names
, emptyW
, emptyW
);
4629 add_localizedstring(names
, emptyW
, keynameW
);
4631 hr
= init_fontfamily_data(names
, &family_data
);
4632 IDWriteLocalizedStrings_Release(names
);
4634 IDWriteFontFile_Release(file
);
4638 /* fill with faces */
4639 for (i
= 0; i
< face_count
; i
++) {
4640 struct dwrite_font_data
*font_data
;
4641 struct fontface_desc desc
;
4643 /* alloc and init new font data structure */
4644 desc
.factory
= factory
;
4645 desc
.face_type
= face_type
;
4648 desc
.stream
= stream
;
4649 desc
.files_number
= 1;
4650 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4651 desc
.font_data
= NULL
;
4653 hr
= init_font_data(&desc
, &font_data
);
4657 /* add font to family */
4658 hr
= fontfamily_add_font(family_data
, font_data
);
4660 release_font_data(font_data
);
4663 /* add family to collection */
4664 hr
= fontcollection_add_family(collection
, family_data
);
4666 release_fontfamily_data(family_data
);
4667 IDWriteFontFileStream_Release(stream
);
4668 IDWriteFontFile_Release(file
);
4673 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4675 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4676 struct dwrite_fontcollection
*collection
;
4677 static const WCHAR emptyW
[] = {0};
4678 WCHAR eudckeypathW
[16];
4686 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4690 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4691 if (!collection
) return E_OUTOFMEMORY
;
4693 hr
= init_font_collection(collection
, FALSE
);
4695 heap_free(collection
);
4699 *ret
= &collection
->IDWriteFontCollection3_iface
;
4700 collection
->factory
= factory
;
4701 IDWriteFactory7_AddRef(factory
);
4703 /* return empty collection if EUDC fonts are not configured */
4704 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4705 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4708 retval
= ERROR_SUCCESS
;
4710 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4711 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4712 DWORD type
, path_len
, name_len
;
4714 path_len
= ARRAY_SIZE(pathW
);
4715 name_len
= ARRAY_SIZE(keynameW
);
4716 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4717 if (retval
|| type
!= REG_SZ
)
4720 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4722 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4724 RegCloseKey(eudckey
);
4726 /* try to add global default if not defined for specific codepage */
4728 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4730 if (FAILED(hr
) || !exists
) {
4731 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4732 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4734 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4737 /* EUDC collection offers simulated faces too */
4738 for (i
= 0; i
< collection
->count
; ++i
)
4740 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4741 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4747 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4749 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4751 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4753 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4756 IDWriteFontFile_AddRef(iface
);
4760 WARN("%s not implemented.\n", debugstr_guid(riid
));
4763 return E_NOINTERFACE
;
4766 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4768 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4769 ULONG ref
= InterlockedIncrement(&This
->ref
);
4770 TRACE("(%p)->(%d)\n", This
, ref
);
4774 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4776 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4777 ULONG ref
= InterlockedDecrement(&This
->ref
);
4779 TRACE("(%p)->(%d)\n", This
, ref
);
4783 IDWriteFontFileLoader_Release(This
->loader
);
4784 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4785 heap_free(This
->reference_key
);
4792 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4794 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4795 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4796 *fontFileReferenceKey
= This
->reference_key
;
4797 *fontFileReferenceKeySize
= This
->key_size
;
4802 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4804 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4805 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4806 *fontFileLoader
= This
->loader
;
4807 IDWriteFontFileLoader_AddRef(This
->loader
);
4812 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4813 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4815 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4816 IDWriteFontFileStream
*stream
;
4819 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, is_supported
, file_type
, face_type
, face_count
);
4821 *is_supported
= FALSE
;
4822 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4824 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4827 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4831 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4833 /* TODO: Further Analysis */
4834 IDWriteFontFileStream_Release(stream
);
4838 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4839 dwritefontfile_QueryInterface
,
4840 dwritefontfile_AddRef
,
4841 dwritefontfile_Release
,
4842 dwritefontfile_GetReferenceKey
,
4843 dwritefontfile_GetLoader
,
4844 dwritefontfile_Analyze
,
4847 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4848 IDWriteFontFile
**ret
)
4850 struct dwrite_fontfile
*file
;
4855 file
= heap_alloc(sizeof(*file
));
4856 key
= heap_alloc(key_size
);
4857 if (!file
|| !key
) {
4860 return E_OUTOFMEMORY
;
4863 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4865 IDWriteFontFileLoader_AddRef(loader
);
4866 file
->loader
= loader
;
4867 file
->stream
= NULL
;
4868 file
->reference_key
= key
;
4869 memcpy(file
->reference_key
, reference_key
, key_size
);
4870 file
->key_size
= key_size
;
4872 *ret
= &file
->IDWriteFontFile_iface
;
4877 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
4879 struct file_stream_desc stream_desc
;
4880 struct dwrite_font_data
*font_data
;
4881 struct dwrite_fontface
*fontface
;
4887 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4889 return E_OUTOFMEMORY
;
4891 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4892 if (!fontface
->files
) {
4893 heap_free(fontface
);
4894 return E_OUTOFMEMORY
;
4897 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
4898 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
4899 fontface
->refcount
= 1;
4900 fontface
->type
= desc
->face_type
;
4901 fontface
->file_count
= desc
->files_number
;
4902 fontface
->cmap
.exists
= TRUE
;
4903 fontface
->vdmx
.exists
= TRUE
;
4904 fontface
->gasp
.exists
= TRUE
;
4905 fontface
->cpal
.exists
= TRUE
;
4906 fontface
->colr
.exists
= TRUE
;
4907 fontface
->index
= desc
->index
;
4908 fontface
->simulations
= desc
->simulations
;
4909 fontface
->factory
= desc
->factory
;
4910 IDWriteFactory7_AddRef(fontface
->factory
);
4912 for (i
= 0; i
< fontface
->file_count
; i
++) {
4913 fontface
->files
[i
] = desc
->files
[i
];
4914 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4916 fontface
->stream
= desc
->stream
;
4917 IDWriteFontFileStream_AddRef(fontface
->stream
);
4919 stream_desc
.stream
= fontface
->stream
;
4920 stream_desc
.face_type
= desc
->face_type
;
4921 stream_desc
.face_index
= desc
->index
;
4922 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4923 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
4924 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4925 /* TODO: test what happens if caret is already slanted */
4926 if (fontface
->caret
.slopeRise
== 1) {
4927 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4928 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4932 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace5_iface
);
4933 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace5_iface
))
4934 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4935 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace5_iface
))
4936 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4937 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
4939 /* Font properties are reused from font object when 'normal' face creation path is used:
4940 collection -> family -> matching font -> fontface.
4942 If face is created directly from factory we have to go through properties resolution.
4944 if (desc
->font_data
)
4946 font_data
= desc
->font_data
;
4947 addref_font_data(font_data
);
4951 hr
= init_font_data(desc
, &font_data
);
4954 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
4959 fontface
->weight
= font_data
->weight
;
4960 fontface
->style
= font_data
->style
;
4961 fontface
->stretch
= font_data
->stretch
;
4962 fontface
->panose
= font_data
->panose
;
4963 fontface
->fontsig
= font_data
->fontsig
;
4964 fontface
->lf
= font_data
->lf
;
4965 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
4966 fontface
->names
= font_data
->names
;
4967 if (fontface
->names
)
4968 IDWriteLocalizedStrings_AddRef(fontface
->names
);
4969 fontface
->family_names
= font_data
->family_names
;
4970 if (fontface
->family_names
)
4971 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
4972 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
4973 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
4975 if (fontface
->info_strings
[i
])
4976 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
4978 release_font_data(font_data
);
4980 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
4982 *ret
= &fontface
->IDWriteFontFace5_iface
;
4987 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4994 struct local_cached_stream
4997 IDWriteFontFileStream
*stream
;
4998 struct local_refkey
*key
;
5002 struct dwrite_localfontfilestream
5004 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5007 struct local_cached_stream
*entry
;
5008 const void *file_ptr
;
5012 struct dwrite_localfontfileloader
{
5013 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5016 struct list streams
;
5017 CRITICAL_SECTION cs
;
5020 static struct dwrite_localfontfileloader local_fontfile_loader
;
5022 struct dwrite_inmemory_stream_data
5030 struct dwrite_inmemory_filestream
5032 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5035 struct dwrite_inmemory_stream_data
*data
;
5038 struct dwrite_inmemory_fileloader
5040 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5043 struct dwrite_inmemory_stream_data
**streams
;
5048 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5050 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5053 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5055 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5058 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5060 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5063 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5065 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5068 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5070 if (InterlockedDecrement(&stream
->ref
) == 0) {
5072 IUnknown_Release(stream
->owner
);
5074 heap_free(stream
->data
);
5079 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5081 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5083 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5085 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5086 IsEqualIID(riid
, &IID_IUnknown
))
5089 if (InterlockedIncrement(&This
->ref
) == 1) {
5090 InterlockedDecrement(&This
->ref
);
5097 WARN("%s not implemented.\n", debugstr_guid(riid
));
5100 return E_NOINTERFACE
;
5103 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5105 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5106 ULONG ref
= InterlockedIncrement(&This
->ref
);
5107 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
5111 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5113 list_remove(&stream
->entry
);
5114 heap_free(stream
->key
);
5118 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5120 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5121 ULONG ref
= InterlockedDecrement(&This
->ref
);
5123 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
5126 UnmapViewOfFile(This
->file_ptr
);
5128 EnterCriticalSection(&local_fontfile_loader
.cs
);
5129 release_cached_stream(This
->entry
);
5130 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5138 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5139 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5141 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5143 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
5144 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5146 *fragment_context
= NULL
;
5148 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
5149 *fragment_start
= NULL
;
5153 *fragment_start
= (char*)This
->file_ptr
+ offset
;
5157 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5159 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5160 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
5163 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5165 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5166 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
5171 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5173 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
5176 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
5178 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
5179 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
5180 *last_writetime
= li
.QuadPart
;
5185 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5187 localfontfilestream_QueryInterface
,
5188 localfontfilestream_AddRef
,
5189 localfontfilestream_Release
,
5190 localfontfilestream_ReadFileFragment
,
5191 localfontfilestream_ReleaseFileFragment
,
5192 localfontfilestream_GetFileSize
,
5193 localfontfilestream_GetLastWriteTime
5196 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
5198 struct dwrite_localfontfilestream
*This
;
5202 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
5204 return E_OUTOFMEMORY
;
5206 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5209 This
->file_ptr
= file_ptr
;
5211 This
->entry
= entry
;
5213 *ret
= &This
->IDWriteFontFileStream_iface
;
5217 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5219 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5221 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5223 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5224 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5225 IsEqualIID(riid
, &IID_IUnknown
))
5228 IDWriteLocalFontFileLoader_AddRef(iface
);
5232 WARN("%s not implemented.\n", debugstr_guid(riid
));
5235 return E_NOINTERFACE
;
5238 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5240 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5241 ULONG ref
= InterlockedIncrement(&This
->ref
);
5242 TRACE("(%p)->(%d)\n", This
, ref
);
5246 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5248 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5249 ULONG ref
= InterlockedDecrement(&This
->ref
);
5251 TRACE("(%p)->(%d)\n", This
, ref
);
5256 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5258 const struct local_refkey
*refkey
= key
;
5259 struct local_cached_stream
*stream
;
5260 IDWriteFontFileStream
*filestream
;
5261 HANDLE file
, mapping
;
5268 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5269 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5270 if (file
== INVALID_HANDLE_VALUE
) {
5271 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5275 GetFileSizeEx(file
, &size
);
5276 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5281 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5282 CloseHandle(mapping
);
5284 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5288 stream
= heap_alloc(sizeof(*stream
));
5290 UnmapViewOfFile(file_ptr
);
5291 return E_OUTOFMEMORY
;
5294 stream
->key
= heap_alloc(key_size
);
5296 UnmapViewOfFile(file_ptr
);
5298 return E_OUTOFMEMORY
;
5301 stream
->key_size
= key_size
;
5302 memcpy(stream
->key
, key
, key_size
);
5304 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5306 UnmapViewOfFile(file_ptr
);
5307 heap_free(stream
->key
);
5312 stream
->stream
= filestream
;
5319 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5320 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5322 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5323 const struct local_refkey
*refkey
= key
;
5324 struct local_cached_stream
*stream
;
5327 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, ret
);
5328 TRACE("name: %s\n", debugstr_w(refkey
->name
));
5330 EnterCriticalSection(&This
->cs
);
5334 /* search cache first */
5335 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
5336 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5337 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5342 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
) {
5343 list_add_head(&This
->streams
, &stream
->entry
);
5344 *ret
= stream
->stream
;
5347 LeaveCriticalSection(&This
->cs
);
5352 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
5354 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5355 const struct local_refkey
*refkey
= key
;
5357 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
5359 *length
= strlenW(refkey
->name
);
5363 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5365 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5366 const struct local_refkey
*refkey
= key
;
5368 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
5370 if (length
< strlenW(refkey
->name
))
5371 return E_INVALIDARG
;
5373 strcpyW(path
, refkey
->name
);
5377 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5378 UINT32 key_size
, FILETIME
*writetime
)
5380 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5381 const struct local_refkey
*refkey
= key
;
5383 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, writetime
);
5385 *writetime
= refkey
->writetime
;
5389 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
5390 localfontfileloader_QueryInterface
,
5391 localfontfileloader_AddRef
,
5392 localfontfileloader_Release
,
5393 localfontfileloader_CreateStreamFromKey
,
5394 localfontfileloader_GetFilePathLengthFromKey
,
5395 localfontfileloader_GetFilePathFromKey
,
5396 localfontfileloader_GetLastWriteTimeFromKey
5399 void init_local_fontfile_loader(void)
5401 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5402 local_fontfile_loader
.ref
= 1;
5403 list_init(&local_fontfile_loader
.streams
);
5404 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5405 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5408 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5410 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5413 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5415 struct local_refkey
*refkey
;
5418 return E_INVALIDARG
;
5420 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5423 refkey
= heap_alloc(*size
);
5425 return E_OUTOFMEMORY
;
5428 refkey
->writetime
= *writetime
;
5430 WIN32_FILE_ATTRIBUTE_DATA info
;
5432 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5433 refkey
->writetime
= info
.ftLastWriteTime
;
5435 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5437 strcpyW(refkey
->name
, path
);
5444 /* IDWriteGlyphRunAnalysis */
5445 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5447 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5449 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5451 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5452 IsEqualIID(riid
, &IID_IUnknown
))
5455 IDWriteGlyphRunAnalysis_AddRef(iface
);
5459 WARN("%s not implemented.\n", debugstr_guid(riid
));
5462 return E_NOINTERFACE
;
5465 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5467 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5468 ULONG ref
= InterlockedIncrement(&This
->ref
);
5469 TRACE("(%p)->(%u)\n", This
, ref
);
5473 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5475 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5476 ULONG ref
= InterlockedDecrement(&This
->ref
);
5478 TRACE("(%p)->(%u)\n", This
, ref
);
5481 if (This
->run
.fontFace
)
5482 IDWriteFontFace_Release(This
->run
.fontFace
);
5483 heap_free(This
->glyphs
);
5484 heap_free(This
->origins
);
5485 heap_free(This
->bitmap
);
5492 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5496 case DWRITE_RENDERING_MODE1_NATURAL
:
5497 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5498 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5505 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5507 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5510 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5512 struct dwrite_glyphbitmap glyph_bitmap
;
5513 IDWriteFontFace4
*fontface
;
5517 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5518 *bounds
= analysis
->bounds
;
5522 if (analysis
->run
.isSideways
)
5523 FIXME("sideways runs are not supported.\n");
5525 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5527 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5529 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5530 glyph_bitmap
.fontface
= fontface
;
5531 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5532 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5533 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5534 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5535 glyph_bitmap
.m
= &analysis
->m
;
5537 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5538 RECT
*bbox
= &glyph_bitmap
.bbox
;
5541 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5542 freetype_get_glyph_bbox(&glyph_bitmap
);
5544 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5545 (bbox
->bottom
- bbox
->top
);
5546 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5547 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5549 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5550 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5553 IDWriteFontFace4_Release(fontface
);
5555 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5556 *bounds
= analysis
->bounds
;
5559 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5561 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5563 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
5565 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5566 SetRectEmpty(bounds
);
5567 return E_INVALIDARG
;
5570 if (type
!= This
->texture_type
) {
5571 SetRectEmpty(bounds
);
5575 glyphrunanalysis_get_texturebounds(This
, bounds
);
5579 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5581 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5582 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5583 (runbounds
->left
- bounds
->left
) * 3;
5585 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5586 runbounds
->left
- bounds
->left
;
5589 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5591 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5592 struct dwrite_glyphbitmap glyph_bitmap
;
5593 IDWriteFontFace4
*fontface
;
5594 D2D_POINT_2F origin
;
5599 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5601 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5605 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5606 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5608 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5609 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5610 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5611 IDWriteFontFace4_Release(fontface
);
5612 return E_OUTOFMEMORY
;
5615 origin
.x
= origin
.y
= 0.0f
;
5617 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5618 glyph_bitmap
.fontface
= fontface
;
5619 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5620 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5621 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5622 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5623 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5624 glyph_bitmap
.m
= &analysis
->m
;
5625 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5626 IDWriteFontFace4_Release(fontface
);
5627 return E_OUTOFMEMORY
;
5630 bbox
= &glyph_bitmap
.bbox
;
5632 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5633 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5634 int x
, y
, width
, height
;
5637 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5638 freetype_get_glyph_bbox(&glyph_bitmap
);
5640 if (IsRectEmpty(bbox
))
5643 width
= bbox
->right
- bbox
->left
;
5644 height
= bbox
->bottom
- bbox
->top
;
5646 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5647 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5648 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5650 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5652 /* blit to analysis bitmap */
5653 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5656 /* convert 1bpp to 8bpp/24bpp */
5657 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5658 for (y
= 0; y
< height
; y
++) {
5659 for (x
= 0; x
< width
; x
++)
5660 if (src
[x
/ 8] & masks
[x
% 8])
5661 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5662 src
+= glyph_bitmap
.pitch
;
5663 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5667 for (y
= 0; y
< height
; y
++) {
5668 for (x
= 0; x
< width
; x
++)
5669 if (src
[x
/ 8] & masks
[x
% 8])
5670 dst
[x
] = DWRITE_ALPHA_MAX
;
5671 src
+= glyph_bitmap
.pitch
;
5672 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5677 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5678 for (y
= 0; y
< height
; y
++) {
5679 for (x
= 0; x
< width
; x
++)
5680 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5681 src
+= glyph_bitmap
.pitch
;
5682 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5686 for (y
= 0; y
< height
; y
++) {
5687 for (x
= 0; x
< width
; x
++)
5689 src
+= glyph_bitmap
.pitch
;
5690 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5695 heap_free(glyph_bitmap
.buf
);
5697 IDWriteFontFace4_Release(fontface
);
5699 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5701 /* we don't need this anymore */
5702 heap_free(analysis
->glyphs
);
5703 heap_free(analysis
->origins
);
5704 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5706 analysis
->glyphs
= NULL
;
5707 analysis
->origins
= NULL
;
5708 analysis
->run
.glyphIndices
= NULL
;
5709 analysis
->run
.fontFace
= NULL
;
5714 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5715 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5717 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5721 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5723 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5724 return E_INVALIDARG
;
5726 /* make sure buffer is large enough for requested texture type */
5727 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5728 if (This
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5731 if (size
< required
)
5732 return E_NOT_SUFFICIENT_BUFFER
;
5734 /* validate requested texture type */
5735 if (This
->texture_type
!= type
)
5736 return DWRITE_E_UNSUPPORTEDOPERATION
;
5738 memset(bitmap
, 0, size
);
5739 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5740 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5741 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5742 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5743 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5744 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5748 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5751 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5755 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5756 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5758 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5759 memcpy(dst
, src
, draw_width
);
5768 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5769 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5771 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5773 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5776 return E_INVALIDARG
;
5778 switch (This
->rendering_mode
)
5780 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5781 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5784 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5785 *gamma
= (FLOAT
)value
/ 1000.0f
;
5787 *cleartypelevel
= 1.0f
;
5790 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5791 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5793 case DWRITE_RENDERING_MODE1_ALIASED
:
5794 case DWRITE_RENDERING_MODE1_NATURAL
:
5795 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5796 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5797 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5798 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5807 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5808 glyphrunanalysis_QueryInterface
,
5809 glyphrunanalysis_AddRef
,
5810 glyphrunanalysis_Release
,
5811 glyphrunanalysis_GetAlphaTextureBounds
,
5812 glyphrunanalysis_CreateAlphaTexture
,
5813 glyphrunanalysis_GetAlphaBlendParams
5816 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5819 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5820 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5824 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5825 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5827 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5831 FIXME("Sideways mode is not supported.\n");
5833 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5835 switch (measuring_mode
)
5837 case DWRITE_MEASURING_MODE_NATURAL
:
5838 return (float)advance
* emsize
/ (float)upem
;
5839 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5840 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5841 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5843 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5848 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5850 struct dwrite_glyphrunanalysis
*analysis
;
5851 struct dwrite_fontface
*fontface
;
5852 D2D_POINT_2F origin
;
5858 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5859 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5860 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5861 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5862 return E_INVALIDARG
;
5864 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5865 return E_INVALIDARG
;
5867 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5868 return E_INVALIDARG
;
5870 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5871 return E_INVALIDARG
;
5873 analysis
= heap_alloc(sizeof(*analysis
));
5875 return E_OUTOFMEMORY
;
5877 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5879 analysis
->rendering_mode
= desc
->rendering_mode
;
5881 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5882 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5883 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5885 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5887 analysis
->flags
= 0;
5888 analysis
->bitmap
= NULL
;
5889 analysis
->max_glyph_bitmap_size
= 0;
5890 SetRectEmpty(&analysis
->bounds
);
5891 analysis
->run
= *desc
->run
;
5892 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5893 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
5894 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
5896 if (!analysis
->glyphs
|| !analysis
->origins
) {
5897 heap_free(analysis
->glyphs
);
5898 heap_free(analysis
->origins
);
5900 analysis
->glyphs
= NULL
;
5901 analysis
->origins
= NULL
;
5903 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5904 return E_OUTOFMEMORY
;
5907 /* check if transform is usable */
5908 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5909 analysis
->m
= *desc
->transform
;
5910 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5913 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5915 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5916 analysis
->run
.glyphAdvances
= NULL
;
5917 analysis
->run
.glyphOffsets
= NULL
;
5919 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5921 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5923 fontface
= unsafe_impl_from_IDWriteFontFace(desc
->run
->fontFace
);
5925 origin
.x
= desc
->origin
.x
;
5926 origin
.y
= desc
->origin
.y
;
5927 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
5931 /* Use nominal advances if not provided by caller. */
5932 if (desc
->run
->glyphAdvances
)
5933 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
];
5935 advance
= rtl_factor
* fontface_get_scaled_design_advance(fontface
, desc
->measuring_mode
,
5936 desc
->run
->fontEmSize
, 1.0f
, desc
->transform
, desc
->run
->glyphIndices
[i
], desc
->run
->isSideways
);
5938 analysis
->origins
[i
] = origin
;
5939 if (desc
->run
->bidiLevel
& 1)
5941 if (desc
->run
->isSideways
)
5942 analysis
->origins
[i
].y
+= advance
;
5944 analysis
->origins
[i
].x
+= advance
;
5947 /* Offsets are optional, appled to pre-transformed origin. */
5948 if (desc
->run
->glyphOffsets
) {
5949 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
;
5950 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
;
5952 if (desc
->run
->isSideways
) {
5953 analysis
->origins
[i
].x
+= ascenderoffset
;
5954 analysis
->origins
[i
].y
+= advanceoffset
;
5957 analysis
->origins
[i
].x
+= advanceoffset
;
5958 analysis
->origins
[i
].y
+= ascenderoffset
;
5962 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5963 transform_point(analysis
->origins
+ i
, &analysis
->m
);
5965 if (desc
->run
->isSideways
)
5966 origin
.y
+= advance
;
5968 origin
.x
+= advance
;
5971 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5975 /* IDWriteColorGlyphRunEnumerator1 */
5976 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
5978 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5980 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
5981 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5982 IsEqualIID(riid
, &IID_IUnknown
))
5985 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
5989 WARN("%s not implemented.\n", debugstr_guid(riid
));
5992 return E_NOINTERFACE
;
5995 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
5997 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
5998 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6000 TRACE("%p, refcount %u.\n", iface
, refcount
);
6005 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6007 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6008 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6010 TRACE("%p, refcount %u.\n", iface
, refcount
);
6014 heap_free(glyphenum
->advances
);
6015 heap_free(glyphenum
->color_advances
);
6016 heap_free(glyphenum
->offsets
);
6017 heap_free(glyphenum
->color_offsets
);
6018 heap_free(glyphenum
->glyphindices
);
6019 heap_free(glyphenum
->glyphs
);
6020 if (glyphenum
->colr
.context
)
6021 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6022 IDWriteFontFace5_Release(glyphenum
->fontface
);
6023 heap_free(glyphenum
);
6029 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6031 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6032 FLOAT origin
= 0.0f
;
6038 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6042 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6044 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6045 FLOAT advance_adj
= 0.0f
;
6046 BOOL got_palette_index
;
6049 /* start with regular glyphs */
6050 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6051 UINT32 first_glyph
= 0;
6053 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6054 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6055 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6056 first_glyph
= min(first_glyph
, g
);
6059 glyphenum
->glyphindices
[g
] = 1;
6060 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6061 if (glyphenum
->color_offsets
)
6062 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6065 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6066 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6067 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6068 colorrun
->paletteIndex
= 0xffff;
6069 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6070 glyphenum
->has_regular_glyphs
= FALSE
;
6074 colorrun
->glyphRun
.glyphCount
= 0;
6075 got_palette_index
= FALSE
;
6079 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6081 glyphenum
->glyphindices
[g
] = 1;
6083 /* all glyph layers were returned */
6084 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6085 advance_adj
+= glyphenum
->advances
[g
];
6089 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6090 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6091 if (!got_palette_index
) {
6092 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6093 /* use foreground color or request one from the font */
6094 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6095 if (colorrun
->paletteIndex
!= 0xffff)
6097 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6098 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6100 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6101 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6103 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6104 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6105 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6106 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6107 got_palette_index
= TRUE
;
6110 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6111 /* offsets are relative to glyph origin, nothing to fix up */
6112 if (glyphenum
->color_offsets
)
6113 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6114 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6116 glyphenum
->color_advances
[index
-1] += advance_adj
;
6117 colorrun
->glyphRun
.glyphCount
++;
6121 advance_adj
+= glyphenum
->advances
[g
];
6124 /* reset last advance */
6125 if (colorrun
->glyphRun
.glyphCount
)
6126 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6128 return colorrun
->glyphRun
.glyphCount
> 0;
6131 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6133 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6135 TRACE("%p, %p.\n", iface
, has_run
);
6139 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6140 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6142 if (colorglyphenum_build_color_run(glyphenum
))
6145 glyphenum
->current_layer
++;
6148 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6153 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6154 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6156 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6159 return E_NOT_VALID_STATE
;
6162 *run
= &glyphenum
->colorrun
;
6166 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6167 DWRITE_COLOR_GLYPH_RUN
const **run
)
6169 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6171 TRACE("%p, %p.\n", iface
, run
);
6173 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6176 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6177 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6179 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6181 TRACE("%p, %p.\n", iface
, run
);
6183 return colorglyphenum_get_current_run(glyphenum
, run
);
6186 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6188 colorglyphenum_QueryInterface
,
6189 colorglyphenum_AddRef
,
6190 colorglyphenum_Release
,
6191 colorglyphenum_MoveNext
,
6192 colorglyphenum_GetCurrentRun
,
6193 colorglyphenum1_GetCurrentRun
,
6196 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6197 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6198 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6200 struct dwrite_colorglyphenum
*colorglyphenum
;
6201 BOOL colorfont
, has_colored_glyph
;
6202 struct dwrite_fontface
*fontface
;
6207 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6209 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6210 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6212 return DWRITE_E_NOCOLOR
;
6214 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6215 if (!colorglyphenum
)
6216 return E_OUTOFMEMORY
;
6218 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6219 colorglyphenum
->refcount
= 1;
6220 colorglyphenum
->origin_x
= originX
;
6221 colorglyphenum
->origin_y
= originY
;
6222 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6223 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6224 colorglyphenum
->glyphs
= NULL
;
6225 colorglyphenum
->run
= *run
;
6226 colorglyphenum
->run
.glyphIndices
= NULL
;
6227 colorglyphenum
->run
.glyphAdvances
= NULL
;
6228 colorglyphenum
->run
.glyphOffsets
= NULL
;
6229 colorglyphenum
->palette
= palette
;
6230 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6231 colorglyphenum
->colr
.exists
= TRUE
;
6232 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6233 colorglyphenum
->current_layer
= 0;
6234 colorglyphenum
->max_layer_num
= 0;
6236 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6238 has_colored_glyph
= FALSE
;
6239 colorglyphenum
->has_regular_glyphs
= FALSE
;
6240 for (i
= 0; i
< run
->glyphCount
; i
++) {
6241 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6242 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6243 has_colored_glyph
= TRUE
;
6245 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6246 colorglyphenum
->has_regular_glyphs
= TRUE
;
6249 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6250 is supposed to proceed normally, like if font had no color info at all. */
6251 if (!has_colored_glyph
) {
6252 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6253 return DWRITE_E_NOCOLOR
;
6256 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6257 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6258 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6259 if (run
->glyphOffsets
) {
6260 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6261 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6262 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6265 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6266 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6267 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6268 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6269 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6270 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6271 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6272 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6274 if (run
->glyphAdvances
)
6275 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6278 for (i
= 0; i
< run
->glyphCount
; ++i
)
6279 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6280 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6283 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6288 /* IDWriteFontFaceReference */
6289 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6291 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6293 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6294 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6295 IsEqualIID(riid
, &IID_IUnknown
))
6298 IDWriteFontFaceReference1_AddRef(iface
);
6302 WARN("%s not implemented.\n", debugstr_guid(riid
));
6306 return E_NOINTERFACE
;
6309 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6311 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6312 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6314 TRACE("%p, refcount %u.\n", iface
, refcount
);
6319 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6321 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6322 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6324 TRACE("%p, refcount %u.\n", iface
, refcount
);
6328 IDWriteFontFile_Release(reference
->file
);
6329 IDWriteFactory7_Release(reference
->factory
);
6330 heap_free(reference
->axis_values
);
6331 heap_free(reference
);
6337 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6339 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6341 TRACE("%p, %p.\n", iface
, fontface
);
6343 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6346 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6347 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6349 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6350 DWRITE_FONT_FILE_TYPE file_type
;
6351 DWRITE_FONT_FACE_TYPE face_type
;
6352 IDWriteFontFace
*fontface
;
6357 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6359 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6363 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6364 simulations
, &fontface
);
6367 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6368 IDWriteFontFace_Release(fontface
);
6374 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6376 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6377 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6380 TRACE("%p, %p.\n", iface
, ref
);
6382 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6383 reference
->simulations
== other
->simulations
;
6384 if (reference
->axis_values_count
)
6386 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6387 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6393 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6395 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6397 TRACE("%p.\n", iface
);
6399 return reference
->index
;
6402 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6404 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6406 TRACE("%p.\n", iface
);
6408 return reference
->simulations
;
6411 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6413 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6414 IDWriteFontFileLoader
*loader
;
6419 TRACE("%p, %p.\n", iface
, file
);
6421 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6425 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6429 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6430 IDWriteFontFileLoader_Release(loader
);
6435 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6437 FIXME("%p.\n", iface
);
6442 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6444 FIXME("%p.\n", iface
);
6449 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6451 FIXME("%p, %p.\n", iface
, writetime
);
6456 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6458 FIXME("%p.\n", iface
);
6460 return DWRITE_LOCALITY_LOCAL
;
6463 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6465 FIXME("%p.\n", iface
);
6470 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6471 WCHAR
const *chars
, UINT32 count
)
6473 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6478 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6479 UINT16
const *glyphs
, UINT32 count
)
6481 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6486 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6487 UINT64 offset
, UINT64 size
)
6489 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6494 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6496 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6497 IDWriteFontFace3
*fontface3
;
6500 TRACE("%p, %p.\n", iface
, fontface
);
6502 /* FIXME: created instance should likely respect given axis. */
6503 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6506 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6507 IDWriteFontFace3_Release(fontface3
);
6513 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6515 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6517 TRACE("%p.\n", iface
);
6519 return reference
->axis_values_count
;
6522 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6523 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6525 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6527 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6529 if (value_count
< reference
->axis_values_count
)
6530 return E_NOT_SUFFICIENT_BUFFER
;
6532 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6537 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6539 fontfacereference_QueryInterface
,
6540 fontfacereference_AddRef
,
6541 fontfacereference_Release
,
6542 fontfacereference_CreateFontFace
,
6543 fontfacereference_CreateFontFaceWithSimulations
,
6544 fontfacereference_Equals
,
6545 fontfacereference_GetFontFaceIndex
,
6546 fontfacereference_GetSimulations
,
6547 fontfacereference_GetFontFile
,
6548 fontfacereference_GetLocalFileSize
,
6549 fontfacereference_GetFileSize
,
6550 fontfacereference_GetFileTime
,
6551 fontfacereference_GetLocality
,
6552 fontfacereference_EnqueueFontDownloadRequest
,
6553 fontfacereference_EnqueueCharacterDownloadRequest
,
6554 fontfacereference_EnqueueGlyphDownloadRequest
,
6555 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6556 fontfacereference1_CreateFontFace
,
6557 fontfacereference1_GetFontAxisValueCount
,
6558 fontfacereference1_GetFontAxisValues
,
6561 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6562 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6563 IDWriteFontFaceReference1
**ret
)
6565 struct dwrite_fontfacereference
*object
;
6569 if (!is_simulation_valid(simulations
))
6570 return E_INVALIDARG
;
6572 object
= heap_alloc_zero(sizeof(*object
));
6574 return E_OUTOFMEMORY
;
6576 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6577 object
->refcount
= 1;
6579 object
->factory
= factory
;
6580 IDWriteFactory7_AddRef(object
->factory
);
6581 object
->file
= file
;
6582 IDWriteFontFile_AddRef(object
->file
);
6583 object
->index
= index
;
6584 object
->simulations
= simulations
;
6585 if (axis_values_count
)
6587 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6589 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6590 return E_OUTOFMEMORY
;
6592 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6593 object
->axis_values_count
= axis_values_count
;
6596 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6601 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6603 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6605 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6607 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6609 IDWriteFontFileStream_AddRef(iface
);
6615 WARN("%s not implemented.\n", debugstr_guid(riid
));
6616 return E_NOINTERFACE
;
6619 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6621 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6622 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6623 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6627 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6629 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6630 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6632 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6635 release_inmemory_stream(stream
->data
);
6642 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6643 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6645 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6647 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6648 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6650 *fragment_context
= NULL
;
6652 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6653 *fragment_start
= NULL
;
6657 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6661 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6663 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6665 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6668 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6670 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6672 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6674 *size
= stream
->data
->size
;
6679 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6681 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6683 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6685 *last_writetime
= 0;
6690 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6691 inmemoryfilestream_QueryInterface
,
6692 inmemoryfilestream_AddRef
,
6693 inmemoryfilestream_Release
,
6694 inmemoryfilestream_ReadFileFragment
,
6695 inmemoryfilestream_ReleaseFileFragment
,
6696 inmemoryfilestream_GetFileSize
,
6697 inmemoryfilestream_GetLastWriteTime
,
6700 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6701 REFIID riid
, void **obj
)
6703 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6705 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6707 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6708 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6709 IsEqualIID(riid
, &IID_IUnknown
))
6712 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6716 WARN("%s not implemented.\n", debugstr_guid(riid
));
6720 return E_NOINTERFACE
;
6723 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6725 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6726 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6727 TRACE("(%p)->(%u)\n", loader
, ref
);
6731 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6733 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6734 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6737 TRACE("(%p)->(%u)\n", loader
, ref
);
6740 for (i
= 0; i
< loader
->count
; ++i
)
6741 release_inmemory_stream(loader
->streams
[i
]);
6742 heap_free(loader
->streams
);
6749 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6750 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6752 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6753 struct dwrite_inmemory_filestream
*stream
;
6756 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6760 if (key_size
!= sizeof(DWORD
))
6761 return E_INVALIDARG
;
6763 index
= *(DWORD
*)key
;
6765 if (index
>= loader
->count
)
6766 return E_INVALIDARG
;
6768 if (!(stream
= heap_alloc(sizeof(*stream
))))
6769 return E_OUTOFMEMORY
;
6771 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6773 stream
->data
= loader
->streams
[index
];
6774 InterlockedIncrement(&stream
->data
->ref
);
6776 *ret
= &stream
->IDWriteFontFileStream_iface
;
6781 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6782 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6784 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6785 struct dwrite_inmemory_stream_data
*stream
;
6788 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6792 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6793 return E_OUTOFMEMORY
;
6795 if (!(stream
= heap_alloc(sizeof(*stream
))))
6796 return E_OUTOFMEMORY
;
6799 stream
->size
= data_size
;
6800 stream
->owner
= owner
;
6801 if (stream
->owner
) {
6802 IUnknown_AddRef(stream
->owner
);
6803 stream
->data
= (void *)data
;
6806 if (!(stream
->data
= heap_alloc(data_size
))) {
6808 return E_OUTOFMEMORY
;
6810 memcpy(stream
->data
, data
, data_size
);
6813 key
= loader
->count
;
6814 loader
->streams
[loader
->count
++] = stream
;
6816 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6817 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6820 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6822 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6824 TRACE("%p.\n", iface
);
6826 return loader
->count
;
6829 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6831 inmemoryfontfileloader_QueryInterface
,
6832 inmemoryfontfileloader_AddRef
,
6833 inmemoryfontfileloader_Release
,
6834 inmemoryfontfileloader_CreateStreamFromKey
,
6835 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6836 inmemoryfontfileloader_GetFileCount
,
6839 HRESULT
create_inmemory_fileloader(IDWriteFontFileLoader
**ret
)
6841 struct dwrite_inmemory_fileloader
*loader
;
6845 loader
= heap_alloc_zero(sizeof(*loader
));
6847 return E_OUTOFMEMORY
;
6849 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6852 *ret
= (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
;
6857 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6859 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6861 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6862 IsEqualIID(riid
, &IID_IUnknown
))
6865 IDWriteFontResource_AddRef(iface
);
6869 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6871 return E_NOINTERFACE
;
6874 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6876 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6877 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6879 TRACE("%p, refcount %u.\n", iface
, refcount
);
6884 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6886 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6887 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6889 TRACE("%p, refcount %u.\n", iface
, refcount
);
6893 IDWriteFactory7_Release(resource
->factory
);
6894 IDWriteFontFile_Release(resource
->file
);
6895 heap_free(resource
);
6901 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6903 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6905 TRACE("%p, %p.\n", iface
, fontfile
);
6907 *fontfile
= resource
->file
;
6908 IDWriteFontFile_AddRef(*fontfile
);
6913 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6915 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6917 TRACE("%p.\n", iface
);
6919 return resource
->face_index
;
6922 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6924 FIXME("%p.\n", iface
);
6929 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6930 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6932 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
6937 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
6938 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
6940 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
6945 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
6948 FIXME("%p, %u.\n", iface
, axis
);
6950 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
6953 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
6954 IDWriteLocalizedStrings
**names
)
6956 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
6961 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
6963 FIXME("%p, %u.\n", iface
, axis
);
6968 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
6969 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
6971 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
6976 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
6978 FIXME("%p.\n", iface
);
6983 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
6984 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
6985 IDWriteFontFace5
**fontface
)
6987 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6988 IDWriteFontFaceReference1
*reference
;
6991 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
6993 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
6994 simulations
, axis_values
, num_values
, &reference
);
6997 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
6998 IDWriteFontFaceReference1_Release(reference
);
7004 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7005 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7006 IDWriteFontFaceReference1
**reference
)
7008 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7010 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7012 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7013 simulations
, axis_values
, num_values
, reference
);
7016 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7018 dwritefontresource_QueryInterface
,
7019 dwritefontresource_AddRef
,
7020 dwritefontresource_Release
,
7021 dwritefontresource_GetFontFile
,
7022 dwritefontresource_GetFontFaceIndex
,
7023 dwritefontresource_GetFontAxisCount
,
7024 dwritefontresource_GetDefaultFontAxisValues
,
7025 dwritefontresource_GetFontAxisRanges
,
7026 dwritefontresource_GetFontAxisAttributes
,
7027 dwritefontresource_GetAxisNames
,
7028 dwritefontresource_GetAxisValueNameCount
,
7029 dwritefontresource_GetAxisValueNames
,
7030 dwritefontresource_HasVariations
,
7031 dwritefontresource_CreateFontFace
,
7032 dwritefontresource_CreateFontFaceReference
,
7035 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7036 IDWriteFontResource
**ret
)
7038 struct dwrite_fontresource
*resource
;
7042 resource
= heap_alloc_zero(sizeof(*resource
));
7044 return E_OUTOFMEMORY
;
7046 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7047 resource
->refcount
= 1;
7048 resource
->face_index
= face_index
;
7049 resource
->file
= file
;
7050 IDWriteFontFile_AddRef(resource
->file
);
7051 resource
->factory
= factory
;
7052 IDWriteFactory7_AddRef(resource
->factory
);
7054 *ret
= &resource
->IDWriteFontResource_iface
;