4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2017 Nikolay Sivov for CodeWeavers
6 * Copyright 2014 Aric Stewart for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "dwrite_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
31 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
33 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
34 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
35 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
36 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
37 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
38 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
39 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
40 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
42 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
44 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
45 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
46 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
48 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
49 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
50 static const WCHAR semiW
[] = {'s','e','m','i',0};
51 static const WCHAR extW
[] = {'e','x','t',0};
52 static const WCHAR thinW
[] = {'t','h','i','n',0};
53 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
54 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
55 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
56 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
57 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
58 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
59 static const WCHAR boldW
[] = {'B','o','l','d',0};
60 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
61 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
62 static const WCHAR demiW
[] = {'d','e','m','i',0};
63 static const WCHAR spaceW
[] = {' ',0};
64 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
66 struct dwrite_font_propvec
{
72 struct dwrite_font_data
76 DWRITE_FONT_STYLE style
;
77 DWRITE_FONT_STRETCH stretch
;
78 DWRITE_FONT_WEIGHT weight
;
80 FONTSIGNATURE fontsig
;
81 UINT32 flags
; /* enum font_flags */
82 struct dwrite_font_propvec propvec
;
83 struct dwrite_cmap cmap
;
84 /* Static axis for weight/width/italic. */
85 DWRITE_FONT_AXIS_VALUE axis
[3];
87 DWRITE_FONT_METRICS1 metrics
;
88 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
89 IDWriteLocalizedStrings
*family_names
;
90 IDWriteLocalizedStrings
*names
;
92 /* data needed to create fontface instance */
93 DWRITE_FONT_FACE_TYPE face_type
;
94 IDWriteFontFile
*file
;
103 /* used to mark font as tested when scanning for simulation candidate */
104 unsigned int bold_sim_tested
: 1;
105 unsigned int oblique_sim_tested
: 1;
108 struct dwrite_fontfamily_data
112 IDWriteLocalizedStrings
*familyname
;
114 struct dwrite_font_data
**fonts
;
118 unsigned int has_normal_face
: 1;
119 unsigned int has_oblique_face
: 1;
120 unsigned int has_italic_face
: 1;
123 struct dwrite_fontcollection
125 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
128 IDWriteFactory7
*factory
;
129 struct dwrite_fontfamily_data
**family_data
;
134 struct dwrite_fontfamily
136 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
137 IDWriteFontList2 IDWriteFontList2_iface
;
140 struct dwrite_fontfamily_data
*data
;
141 struct dwrite_fontcollection
*collection
;
144 struct dwrite_fontlist
146 IDWriteFontList2 IDWriteFontList2_iface
;
149 struct dwrite_font_data
**fonts
;
151 struct dwrite_fontfamily
*family
;
156 IDWriteFont3 IDWriteFont3_iface
;
159 DWRITE_FONT_STYLE style
;
160 struct dwrite_font_data
*data
;
161 struct dwrite_fontfamily
*family
;
164 enum runanalysis_flags
{
165 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
166 RUNANALYSIS_BITMAP_READY
= 1 << 1,
167 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
170 struct dwrite_glyphrunanalysis
172 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
175 DWRITE_RENDERING_MODE1 rendering_mode
;
176 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
177 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
180 D2D_POINT_2F
*origins
;
185 UINT32 max_glyph_bitmap_size
;
188 struct dwrite_colorglyphenum
190 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
193 FLOAT origin_x
; /* original run origin */
196 IDWriteFontFace5
*fontface
; /* for convenience */
197 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
198 DWRITE_GLYPH_RUN run
; /* base run */
199 UINT32 palette
; /* palette index to get layer color from */
200 FLOAT
*advances
; /* original or measured advances for base glyphs */
201 FLOAT
*color_advances
; /* returned color run points to this */
202 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
203 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
204 UINT16
*glyphindices
; /* returned color run points to this */
205 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
206 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
207 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
208 UINT16 max_layer_num
; /* max number of layers for this run */
209 struct dwrite_fonttable colr
; /* used to access layers */
212 #define GLYPH_BLOCK_SHIFT 8
213 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
214 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
215 #define GLYPH_MAX 65536
217 struct dwrite_fontfile
219 IDWriteFontFile IDWriteFontFile_iface
;
222 IDWriteFontFileLoader
*loader
;
225 IDWriteFontFileStream
*stream
;
228 struct dwrite_fontfacereference
230 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
233 IDWriteFontFile
*file
;
236 DWRITE_FONT_AXIS_VALUE
*axis_values
;
237 UINT32 axis_values_count
;
238 IDWriteFactory7
*factory
;
241 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
243 struct dwrite_fontresource
245 IDWriteFontResource IDWriteFontResource_iface
;
248 IDWriteFontFile
*file
;
250 IDWriteFactory7
*factory
;
253 struct dwrite_fontset_builder
255 IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface
;
257 IDWriteFactory7
*factory
;
260 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
262 struct dwrite_fontface
*fontface
= context
;
265 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
266 size
, data_context
, &exists
)) || !exists
)
270 *data_context
= NULL
;
274 static void dwrite_release_font_table(void *context
, void *data_context
)
276 struct dwrite_fontface
*fontface
= context
;
277 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
280 static UINT16
dwrite_get_font_upem(void *context
)
282 struct dwrite_fontface
*fontface
= context
;
283 return fontface
->metrics
.designUnitsPerEm
;
286 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
288 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
289 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
292 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
294 struct dwrite_fontface
*fontface
= context
;
295 return !!dwritefontface_get_glyph(fontface
, codepoint
);
298 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
300 struct dwrite_fontface
*fontface
= context
;
301 return dwritefontface_get_glyph(fontface
, codepoint
);
304 static const struct shaping_font_ops dwrite_font_ops
=
306 dwrite_grab_font_table
,
307 dwrite_release_font_table
,
308 dwrite_get_font_upem
,
313 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
315 if (fontface
->shaping_cache
)
316 return fontface
->shaping_cache
;
318 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
321 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
323 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
326 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
328 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
331 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
333 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
336 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
338 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
340 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
343 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
345 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
348 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
350 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
353 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
355 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
358 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
360 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
363 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
365 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
368 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
370 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
373 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
375 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
378 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
380 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
383 static struct dwrite_fontset_builder
*impl_from_IDWriteFontSetBuilder2(IDWriteFontSetBuilder2
*iface
)
385 return CONTAINING_RECORD(iface
, struct dwrite_fontset_builder
, IDWriteFontSetBuilder2_iface
);
388 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
390 static const DWRITE_GLYPH_METRICS nil
;
391 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
393 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
394 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
398 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
400 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
403 /* start new block */
404 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
406 return E_OUTOFMEMORY
;
409 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
413 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
417 if (table
->data
|| !table
->exists
)
420 table
->exists
= FALSE
;
421 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
423 if (FAILED(hr
) || !table
->exists
) {
424 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
431 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
432 struct dwrite_font_propvec
*vec
)
434 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
435 vec
->style
= style
* 7.0f
;
436 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
439 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
441 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
444 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
446 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
449 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
451 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
452 return &fontface
->vdmx
;
455 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
457 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
458 return &fontface
->gasp
;
461 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
463 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
464 return &fontface
->cpal
;
467 static void addref_font_data(struct dwrite_font_data
*data
)
469 InterlockedIncrement(&data
->ref
);
472 static void release_font_data(struct dwrite_font_data
*data
)
476 if (InterlockedDecrement(&data
->ref
) > 0)
479 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
481 if (data
->info_strings
[i
])
482 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
485 IDWriteLocalizedStrings_Release(data
->names
);
487 if (data
->family_names
)
488 IDWriteLocalizedStrings_Release(data
->family_names
);
490 dwrite_cmap_release(&data
->cmap
);
491 IDWriteFontFile_Release(data
->file
);
492 heap_free(data
->facename
);
496 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
500 if (InterlockedDecrement(&data
->refcount
) > 0)
503 for (i
= 0; i
< data
->count
; ++i
)
504 release_font_data(data
->fonts
[i
]);
505 heap_free(data
->fonts
);
506 IDWriteLocalizedStrings_Release(data
->familyname
);
510 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
512 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
513 fontface
->cached
= NULL
;
516 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
518 UINT32 left_key_size
, right_key_size
;
519 const void *left_key
, *right_key
;
525 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
529 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
533 if (left_key_size
!= right_key_size
)
536 return !memcmp(left_key
, right_key
, left_key_size
);
539 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
541 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
543 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
545 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
546 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
547 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
548 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
549 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
550 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
551 IsEqualIID(riid
, &IID_IUnknown
))
555 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
556 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
562 if (InterlockedIncrement(&fontface
->refcount
) == 1)
564 InterlockedDecrement(&fontface
->refcount
);
571 WARN("%s not implemented.\n", debugstr_guid(riid
));
573 return E_NOINTERFACE
;
576 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
578 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
579 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
581 TRACE("%p, refcount %u.\n", iface
, refcount
);
586 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
588 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
589 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
591 TRACE("%p, refcount %u.\n", iface
, refcount
);
597 if (fontface
->cached
)
599 factory_lock(fontface
->factory
);
600 list_remove(&fontface
->cached
->entry
);
601 factory_unlock(fontface
->factory
);
602 heap_free(fontface
->cached
);
604 release_scriptshaping_cache(fontface
->shaping_cache
);
605 if (fontface
->vdmx
.context
)
606 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
607 if (fontface
->gasp
.context
)
608 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
609 if (fontface
->cpal
.context
)
610 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
611 if (fontface
->colr
.context
)
612 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
613 for (i
= 0; i
< fontface
->file_count
; i
++)
615 if (fontface
->files
[i
])
616 IDWriteFontFile_Release(fontface
->files
[i
]);
618 if (fontface
->stream
)
619 IDWriteFontFileStream_Release(fontface
->stream
);
620 heap_free(fontface
->files
);
622 IDWriteLocalizedStrings_Release(fontface
->names
);
623 if (fontface
->family_names
)
624 IDWriteLocalizedStrings_Release(fontface
->family_names
);
625 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
627 if (fontface
->info_strings
[i
])
628 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
631 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
632 heap_free(fontface
->glyphs
[i
]);
634 freetype_notify_cacheremove(iface
);
636 dwrite_cmap_release(&fontface
->cmap
);
637 IDWriteFactory7_Release(fontface
->factory
);
644 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
646 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
648 TRACE("%p.\n", iface
);
650 return fontface
->type
;
653 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
654 IDWriteFontFile
**fontfiles
)
656 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
659 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
661 if (fontfiles
== NULL
)
663 *number_of_files
= fontface
->file_count
;
667 if (*number_of_files
< fontface
->file_count
)
670 for (i
= 0; i
< fontface
->file_count
; i
++)
672 IDWriteFontFile_AddRef(fontface
->files
[i
]);
673 fontfiles
[i
] = fontface
->files
[i
];
679 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
681 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
683 TRACE("%p.\n", iface
);
685 return fontface
->index
;
688 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
690 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
692 TRACE("%p.\n", iface
);
694 return fontface
->simulations
;
697 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
699 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
701 TRACE("%p.\n", iface
);
703 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
706 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
708 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
710 TRACE("%p, %p.\n", iface
, metrics
);
712 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
715 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
717 TRACE("%p.\n", iface
);
719 return freetype_get_glyphcount(iface
);
722 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
723 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
725 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
729 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
735 FIXME("sideways metrics are not supported.\n");
737 for (i
= 0; i
< glyph_count
; i
++) {
738 DWRITE_GLYPH_METRICS metrics
;
740 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
742 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
743 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
753 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
754 UINT32 count
, UINT16
*glyphs
)
756 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
759 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
766 memset(glyphs
, 0, count
* sizeof(*glyphs
));
770 for (i
= 0; i
< count
; ++i
)
771 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
776 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
777 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
779 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
780 struct file_stream_desc stream_desc
;
782 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
784 stream_desc
.stream
= fontface
->stream
;
785 stream_desc
.face_type
= fontface
->type
;
786 stream_desc
.face_index
= fontface
->index
;
787 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
790 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
792 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
794 TRACE("%p, %p.\n", iface
, table_context
);
796 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
799 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
800 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
801 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
803 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
804 count
, is_sideways
, is_rtl
, sink
);
806 if (!glyphs
|| !sink
)
810 FIXME("sideways mode is not supported.\n");
812 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
815 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
816 float ppem
, unsigned int gasp
)
818 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
822 case DWRITE_MEASURING_MODE_NATURAL
:
824 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
825 mode
= DWRITE_RENDERING_MODE_NATURAL
;
827 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
830 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
831 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
833 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
834 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
843 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
844 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
846 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
850 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
853 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
857 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
858 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
861 ppem
= emSize
* ppdip
;
863 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
864 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
868 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
869 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
873 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
874 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
876 DWRITE_FONT_METRICS1 metrics1
;
877 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
878 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
882 static inline int round_metric(FLOAT metric
)
884 return (int)floorf(metric
+ 0.5f
);
887 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
889 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
892 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
895 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
896 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
897 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
899 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
900 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
901 DWRITE_MEASURING_MODE mode
;
906 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
907 glyph_count
, metrics
, is_sideways
);
909 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
910 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
912 size
= emSize
* ppdip
;
913 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
914 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
916 for (i
= 0; i
< glyph_count
; i
++) {
917 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
918 DWRITE_GLYPH_METRICS design
;
921 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
925 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
927 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
929 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
931 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
932 SCALE_METRIC(leftSideBearing
);
933 SCALE_METRIC(rightSideBearing
);
934 SCALE_METRIC(topSideBearing
);
935 SCALE_METRIC(advanceHeight
);
936 SCALE_METRIC(bottomSideBearing
);
937 SCALE_METRIC(verticalOriginY
);
944 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
946 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
948 TRACE("%p, %p.\n", iface
, metrics
);
950 *metrics
= fontface
->metrics
;
953 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
954 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
956 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
957 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
958 UINT16 ascent
, descent
;
961 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
963 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
964 memset(metrics
, 0, sizeof(*metrics
));
968 em_size
*= pixels_per_dip
;
969 if (m
&& m
->m22
!= 0.0f
)
970 em_size
*= fabs(m
->m22
);
972 scale
= em_size
/ design
->designUnitsPerEm
;
973 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
975 ascent
= round_metric(design
->ascent
* scale
);
976 descent
= round_metric(design
->descent
* scale
);
979 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
980 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
981 metrics
->ascent
= round_metric(ascent
/ scale
);
982 metrics
->descent
= round_metric(descent
/ scale
);
984 SCALE_METRIC(lineGap
);
985 SCALE_METRIC(capHeight
);
986 SCALE_METRIC(xHeight
);
987 SCALE_METRIC(underlinePosition
);
988 SCALE_METRIC(underlineThickness
);
989 SCALE_METRIC(strikethroughPosition
);
990 SCALE_METRIC(strikethroughThickness
);
991 SCALE_METRIC(glyphBoxLeft
);
992 SCALE_METRIC(glyphBoxTop
);
993 SCALE_METRIC(glyphBoxRight
);
994 SCALE_METRIC(glyphBoxBottom
);
995 SCALE_METRIC(subscriptPositionX
);
996 SCALE_METRIC(subscriptPositionY
);
997 SCALE_METRIC(subscriptSizeX
);
998 SCALE_METRIC(subscriptSizeY
);
999 SCALE_METRIC(superscriptPositionX
);
1000 SCALE_METRIC(superscriptPositionY
);
1001 SCALE_METRIC(superscriptSizeX
);
1002 SCALE_METRIC(superscriptSizeY
);
1004 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
1010 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1012 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1014 TRACE("%p, %p.\n", iface
, metrics
);
1016 *metrics
= fontface
->caret
;
1019 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1020 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1022 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1024 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1027 if (max_count
&& !ranges
)
1028 return E_INVALIDARG
;
1030 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1031 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1034 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1036 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1038 TRACE("%p.\n", iface
);
1040 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1043 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1044 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1046 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1051 FIXME("Sideways mode is not supported.\n");
1053 switch (measuring_mode
)
1055 case DWRITE_MEASURING_MODE_NATURAL
:
1056 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1057 glyph
, measuring_mode
, &has_contours
);
1059 advance
+= adjustment
;
1062 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1063 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1068 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1069 FIXME("Transform is not supported.\n");
1071 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1074 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1076 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1080 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1085 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1086 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1088 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1091 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1094 FIXME("sideways mode not supported\n");
1096 for (i
= 0; i
< glyph_count
; ++i
)
1098 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1099 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1105 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1106 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1107 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1109 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1110 DWRITE_MEASURING_MODE measuring_mode
;
1113 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1114 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1116 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1117 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1118 return E_INVALIDARG
;
1121 if (em_size
== 0.0f
) {
1122 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1126 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1127 for (i
= 0; i
< glyph_count
; ++i
)
1129 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1130 glyphs
[i
], is_sideways
);
1136 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1137 const UINT16
*indices
, INT32
*adjustments
)
1139 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1142 TRACE("%p, %u, %p, %p.\n", iface
, count
, indices
, adjustments
);
1144 if (!(indices
|| adjustments
) || !count
)
1145 return E_INVALIDARG
;
1147 if (!indices
|| count
== 1) {
1148 memset(adjustments
, 0, count
*sizeof(INT32
));
1149 return E_INVALIDARG
;
1152 if (!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
))
1154 memset(adjustments
, 0, count
*sizeof(INT32
));
1158 for (i
= 0; i
< count
-1; i
++)
1159 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1160 adjustments
[count
-1] = 0;
1165 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1167 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1169 TRACE("%p.\n", iface
);
1171 return !!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1174 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1175 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1176 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1178 DWRITE_GRID_FIT_MODE gridfitmode
;
1179 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1180 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1183 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1184 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1186 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1188 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1190 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1193 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1195 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1197 TRACE("%p.\n", iface
);
1199 return !!(fontface
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1202 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1204 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1206 TRACE("%p.\n", iface
);
1208 return !!(fontface
->flags
& FONT_IS_COLORED
);
1211 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1213 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1215 TRACE("%p.\n", iface
);
1217 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1220 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1222 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1224 TRACE("%p.\n", iface
);
1226 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1229 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1230 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1232 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1234 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1236 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1239 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1240 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1241 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1242 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1244 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1248 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1249 measuringmode
, params
, renderingmode
, gridfitmode
);
1252 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1255 FIXME("sideways mode not supported\n");
1257 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1259 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1260 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1262 IDWriteRenderingParams2
*params2
;
1265 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1267 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1268 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1269 IDWriteRenderingParams2_Release(params2
);
1272 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1275 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1277 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1279 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1280 if (emSize
>= emthreshold
)
1281 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1283 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1286 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1287 if (emSize
>= emthreshold
)
1288 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1289 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1290 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1292 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1293 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1299 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1300 IDWriteFontFaceReference
**reference
)
1302 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1304 TRACE("%p, %p.\n", iface
, reference
);
1306 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1307 IDWriteFontFaceReference_AddRef(*reference
);
1312 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1314 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1316 TRACE("%p, %p.\n", iface
, panose
);
1318 *panose
= fontface
->panose
;
1321 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1323 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1325 TRACE("%p.\n", iface
);
1327 return fontface
->weight
;
1330 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1332 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1334 TRACE("%p.\n", iface
);
1336 return fontface
->stretch
;
1339 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1341 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1343 TRACE("%p.\n", iface
);
1345 return fontface
->style
;
1348 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1350 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1352 TRACE("%p, %p.\n", iface
, names
);
1354 return clone_localizedstrings(fontface
->family_names
, names
);
1357 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1359 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1361 TRACE("%p, %p.\n", iface
, names
);
1363 return clone_localizedstrings(fontface
->names
, names
);
1366 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1367 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1368 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1375 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1376 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1381 if (!strings_cache
[stringid
])
1383 struct file_stream_desc desc
= *stream_desc
;
1386 hr
= get_filestream_from_file(file
, &desc
.stream
);
1388 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1390 if (!stream_desc
->stream
&& desc
.stream
)
1391 IDWriteFontFileStream_Release(desc
.stream
);
1394 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1396 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1404 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1405 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1407 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1408 struct file_stream_desc stream_desc
;
1410 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1412 stream_desc
.stream
= fontface
->stream
;
1413 stream_desc
.face_index
= fontface
->index
;
1414 stream_desc
.face_type
= fontface
->type
;
1415 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1418 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1420 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1422 TRACE("%p, %#x.\n", iface
, ch
);
1424 return !!dwritefontface_get_glyph(fontface
, ch
);
1427 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1428 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1429 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1431 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1435 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1436 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1439 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1442 FIXME("sideways mode not supported\n");
1444 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1446 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1447 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1449 IDWriteRenderingParams3
*params3
;
1452 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1454 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1455 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1456 IDWriteRenderingParams3_Release(params3
);
1459 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1462 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1464 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1466 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1467 if (emSize
>= emthreshold
)
1468 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1470 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1473 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1474 if (emSize
>= emthreshold
)
1475 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1476 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1477 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1479 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1480 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1486 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1488 FIXME("%p, %#x: stub\n", iface
, ch
);
1493 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1495 FIXME("%p, %u: stub\n", iface
, glyph
);
1500 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1501 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1503 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1508 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1509 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1511 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1516 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1517 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1519 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1524 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1526 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1528 TRACE("%p.\n", iface
);
1530 return fontface
->glyph_image_formats
;
1533 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1534 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1536 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1541 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1543 FIXME("%p, %p: stub\n", iface
, context
);
1546 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1548 FIXME("%p: stub\n", iface
);
1553 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1556 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1561 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1566 FIXME("%p: stub\n", iface
);
1571 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1573 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1575 TRACE("%p, %p.\n", iface
, resource
);
1577 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->files
[0], fontface
->index
, resource
);
1580 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1582 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1584 TRACE("%p, %p.\n", iface
, other
);
1586 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1589 /* TODO: add variations support */
1591 return fontface
->index
== other_face
->index
&&
1592 fontface
->simulations
== other_face
->simulations
&&
1593 is_same_fontfile(fontface
->files
[0], other_face
->files
[0]);
1596 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1598 dwritefontface_QueryInterface
,
1599 dwritefontface_AddRef
,
1600 dwritefontface_Release
,
1601 dwritefontface_GetType
,
1602 dwritefontface_GetFiles
,
1603 dwritefontface_GetIndex
,
1604 dwritefontface_GetSimulations
,
1605 dwritefontface_IsSymbolFont
,
1606 dwritefontface_GetMetrics
,
1607 dwritefontface_GetGlyphCount
,
1608 dwritefontface_GetDesignGlyphMetrics
,
1609 dwritefontface_GetGlyphIndices
,
1610 dwritefontface_TryGetFontTable
,
1611 dwritefontface_ReleaseFontTable
,
1612 dwritefontface_GetGlyphRunOutline
,
1613 dwritefontface_GetRecommendedRenderingMode
,
1614 dwritefontface_GetGdiCompatibleMetrics
,
1615 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1616 dwritefontface1_GetMetrics
,
1617 dwritefontface1_GetGdiCompatibleMetrics
,
1618 dwritefontface1_GetCaretMetrics
,
1619 dwritefontface1_GetUnicodeRanges
,
1620 dwritefontface1_IsMonospacedFont
,
1621 dwritefontface1_GetDesignGlyphAdvances
,
1622 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1623 dwritefontface1_GetKerningPairAdjustments
,
1624 dwritefontface1_HasKerningPairs
,
1625 dwritefontface1_GetRecommendedRenderingMode
,
1626 dwritefontface1_GetVerticalGlyphVariants
,
1627 dwritefontface1_HasVerticalGlyphVariants
,
1628 dwritefontface2_IsColorFont
,
1629 dwritefontface2_GetColorPaletteCount
,
1630 dwritefontface2_GetPaletteEntryCount
,
1631 dwritefontface2_GetPaletteEntries
,
1632 dwritefontface2_GetRecommendedRenderingMode
,
1633 dwritefontface3_GetFontFaceReference
,
1634 dwritefontface3_GetPanose
,
1635 dwritefontface3_GetWeight
,
1636 dwritefontface3_GetStretch
,
1637 dwritefontface3_GetStyle
,
1638 dwritefontface3_GetFamilyNames
,
1639 dwritefontface3_GetFaceNames
,
1640 dwritefontface3_GetInformationalStrings
,
1641 dwritefontface3_HasCharacter
,
1642 dwritefontface3_GetRecommendedRenderingMode
,
1643 dwritefontface3_IsCharacterLocal
,
1644 dwritefontface3_IsGlyphLocal
,
1645 dwritefontface3_AreCharactersLocal
,
1646 dwritefontface3_AreGlyphsLocal
,
1647 dwritefontface4_GetGlyphImageFormats_
,
1648 dwritefontface4_GetGlyphImageFormats
,
1649 dwritefontface4_GetGlyphImageData
,
1650 dwritefontface4_ReleaseGlyphImageData
,
1651 dwritefontface5_GetFontAxisValueCount
,
1652 dwritefontface5_GetFontAxisValues
,
1653 dwritefontface5_HasVariations
,
1654 dwritefontface5_GetFontResource
,
1655 dwritefontface5_Equals
,
1658 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1660 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1661 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1664 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1666 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1667 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1670 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1672 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1673 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1676 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1677 IDWriteFontFace3
**ret
)
1679 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1681 TRACE("%p, %p.\n", iface
, ret
);
1683 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1684 IDWriteFontFace3_AddRef(*ret
);
1689 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1690 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1692 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1693 DWRITE_FONT_FILE_TYPE file_type
;
1694 DWRITE_FONT_FACE_TYPE face_type
;
1695 IDWriteFontFace
*face
;
1700 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1702 hr
= IDWriteFontFile_Analyze(fontface
->files
[0], &is_supported
, &file_type
, &face_type
, &face_num
);
1706 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, fontface
->files
, fontface
->index
,
1707 simulations
, &face
);
1710 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1711 IDWriteFontFace_Release(face
);
1717 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1719 FIXME("%p, %p.\n", iface
, ref
);
1724 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1726 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1728 TRACE("%p.\n", iface
);
1730 return fontface
->index
;
1733 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1735 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1737 TRACE("%p.\n", iface
);
1739 return fontface
->simulations
;
1742 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1744 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1746 TRACE("%p, %p.\n", iface
, file
);
1748 *file
= fontface
->files
[0];
1749 IDWriteFontFile_AddRef(*file
);
1754 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1756 FIXME("%p.\n", iface
);
1761 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1763 FIXME("%p.\n", iface
);
1768 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1770 FIXME("%p, %p.\n", iface
, writetime
);
1775 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1777 FIXME("%p.\n", iface
);
1779 return DWRITE_LOCALITY_LOCAL
;
1782 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1784 FIXME("%p.\n", iface
);
1789 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1790 WCHAR
const *chars
, UINT32 count
)
1792 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1797 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1798 UINT16
const *glyphs
, UINT32 count
)
1800 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1805 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1806 UINT64 offset
, UINT64 size
)
1808 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1813 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1815 dwritefontface_reference_QueryInterface
,
1816 dwritefontface_reference_AddRef
,
1817 dwritefontface_reference_Release
,
1818 dwritefontface_reference_CreateFontFace
,
1819 dwritefontface_reference_CreateFontFaceWithSimulations
,
1820 dwritefontface_reference_Equals
,
1821 dwritefontface_reference_GetFontFaceIndex
,
1822 dwritefontface_reference_GetSimulations
,
1823 dwritefontface_reference_GetFontFile
,
1824 dwritefontface_reference_GetLocalFileSize
,
1825 dwritefontface_reference_GetFileSize
,
1826 dwritefontface_reference_GetFileTime
,
1827 dwritefontface_reference_GetLocality
,
1828 dwritefontface_reference_EnqueueFontDownloadRequest
,
1829 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1830 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1831 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1834 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1836 struct dwrite_font_data
*data
= font
->data
;
1837 struct fontface_desc desc
;
1838 struct list
*cached_list
;
1843 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1844 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1848 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1851 desc
.factory
= font
->family
->collection
->factory
;
1852 desc
.face_type
= data
->face_type
;
1853 desc
.files
= &data
->file
;
1854 desc
.files_number
= 1;
1855 desc
.index
= data
->face_index
;
1856 desc
.simulations
= data
->simulations
;
1857 desc
.font_data
= data
;
1858 hr
= create_fontface(&desc
, cached_list
, fontface
);
1860 IDWriteFontFileStream_Release(desc
.stream
);
1864 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1866 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1868 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1869 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1870 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1871 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1872 IsEqualIID(riid
, &IID_IUnknown
))
1875 IDWriteFont3_AddRef(iface
);
1879 WARN("%s not implemented.\n", debugstr_guid(riid
));
1882 return E_NOINTERFACE
;
1885 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1887 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1888 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
1890 TRACE("%p, refcount %d.\n", iface
, refcount
);
1895 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1897 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1898 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
1900 TRACE("%p, refcount %d.\n", iface
, refcount
);
1904 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
1905 release_font_data(font
->data
);
1912 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1914 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1916 TRACE("%p, %p.\n", iface
, family
);
1918 *family
= (IDWriteFontFamily
*)font
->family
;
1919 IDWriteFontFamily_AddRef(*family
);
1923 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1925 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1927 TRACE("%p.\n", iface
);
1929 return font
->data
->weight
;
1932 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1934 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1936 TRACE("%p.\n", iface
);
1938 return font
->data
->stretch
;
1941 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1943 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1945 TRACE("%p.\n", iface
);
1950 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1952 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1954 TRACE("%p.\n", iface
);
1956 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
1959 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1961 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1963 TRACE("%p, %p.\n", iface
, names
);
1965 return clone_localizedstrings(font
->data
->names
, names
);
1968 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1969 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1971 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1972 struct dwrite_font_data
*data
= font
->data
;
1973 struct file_stream_desc stream_desc
;
1975 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
1977 /* Stream will be created if necessary. */
1978 stream_desc
.stream
= NULL
;
1979 stream_desc
.face_index
= data
->face_index
;
1980 stream_desc
.face_type
= data
->face_type
;
1981 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
1984 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1986 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1988 TRACE("%p.\n", iface
);
1990 return font
->data
->simulations
;
1993 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1995 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1997 TRACE("%p, %p.\n", iface
, metrics
);
1999 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
2002 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
2005 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2006 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
2010 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2012 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2014 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2016 *exists
= dwritefont_has_character(font
, ch
);
2021 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2023 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2025 TRACE("%p, %p.\n", iface
, fontface
);
2027 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2030 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2032 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2034 TRACE("%p, %p.\n", iface
, metrics
);
2036 *metrics
= font
->data
->metrics
;
2039 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2041 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2043 TRACE("%p, %p.\n", iface
, panose
);
2045 *panose
= font
->data
->panose
;
2048 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2051 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2053 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2056 if (max_count
&& !ranges
)
2057 return E_INVALIDARG
;
2059 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2060 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2063 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2065 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2067 TRACE("%p.\n", iface
);
2069 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2072 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2074 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2076 TRACE("%p.\n", iface
);
2078 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2081 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2083 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2085 TRACE("%p, %p.\n", iface
, fontface
);
2087 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2090 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2092 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2094 TRACE("%p, %p.\n", iface
, other
);
2096 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2099 return font
->data
->face_index
== other_font
->data
->face_index
2100 && font
->data
->simulations
== other_font
->data
->simulations
2101 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2104 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2106 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2108 TRACE("%p, %p.\n", iface
, reference
);
2110 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2111 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2112 (IDWriteFontFaceReference1
**)reference
);
2115 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2117 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2119 TRACE("%p, %#x.\n", iface
, ch
);
2121 return dwritefont_has_character(font
, ch
);
2124 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2126 FIXME("%p: stub.\n", iface
);
2128 return DWRITE_LOCALITY_LOCAL
;
2131 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2132 dwritefont_QueryInterface
,
2135 dwritefont_GetFontFamily
,
2136 dwritefont_GetWeight
,
2137 dwritefont_GetStretch
,
2138 dwritefont_GetStyle
,
2139 dwritefont_IsSymbolFont
,
2140 dwritefont_GetFaceNames
,
2141 dwritefont_GetInformationalStrings
,
2142 dwritefont_GetSimulations
,
2143 dwritefont_GetMetrics
,
2144 dwritefont_HasCharacter
,
2145 dwritefont_CreateFontFace
,
2146 dwritefont1_GetMetrics
,
2147 dwritefont1_GetPanose
,
2148 dwritefont1_GetUnicodeRanges
,
2149 dwritefont1_IsMonospacedFont
,
2150 dwritefont2_IsColorFont
,
2151 dwritefont3_CreateFontFace
,
2153 dwritefont3_GetFontFaceReference
,
2154 dwritefont3_HasCharacter
,
2155 dwritefont3_GetLocality
2158 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2162 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2163 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2166 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2170 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2171 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2174 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2178 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2180 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2181 IDWriteFontFaceReference1_iface
);
2184 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2186 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2187 *lf
= font
->data
->lf
;
2190 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2192 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2196 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2198 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2199 *fontsig
= font
->data
->fontsig
;
2203 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2205 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2206 *fontsig
= fontface
->fontsig
;
2210 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2212 struct dwrite_font
*object
;
2216 if (!(object
= heap_alloc(sizeof(*object
))))
2217 return E_OUTOFMEMORY
;
2219 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2220 object
->refcount
= 1;
2221 object
->family
= family
;
2222 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2223 object
->data
= family
->data
->fonts
[index
];
2224 object
->style
= object
->data
->style
;
2225 addref_font_data(object
->data
);
2227 *font
= &object
->IDWriteFont3_iface
;
2232 /* IDWriteFontList2 */
2233 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2235 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2237 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2238 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2239 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2240 IsEqualIID(riid
, &IID_IUnknown
))
2243 IDWriteFontList2_AddRef(iface
);
2247 WARN("%s not implemented.\n", debugstr_guid(riid
));
2250 return E_NOINTERFACE
;
2253 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2255 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2256 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2258 TRACE("%p, refcount %u.\n", iface
, refcount
);
2263 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2265 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2266 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2268 TRACE("%p, refcount %u.\n", iface
, refcount
);
2274 for (i
= 0; i
< fontlist
->font_count
; i
++)
2275 release_font_data(fontlist
->fonts
[i
]);
2276 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2277 heap_free(fontlist
->fonts
);
2278 heap_free(fontlist
);
2284 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2286 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2287 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2290 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2292 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2294 TRACE("%p.\n", iface
);
2296 return fontlist
->font_count
;
2299 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2301 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2303 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2307 if (fontlist
->font_count
== 0)
2310 if (index
>= fontlist
->font_count
)
2311 return E_INVALIDARG
;
2313 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2316 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2318 FIXME("%p, %u.\n", iface
, index
);
2320 return DWRITE_LOCALITY_LOCAL
;
2323 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2325 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2327 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2331 if (fontlist
->font_count
== 0)
2334 if (index
>= fontlist
->font_count
)
2337 return create_font(fontlist
->family
, index
, font
);
2340 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2341 IDWriteFontFaceReference
**reference
)
2346 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2350 hr
= IDWriteFontList2_GetFont(iface
, index
, &font
);
2354 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2355 IDWriteFont3_Release(font
);
2360 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2362 FIXME("%p, %p.\n", iface
, fontset
);
2367 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2369 dwritefontlist_QueryInterface
,
2370 dwritefontlist_AddRef
,
2371 dwritefontlist_Release
,
2372 dwritefontlist_GetFontCollection
,
2373 dwritefontlist_GetFontCount
,
2374 dwritefontlist_GetFont
,
2375 dwritefontlist1_GetFontLocality
,
2376 dwritefontlist1_GetFont
,
2377 dwritefontlist1_GetFontFaceReference
,
2378 dwritefontlist2_GetFontSet
,
2381 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2383 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2385 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2387 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2388 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2389 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2390 IsEqualIID(riid
, &IID_IUnknown
))
2394 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2395 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2396 IsEqualIID(riid
, &IID_IDWriteFontList
))
2398 *obj
= &family
->IDWriteFontList2_iface
;
2402 WARN("%s not implemented.\n", debugstr_guid(riid
));
2404 return E_NOINTERFACE
;
2407 IUnknown_AddRef((IUnknown
*)*obj
);
2411 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2413 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2414 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2416 TRACE("%p, %u.\n", iface
, refcount
);
2421 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2423 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2424 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2426 TRACE("%p, %u.\n", iface
, refcount
);
2430 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2431 release_fontfamily_data(family
->data
);
2438 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2440 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2442 TRACE("%p, %p.\n", iface
, collection
);
2444 *collection
= (IDWriteFontCollection
*)family
->collection
;
2445 IDWriteFontCollection_AddRef(*collection
);
2449 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2451 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2453 TRACE("%p.\n", iface
);
2455 return family
->data
->count
;
2458 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2460 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2462 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2466 if (!family
->data
->count
)
2469 if (index
>= family
->data
->count
)
2470 return E_INVALIDARG
;
2472 return create_font(family
, index
, (IDWriteFont3
**)font
);
2475 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2477 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2479 TRACE("%p, %p.\n", iface
, names
);
2481 return clone_localizedstrings(family
->data
->familyname
, names
);
2484 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2485 const struct dwrite_font_propvec
*req
)
2487 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2488 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2489 FLOAT cur_req_prod
, next_req_prod
;
2491 if (next_to_req
< cur_to_req
)
2494 if (next_to_req
> cur_to_req
)
2497 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2498 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2500 if (next_req_prod
> cur_req_prod
)
2503 if (next_req_prod
< cur_req_prod
)
2506 if (next
->stretch
> cur
->stretch
)
2508 if (next
->stretch
< cur
->stretch
)
2511 if (next
->style
> cur
->style
)
2513 if (next
->style
< cur
->style
)
2516 if (next
->weight
> cur
->weight
)
2518 if (next
->weight
< cur
->weight
)
2521 /* full match, no reason to prefer new variant */
2525 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2526 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2528 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2529 struct dwrite_font_propvec req
;
2532 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2534 if (!family
->data
->count
)
2537 return DWRITE_E_NOFONT
;
2540 init_font_prop_vec(weight
, stretch
, style
, &req
);
2543 for (i
= 1; i
< family
->data
->count
; ++i
)
2545 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2549 return create_font(family
, match
, (IDWriteFont3
**)font
);
2552 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2554 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2556 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2559 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2561 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2564 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2566 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2571 for (j
= 0; j
< b
; j
++) {
2572 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2573 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2574 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2575 fonts
->fonts
[j
+1] = s
;
2586 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2587 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2589 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2590 matching_filter_func func
= NULL
;
2591 struct dwrite_font_propvec req
;
2592 struct dwrite_fontlist
*fonts
;
2595 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2599 fonts
= heap_alloc(sizeof(*fonts
));
2601 return E_OUTOFMEMORY
;
2603 /* Allocate as many as family has, not all of them will be necessary used. */
2604 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2605 if (!fonts
->fonts
) {
2607 return E_OUTOFMEMORY
;
2610 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2611 fonts
->refcount
= 1;
2612 fonts
->family
= family
;
2613 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2614 fonts
->font_count
= 0;
2616 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2617 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2618 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2619 func
= is_font_acceptable_for_normal
;
2621 else /* requested oblique or italic */ {
2622 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2623 func
= is_font_acceptable_for_oblique_italic
;
2626 for (i
= 0; i
< family
->data
->count
; ++i
)
2628 if (!func
|| func(family
->data
->fonts
[i
]))
2630 fonts
->fonts
[fonts
->font_count
] = family
->data
->fonts
[i
];
2631 addref_font_data(family
->data
->fonts
[i
]);
2632 fonts
->font_count
++;
2636 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2637 init_font_prop_vec(weight
, stretch
, style
, &req
);
2638 matchingfonts_sort(fonts
, &req
);
2640 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2644 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2646 FIXME("%p, %u.\n", iface
, index
);
2648 return DWRITE_LOCALITY_LOCAL
;
2651 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2653 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2655 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2659 if (!family
->data
->count
)
2662 if (index
>= family
->data
->count
)
2665 return create_font(family
, index
, font
);
2668 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2669 IDWriteFontFaceReference
**reference
)
2671 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2672 const struct dwrite_font_data
*font
;
2674 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2678 if (index
>= family
->data
->count
)
2681 font
= family
->data
->fonts
[index
];
2682 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2683 font
->file
, font
->face_index
, font
->simulations
, reference
);
2686 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2687 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2689 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2694 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2696 FIXME("%p, %p.\n", iface
, fontset
);
2701 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2703 dwritefontfamily_QueryInterface
,
2704 dwritefontfamily_AddRef
,
2705 dwritefontfamily_Release
,
2706 dwritefontfamily_GetFontCollection
,
2707 dwritefontfamily_GetFontCount
,
2708 dwritefontfamily_GetFont
,
2709 dwritefontfamily_GetFamilyNames
,
2710 dwritefontfamily_GetFirstMatchingFont
,
2711 dwritefontfamily_GetMatchingFonts
,
2712 dwritefontfamily1_GetFontLocality
,
2713 dwritefontfamily1_GetFont
,
2714 dwritefontfamily1_GetFontFaceReference
,
2715 dwritefontfamily2_GetMatchingFonts
,
2716 dwritefontfamily2_GetFontSet
,
2719 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2721 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2722 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2725 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2727 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2728 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2731 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2733 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2734 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2737 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2738 IDWriteFontCollection
**collection
)
2740 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2741 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2744 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2746 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2747 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2750 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2752 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2753 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2756 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2758 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2759 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2762 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2764 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2765 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2768 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2769 IDWriteFontFaceReference
**reference
)
2771 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2772 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2775 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2777 FIXME("%p, %p.\n", iface
, fontset
);
2782 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2784 dwritefontfamilylist_QueryInterface
,
2785 dwritefontfamilylist_AddRef
,
2786 dwritefontfamilylist_Release
,
2787 dwritefontfamilylist_GetFontCollection
,
2788 dwritefontfamilylist_GetFontCount
,
2789 dwritefontfamilylist_GetFont
,
2790 dwritefontfamilylist1_GetFontLocality
,
2791 dwritefontfamilylist1_GetFont
,
2792 dwritefontfamilylist1_GetFontFaceReference
,
2793 dwritefontfamilylist2_GetFontSet
,
2796 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2797 struct dwrite_fontfamily
**family
)
2799 struct dwrite_fontfamily
*object
;
2803 object
= heap_alloc(sizeof(*object
));
2805 return E_OUTOFMEMORY
;
2807 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2808 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2809 object
->refcount
= 1;
2810 object
->collection
= collection
;
2811 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2812 object
->data
= collection
->family_data
[index
];
2813 InterlockedIncrement(&object
->data
->refcount
);
2820 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2823 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2826 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2828 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2830 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2832 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2833 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2834 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2835 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2836 IsEqualIID(riid
, &IID_IUnknown
))
2839 IDWriteFontCollection3_AddRef(iface
);
2845 if (IsEqualIID(riid
, &IID_issystemcollection
))
2848 WARN("%s not implemented.\n", debugstr_guid(riid
));
2850 return E_NOINTERFACE
;
2853 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2855 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2857 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2858 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2859 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2860 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2861 IsEqualIID(riid
, &IID_IUnknown
))
2864 IDWriteFontCollection3_AddRef(iface
);
2868 WARN("%s not implemented.\n", debugstr_guid(riid
));
2872 return E_NOINTERFACE
;
2875 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2877 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2878 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2880 TRACE("%p, refcount %d.\n", collection
, refcount
);
2885 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2887 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2888 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2891 TRACE("%p, refcount %d.\n", iface
, refcount
);
2895 factory_detach_fontcollection(collection
->factory
, iface
);
2896 for (i
= 0; i
< collection
->count
; ++i
)
2897 release_fontfamily_data(collection
->family_data
[i
]);
2898 heap_free(collection
->family_data
);
2899 heap_free(collection
);
2905 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2907 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2909 TRACE("%p.\n", iface
);
2911 return collection
->count
;
2914 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2915 IDWriteFontFamily
**ret
)
2917 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2918 struct dwrite_fontfamily
*family
;
2921 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2925 if (index
>= collection
->count
)
2928 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2929 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2934 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2938 for (i
= 0; i
< collection
->count
; ++i
)
2940 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2941 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2944 for (j
= 0; j
< count
; j
++) {
2946 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
2947 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2955 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
2956 UINT32
*index
, BOOL
*exists
)
2958 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2960 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
2962 *index
= collection_find_family(collection
, name
);
2963 *exists
= *index
!= ~0u;
2967 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
2970 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2971 struct dwrite_fontfamily
*family
;
2972 BOOL found_font
= FALSE
;
2973 IDWriteFontFile
*file
;
2974 UINT32 face_index
, count
;
2978 TRACE("%p, %p, %p.\n", iface
, face
, font
);
2983 return E_INVALIDARG
;
2986 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
2989 face_index
= IDWriteFontFace_GetIndex(face
);
2992 for (i
= 0; i
< collection
->count
; ++i
)
2994 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
2996 for (j
= 0; j
< family_data
->count
; ++j
)
2998 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
3000 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
3009 IDWriteFontFile_Release(file
);
3012 return DWRITE_E_NOFONT
;
3014 hr
= create_fontfamily(collection
, i
, &family
);
3018 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3019 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3023 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3025 FIXME("%p, %p.\n", iface
, fontset
);
3030 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3031 IDWriteFontFamily1
**ret
)
3033 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3034 struct dwrite_fontfamily
*family
;
3037 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3041 if (index
>= collection
->count
)
3044 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3045 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3050 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3051 UINT32 index
, IDWriteFontFamily2
**ret
)
3053 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3054 struct dwrite_fontfamily
*family
;
3057 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3061 if (index
>= collection
->count
)
3064 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3065 *ret
= &family
->IDWriteFontFamily2_iface
;
3070 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3071 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3072 IDWriteFontList2
**fontlist
)
3074 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3079 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3081 FIXME("%p.\n", iface
);
3083 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3086 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3088 FIXME("%p, %p.\n", iface
, fontset
);
3093 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3095 FIXME("%p.\n", iface
);
3100 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3102 dwritefontcollection_QueryInterface
,
3103 dwritefontcollection_AddRef
,
3104 dwritefontcollection_Release
,
3105 dwritefontcollection_GetFontFamilyCount
,
3106 dwritefontcollection_GetFontFamily
,
3107 dwritefontcollection_FindFamilyName
,
3108 dwritefontcollection_GetFontFromFontFace
,
3109 dwritefontcollection1_GetFontSet
,
3110 dwritefontcollection1_GetFontFamily
,
3111 dwritefontcollection2_GetFontFamily
,
3112 dwritefontcollection2_GetMatchingFonts
,
3113 dwritefontcollection2_GetFontFamilyModel
,
3114 dwritefontcollection2_GetFontSet
,
3115 dwritefontcollection3_GetExpirationEvent
,
3118 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3120 dwritesystemfontcollection_QueryInterface
,
3121 dwritefontcollection_AddRef
,
3122 dwritefontcollection_Release
,
3123 dwritefontcollection_GetFontFamilyCount
,
3124 dwritefontcollection_GetFontFamily
,
3125 dwritefontcollection_FindFamilyName
,
3126 dwritefontcollection_GetFontFromFontFace
,
3127 dwritefontcollection1_GetFontSet
,
3128 dwritefontcollection1_GetFontFamily
,
3129 dwritefontcollection2_GetFontFamily
,
3130 dwritefontcollection2_GetMatchingFonts
,
3131 dwritefontcollection2_GetFontFamilyModel
,
3132 dwritefontcollection2_GetFontSet
,
3133 dwritefontcollection3_GetExpirationEvent
,
3136 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3138 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3139 sizeof(*family_data
->fonts
)))
3141 return E_OUTOFMEMORY
;
3144 family_data
->fonts
[family_data
->count
++] = font_data
;
3145 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3146 family_data
->has_normal_face
= 1;
3147 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3148 family_data
->has_oblique_face
= 1;
3150 family_data
->has_italic_face
= 1;
3154 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3155 struct dwrite_fontfamily_data
*family
)
3157 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3158 sizeof(*collection
->family_data
)))
3160 return E_OUTOFMEMORY
;
3163 collection
->family_data
[collection
->count
++] = family
;
3167 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3169 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3170 collection
->refcount
= 1;
3171 collection
->count
= 0;
3172 collection
->size
= 0;
3173 collection
->family_data
= NULL
;
3178 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3180 IDWriteFontFileLoader
*loader
;
3187 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3191 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3195 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3196 IDWriteFontFileLoader_Release(loader
);
3203 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3205 BOOL exists
= FALSE
;
3210 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3211 if (FAILED(hr
) || !exists
)
3214 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3217 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3221 while (isspaceW(*in
))
3225 if (!(len
= strlenW(in
)))
3228 while (isspaceW(in
[len
-1]))
3231 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3240 INT len
; /* token length */
3241 INT fulllen
; /* full length including following separators */
3244 static inline BOOL
is_name_separator_char(WCHAR ch
)
3246 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3249 struct name_pattern
{
3250 const WCHAR
*part1
; /* NULL indicates end of list */
3251 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3254 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3256 const struct name_pattern
*pattern
;
3257 struct name_token
*token
;
3260 while ((pattern
= &patterns
[i
++])->part1
) {
3261 int len_part1
= strlenW(pattern
->part1
);
3262 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3264 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3265 if (len_part2
== 0) {
3266 /* simple case with single part pattern */
3267 if (token
->len
!= len_part1
)
3270 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3271 if (match
) *match
= *token
;
3272 list_remove(&token
->entry
);
3278 struct name_token
*next_token
;
3279 struct list
*next_entry
;
3281 /* pattern parts are stored in reading order, tokens list is reversed */
3282 if (token
->len
< len_part2
)
3285 /* it's possible to have combined string as a token, like ExtraCondensed */
3286 if (token
->len
== len_part1
+ len_part2
) {
3287 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3290 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3293 /* combined string match */
3294 if (match
) *match
= *token
;
3295 list_remove(&token
->entry
);
3300 /* now it's only possible to have two tokens matched to respective pattern parts */
3301 if (token
->len
!= len_part2
)
3304 next_entry
= list_next(tokens
, &token
->entry
);
3306 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3307 if (next_token
->len
!= len_part1
)
3310 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3313 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3316 /* both parts matched, remove tokens */
3318 match
->ptr
= next_token
->ptr
;
3319 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3321 list_remove(&token
->entry
);
3322 list_remove(&next_token
->entry
);
3323 heap_free(next_token
);
3338 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3340 static const WCHAR itaW
[] = {'i','t','a',0};
3341 static const WCHAR italW
[] = {'i','t','a','l',0};
3342 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3343 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3345 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3346 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3347 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3348 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3350 static const struct name_pattern italic_patterns
[] = {
3359 static const struct name_pattern oblique_patterns
[] = {
3368 /* italic patterns first */
3369 if (match_pattern_list(tokens
, italic_patterns
, match
))
3370 return DWRITE_FONT_STYLE_ITALIC
;
3372 /* oblique patterns */
3373 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3374 return DWRITE_FONT_STYLE_OBLIQUE
;
3379 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3380 struct name_token
*match
)
3382 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3383 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3384 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3385 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3386 static const WCHAR wideW
[] = {'w','i','d','e',0};
3387 static const WCHAR condW
[] = {'c','o','n','d',0};
3389 static const struct name_pattern ultracondensed_patterns
[] = {
3390 { extraW
, compressedW
},
3391 { extW
, compressedW
},
3392 { ultraW
, compressedW
},
3393 { ultraW
, condensedW
},
3398 static const struct name_pattern extracondensed_patterns
[] = {
3400 { extraW
, condensedW
},
3401 { extW
, condensedW
},
3407 static const struct name_pattern semicondensed_patterns
[] = {
3410 { semiW
, condensedW
},
3415 static const struct name_pattern semiexpanded_patterns
[] = {
3417 { semiW
, expandedW
},
3418 { semiW
, extendedW
},
3422 static const struct name_pattern extraexpanded_patterns
[] = {
3423 { extraW
, expandedW
},
3424 { extW
, expandedW
},
3425 { extraW
, extendedW
},
3426 { extW
, extendedW
},
3430 static const struct name_pattern ultraexpanded_patterns
[] = {
3431 { ultraW
, expandedW
},
3432 { ultraW
, extendedW
},
3436 static const struct name_pattern condensed_patterns
[] = {
3442 static const struct name_pattern expanded_patterns
[] = {
3448 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3449 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3451 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3452 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3454 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3455 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3457 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3458 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3460 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3461 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3463 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3464 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3466 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3467 return DWRITE_FONT_STRETCH_CONDENSED
;
3469 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3470 return DWRITE_FONT_STRETCH_EXPANDED
;
3475 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3476 struct name_token
*match
)
3478 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3479 static const WCHAR nordW
[] = {'n','o','r','d',0};
3481 static const struct name_pattern thin_patterns
[] = {
3488 static const struct name_pattern extralight_patterns
[] = {
3495 static const struct name_pattern semilight_patterns
[] = {
3500 static const struct name_pattern demibold_patterns
[] = {
3506 static const struct name_pattern extrabold_patterns
[] = {
3513 static const struct name_pattern extrablack_patterns
[] = {
3520 static const struct name_pattern bold_patterns
[] = {
3525 static const struct name_pattern thin2_patterns
[] = {
3530 static const struct name_pattern light_patterns
[] = {
3535 static const struct name_pattern medium_patterns
[] = {
3540 static const struct name_pattern black_patterns
[] = {
3547 static const struct name_pattern demibold2_patterns
[] = {
3552 static const struct name_pattern extrabold2_patterns
[] = {
3557 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3558 matching pattern. */
3560 if (match_pattern_list(tokens
, thin_patterns
, match
))
3561 return DWRITE_FONT_WEIGHT_THIN
;
3563 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3564 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3566 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3567 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3569 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3570 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3572 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3573 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3575 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3576 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3578 if (match_pattern_list(tokens
, bold_patterns
, match
))
3579 return DWRITE_FONT_WEIGHT_BOLD
;
3581 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3582 return DWRITE_FONT_WEIGHT_THIN
;
3584 if (match_pattern_list(tokens
, light_patterns
, match
))
3585 return DWRITE_FONT_WEIGHT_LIGHT
;
3587 if (match_pattern_list(tokens
, medium_patterns
, match
))
3588 return DWRITE_FONT_WEIGHT_MEDIUM
;
3590 if (match_pattern_list(tokens
, black_patterns
, match
))
3591 return DWRITE_FONT_WEIGHT_BLACK
;
3593 if (match_pattern_list(tokens
, black_patterns
, match
))
3594 return DWRITE_FONT_WEIGHT_BLACK
;
3596 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3597 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3599 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3600 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3602 /* FIXME: use abbreviated names to extract weight */
3607 struct knownweight_entry
{
3609 DWRITE_FONT_WEIGHT weight
;
3612 static int compare_knownweights(const void *a
, const void* b
)
3614 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3615 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3618 if (target
> entry
->weight
)
3620 else if (target
< entry
->weight
)
3626 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3628 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3629 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3630 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3631 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3632 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3633 const struct knownweight_entry
*ptr
;
3635 static const struct knownweight_entry knownweights
[] = {
3636 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3637 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3638 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3639 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3640 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3641 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3642 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3643 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3644 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3645 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3648 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3649 compare_knownweights
);
3655 strcpyW(nameW
, ptr
->nameW
);
3659 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3661 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3662 strW
[name
->len
] = 0;
3665 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3666 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3668 static const WCHAR bookW
[] = {'B','o','o','k',0};
3669 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3670 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3671 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3672 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3674 static const WCHAR
*regular_patterns
[] = {
3683 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3687 len
= strlenW(facenameW
);
3689 /* remove rightmost regular variant from face name */
3690 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3691 int pattern_len
= strlenW(ptr
);
3694 if (pattern_len
> len
)
3697 src
= facenameW
+ len
- pattern_len
;
3698 while (src
>= facenameW
) {
3699 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3700 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3701 len
= strlenW(facenameW
);
3713 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3721 struct name_token
*token
= heap_alloc(sizeof(*token
));
3726 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3732 /* skip separators */
3733 while (is_name_separator_char(*ptr
)) {
3738 list_add_head(tokens
, &token
->entry
);
3742 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3744 struct name_token
*token
, *token2
;
3745 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3748 list_remove(&token
->entry
);
3750 /* don't include last separator */
3751 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3752 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3760 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3762 struct name_token stretch_name
, weight_name
, style_name
;
3763 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3764 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3765 const WCHAR
*regular_ptr
= NULL
;
3766 DWRITE_FONT_STRETCH stretch
;
3767 DWRITE_FONT_WEIGHT weight
;
3771 /* remove leading and trailing spaces from family and face name */
3772 trim_spaces(familyW
, familynameW
);
3773 len
= trim_spaces(faceW
, facenameW
);
3775 /* remove rightmost regular variant from face name */
3776 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3778 /* append face name to family name, FIXME check if face name is a substring of family name */
3780 strcatW(familynameW
, spaceW
);
3781 strcatW(familynameW
, facenameW
);
3784 /* tokenize with " .-_" */
3785 fontname_tokenize(&tokens
, familynameW
);
3787 /* extract and resolve style */
3788 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3790 /* extract stretch */
3791 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3793 /* extract weight */
3794 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3796 /* resolve weight */
3797 if (weight
!= font
->weight
) {
3798 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3799 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3800 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3801 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3802 !(abs(weight
- font
->weight
) <= 150 &&
3803 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3804 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3805 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3807 font
->weight
= weight
;
3811 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3812 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3813 stretch itself is normal (extracted stretch is never normal). */
3814 if (stretch
!= font
->stretch
) {
3815 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3816 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3817 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3819 font
->stretch
= stretch
;
3823 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3825 /* get final combined string from what's left in token list, list is released */
3826 fontname_tokens_to_str(&tokens
, finalW
);
3828 if (!strcmpW(familyW
, finalW
))
3831 /* construct face name */
3832 strcpyW(familyW
, finalW
);
3834 /* resolved weight name */
3835 if (weight_name
.ptr
)
3836 font_name_token_to_str(&weight_name
, weightW
);
3837 /* ignore normal weight */
3838 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3840 /* for known weight values use appropriate names */
3841 else if (is_known_weight_value(font
->weight
, weightW
)) {
3843 /* use Wnnn format as a fallback in case weight is not one of known values */
3845 static const WCHAR fmtW
[] = {'W','%','d',0};
3846 sprintfW(weightW
, fmtW
, font
->weight
);
3849 /* resolved stretch name */
3850 if (stretch_name
.ptr
)
3851 font_name_token_to_str(&stretch_name
, stretchW
);
3852 /* ignore normal stretch */
3853 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3855 /* use predefined stretch names */
3857 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3858 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3859 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3860 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3861 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3862 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3864 static const WCHAR
*stretchnamesW
[] = {
3865 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3870 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3876 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3879 /* resolved style name */
3881 font_name_token_to_str(&style_name
, styleW
);
3882 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3884 /* use predefined names */
3886 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3887 strcpyW(styleW
, italicW
);
3889 strcpyW(styleW
, obliqueW
);
3892 /* use Regular match if it was found initially */
3893 if (!*weightW
&& !*stretchW
&& !*styleW
)
3894 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3898 strcpyW(faceW
, stretchW
);
3901 strcatW(faceW
, spaceW
);
3902 strcatW(faceW
, weightW
);
3906 strcatW(faceW
, spaceW
);
3907 strcatW(faceW
, styleW
);
3911 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3915 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3917 static const float width_axis_values
[] =
3919 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3920 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
3921 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
3922 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
3923 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
3924 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
3925 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
3926 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
3927 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
3928 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
3931 struct file_stream_desc stream_desc
;
3932 struct dwrite_font_props props
;
3933 struct dwrite_font_data
*data
;
3934 WCHAR familyW
[255], faceW
[255];
3939 data
= heap_alloc_zero(sizeof(*data
));
3941 return E_OUTOFMEMORY
;
3944 data
->file
= desc
->files
[0];
3945 data
->face_index
= desc
->index
;
3946 data
->face_type
= desc
->face_type
;
3947 IDWriteFontFile_AddRef(data
->file
);
3949 stream_desc
.stream
= desc
->stream
;
3950 stream_desc
.face_type
= desc
->face_type
;
3951 stream_desc
.face_index
= desc
->index
;
3952 opentype_get_font_properties(&stream_desc
, &props
);
3953 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3954 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3956 /* get family name from font file */
3957 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
3959 WARN("unable to get family name from font\n");
3960 release_font_data(data
);
3964 data
->style
= props
.style
;
3965 data
->stretch
= props
.stretch
;
3966 data
->weight
= props
.weight
;
3967 data
->panose
= props
.panose
;
3968 data
->fontsig
= props
.fontsig
;
3969 data
->lf
= props
.lf
;
3970 data
->flags
= props
.flags
;
3972 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
3973 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
3974 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3975 set_en_localizedstring(data
->family_names
, familyW
);
3976 set_en_localizedstring(data
->names
, faceW
);
3979 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3981 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
3982 data
->axis
[0].value
= props
.weight
;
3983 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
3984 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
3985 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
3986 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
3992 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3993 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3995 struct dwrite_font_data
*data
;
3999 data
= heap_alloc_zero(sizeof(*data
));
4001 return E_OUTOFMEMORY
;
4005 data
->simulations
|= sim
;
4006 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
4007 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
4008 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4009 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4010 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4012 IDWriteFontFile_AddRef(data
->file
);
4013 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4015 create_localizedstrings(&data
->names
);
4016 add_localizedstring(data
->names
, enusW
, facenameW
);
4018 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4024 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4026 struct dwrite_fontfamily_data
*data
;
4028 data
= heap_alloc_zero(sizeof(*data
));
4030 return E_OUTOFMEMORY
;
4033 data
->familyname
= familyname
;
4034 IDWriteLocalizedStrings_AddRef(familyname
);
4041 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4043 size_t i
, j
, heaviest
;
4045 for (i
= 0; i
< family
->count
; ++i
)
4047 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4050 if (family
->fonts
[i
]->bold_sim_tested
)
4053 family
->fonts
[i
]->bold_sim_tested
= 1;
4054 for (j
= i
; j
< family
->count
; ++j
)
4056 if (family
->fonts
[j
]->bold_sim_tested
)
4059 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4060 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4061 if (family
->fonts
[j
]->weight
> weight
) {
4062 weight
= family
->fonts
[j
]->weight
;
4065 family
->fonts
[j
]->bold_sim_tested
= 1;
4069 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4070 static const struct name_pattern weightsim_patterns
[] = {
4085 WCHAR facenameW
[255], initialW
[255];
4086 struct dwrite_font_data
*boldface
;
4089 /* add Bold simulation based on heaviest face data */
4091 /* Simulated face name should only contain Bold as weight term,
4092 so remove existing regular and weight terms. */
4093 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4094 facename_remove_regular_term(initialW
, -1);
4096 /* remove current weight pattern */
4097 fontname_tokenize(&tokens
, initialW
);
4098 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4099 fontname_tokens_to_str(&tokens
, facenameW
);
4101 /* Bold suffix for new name */
4103 strcatW(facenameW
, spaceW
);
4104 strcatW(facenameW
, boldW
);
4106 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4107 boldface
->bold_sim_tested
= 1;
4108 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4109 fontfamily_add_font(family
, boldface
);
4115 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4119 for (i
= 0; i
< family
->count
; ++i
)
4121 UINT32 regular
= ~0u, oblique
= ~0u;
4122 struct dwrite_font_data
*obliqueface
;
4123 WCHAR facenameW
[255];
4125 if (family
->fonts
[i
]->oblique_sim_tested
)
4128 family
->fonts
[i
]->oblique_sim_tested
= 1;
4129 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4131 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4134 /* find regular style with same weight/stretch values */
4135 for (j
= i
; j
< family
->count
; ++j
)
4137 if (family
->fonts
[j
]->oblique_sim_tested
)
4140 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4141 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4143 family
->fonts
[j
]->oblique_sim_tested
= 1;
4144 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4147 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4151 if (regular
!= ~0u && oblique
!= ~0u)
4155 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4159 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4163 /* add oblique simulation based on this regular face */
4165 /* remove regular term if any, append 'Oblique' */
4166 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4167 facename_remove_regular_term(facenameW
, -1);
4170 strcatW(facenameW
, spaceW
);
4171 strcatW(facenameW
, obliqueW
);
4173 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4174 obliqueface
->oblique_sim_tested
= 1;
4175 obliqueface
->lf
.lfItalic
= 1;
4176 fontfamily_add_font(family
, obliqueface
);
4181 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4182 const WCHAR
*replacement_name
)
4184 UINT32 i
= collection_find_family(collection
, replacement_name
);
4185 struct dwrite_fontfamily_data
*target
;
4186 IDWriteLocalizedStrings
*strings
;
4189 /* replacement does not exist */
4193 hr
= create_localizedstrings(&strings
);
4197 /* add a new family with target name, reuse font data from replacement */
4198 add_localizedstring(strings
, enusW
, target_name
);
4199 hr
= init_fontfamily_data(strings
, &target
);
4201 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4204 for (i
= 0; i
< replacement
->count
; ++i
)
4206 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4207 addref_font_data(replacement
->fonts
[i
]);
4210 fontcollection_add_family(collection
, target
);
4211 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4212 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4214 IDWriteLocalizedStrings_Release(strings
);
4218 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4219 system font collections. */
4220 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4222 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4227 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4230 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4235 max_namelen
++; /* returned value doesn't include room for '\0' */
4236 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4237 data
= heap_alloc(max_datalen
);
4239 datalen
= max_datalen
;
4240 namelen
= max_namelen
;
4241 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4242 if (collection_find_family(collection
, name
) == ~0u) {
4243 if (type
== REG_MULTI_SZ
) {
4244 WCHAR
*replacement
= data
;
4245 while (*replacement
) {
4246 if (fontcollection_add_replacement(collection
, name
, replacement
))
4248 replacement
+= strlenW(replacement
) + 1;
4251 else if (type
== REG_SZ
)
4252 fontcollection_add_replacement(collection
, name
, data
);
4255 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4257 datalen
= max_datalen
;
4258 namelen
= max_namelen
;
4266 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4267 IDWriteFontCollection3
**ret
)
4269 struct fontfile_enum
{
4271 IDWriteFontFile
*file
;
4273 struct fontfile_enum
*fileenum
, *fileenum2
;
4274 struct dwrite_fontcollection
*collection
;
4275 struct list scannedfiles
;
4276 BOOL current
= FALSE
;
4282 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4283 if (!collection
) return E_OUTOFMEMORY
;
4285 hr
= init_font_collection(collection
, is_system
);
4287 heap_free(collection
);
4291 *ret
= &collection
->IDWriteFontCollection3_iface
;
4293 TRACE("building font collection:\n");
4295 list_init(&scannedfiles
);
4296 while (hr
== S_OK
) {
4297 DWRITE_FONT_FACE_TYPE face_type
;
4298 DWRITE_FONT_FILE_TYPE file_type
;
4299 BOOL supported
, same
= FALSE
;
4300 IDWriteFontFileStream
*stream
;
4301 IDWriteFontFile
*file
;
4305 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4306 if (FAILED(hr
) || !current
)
4309 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4313 /* check if we've scanned this file already */
4314 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4315 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4320 IDWriteFontFile_Release(file
);
4324 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4325 IDWriteFontFile_Release(file
);
4329 /* Unsupported formats are skipped. */
4330 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4331 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4332 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4333 IDWriteFontFileStream_Release(stream
);
4334 IDWriteFontFile_Release(file
);
4339 /* add to scanned list */
4340 fileenum
= heap_alloc(sizeof(*fileenum
));
4341 fileenum
->file
= file
;
4342 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4344 for (i
= 0; i
< face_count
; ++i
)
4346 struct dwrite_font_data
*font_data
;
4347 struct fontface_desc desc
;
4351 desc
.factory
= factory
;
4352 desc
.face_type
= face_type
;
4354 desc
.stream
= stream
;
4355 desc
.files_number
= 1;
4357 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4358 desc
.font_data
= NULL
;
4360 /* Allocate an initialize new font data structure. */
4361 hr
= init_font_data(&desc
, &font_data
);
4364 /* move to next one */
4369 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4371 /* ignore dot named faces */
4372 if (familyW
[0] == '.')
4374 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4375 release_font_data(font_data
);
4379 index
= collection_find_family(collection
, familyW
);
4381 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4383 struct dwrite_fontfamily_data
*family_data
;
4385 /* create and init new family */
4386 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4388 /* add font to family, family - to collection */
4389 hr
= fontfamily_add_font(family_data
, font_data
);
4391 hr
= fontcollection_add_family(collection
, family_data
);
4394 release_fontfamily_data(family_data
);
4402 IDWriteFontFileStream_Release(stream
);
4405 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4406 IDWriteFontFile_Release(fileenum
->file
);
4407 list_remove(&fileenum
->entry
);
4408 heap_free(fileenum
);
4411 for (i
= 0; i
< collection
->count
; ++i
)
4413 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4414 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4418 fontcollection_add_replacements(collection
);
4420 collection
->factory
= factory
;
4421 IDWriteFactory7_AddRef(factory
);
4426 struct system_fontfile_enumerator
4428 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4431 IDWriteFactory7
*factory
;
4436 DWORD filename_size
;
4439 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4441 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4444 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4446 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4447 IDWriteFontFileEnumerator_AddRef(iface
);
4452 WARN("%s not implemented.\n", debugstr_guid(riid
));
4456 return E_NOINTERFACE
;
4459 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4461 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4462 return InterlockedIncrement(&enumerator
->ref
);
4465 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4467 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4468 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
4472 IDWriteFactory7_Release(enumerator
->factory
);
4473 RegCloseKey(enumerator
->hkey
);
4474 heap_free(enumerator
->filename
);
4475 heap_free(enumerator
);
4481 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4485 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4486 if (!strchrW(filename
, '\\')) {
4487 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4488 WCHAR fullpathW
[MAX_PATH
];
4490 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4491 strcatW(fullpathW
, fontsW
);
4492 strcatW(fullpathW
, filename
);
4494 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4497 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4502 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4504 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4508 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4511 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4514 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4516 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4517 WCHAR name_buf
[256], *name
= name_buf
;
4518 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4523 enumerator
->index
++;
4525 /* iterate until we find next string value */
4528 name_count
= max_name_count
;
4529 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4531 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4532 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4533 if (r
== ERROR_MORE_DATA
) {
4534 if (name_count
>= max_name_count
) {
4535 if (name
!= name_buf
) heap_free(name
);
4536 max_name_count
*= 2;
4537 name
= heap_alloc(max_name_count
* sizeof(*name
));
4538 if (!name
) return E_OUTOFMEMORY
;
4540 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4541 heap_free(enumerator
->filename
);
4542 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4543 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4544 if (!enumerator
->filename
) {
4550 } while (r
== ERROR_MORE_DATA
);
4552 if (r
!= ERROR_SUCCESS
) {
4553 enumerator
->filename
[0] = 0;
4556 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4557 if (type
== REG_SZ
&& *name
!= '@') {
4561 enumerator
->index
++;
4563 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4566 if (name
!= name_buf
) heap_free(name
);
4570 static const IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4572 systemfontfileenumerator_QueryInterface
,
4573 systemfontfileenumerator_AddRef
,
4574 systemfontfileenumerator_Release
,
4575 systemfontfileenumerator_MoveNext
,
4576 systemfontfileenumerator_GetCurrentFontFile
4579 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4581 struct system_fontfile_enumerator
*enumerator
;
4582 static const WCHAR fontslistW
[] = {
4583 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4584 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4585 'F','o','n','t','s',0
4590 enumerator
= heap_alloc(sizeof(*enumerator
));
4592 return E_OUTOFMEMORY
;
4594 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4595 enumerator
->ref
= 1;
4596 enumerator
->factory
= factory
;
4597 enumerator
->index
= -1;
4598 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4599 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4600 if (!enumerator
->filename
) {
4601 heap_free(enumerator
);
4602 return E_OUTOFMEMORY
;
4605 IDWriteFactory7_AddRef(factory
);
4607 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4609 ERR("failed to open fonts list key\n");
4610 IDWriteFactory7_Release(factory
);
4611 heap_free(enumerator
->filename
);
4612 heap_free(enumerator
);
4616 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4621 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4623 IDWriteFontFileEnumerator
*enumerator
;
4628 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4632 TRACE("building system font collection for factory %p\n", factory
);
4633 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4634 IDWriteFontFileEnumerator_Release(enumerator
);
4638 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4639 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4641 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};
4642 static const WCHAR emptyW
[] = {0};
4643 struct dwrite_fontfamily_data
*family_data
;
4644 IDWriteLocalizedStrings
*names
;
4645 DWRITE_FONT_FACE_TYPE face_type
;
4646 DWRITE_FONT_FILE_TYPE file_type
;
4647 IDWriteFontFileStream
*stream
;
4648 IDWriteFontFile
*file
;
4649 UINT32 face_count
, i
;
4653 /* create font file from this path */
4654 hr
= create_local_file_reference(factory
, pathW
, &file
);
4658 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4659 IDWriteFontFile_Release(file
);
4663 /* Unsupported formats are skipped. */
4664 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4665 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4666 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4667 IDWriteFontFileStream_Release(stream
);
4668 IDWriteFontFile_Release(file
);
4672 /* create and init new family */
4674 /* Family names are added for non-specific locale, represented with empty string.
4675 Default family appears with empty family name. */
4676 create_localizedstrings(&names
);
4677 if (!strcmpiW(keynameW
, defaultfontW
))
4678 add_localizedstring(names
, emptyW
, emptyW
);
4680 add_localizedstring(names
, emptyW
, keynameW
);
4682 hr
= init_fontfamily_data(names
, &family_data
);
4683 IDWriteLocalizedStrings_Release(names
);
4685 IDWriteFontFile_Release(file
);
4689 /* fill with faces */
4690 for (i
= 0; i
< face_count
; i
++) {
4691 struct dwrite_font_data
*font_data
;
4692 struct fontface_desc desc
;
4694 /* alloc and init new font data structure */
4695 desc
.factory
= factory
;
4696 desc
.face_type
= face_type
;
4699 desc
.stream
= stream
;
4700 desc
.files_number
= 1;
4701 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4702 desc
.font_data
= NULL
;
4704 hr
= init_font_data(&desc
, &font_data
);
4708 /* add font to family */
4709 hr
= fontfamily_add_font(family_data
, font_data
);
4711 release_font_data(font_data
);
4714 /* add family to collection */
4715 hr
= fontcollection_add_family(collection
, family_data
);
4717 release_fontfamily_data(family_data
);
4718 IDWriteFontFileStream_Release(stream
);
4719 IDWriteFontFile_Release(file
);
4724 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4726 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4727 struct dwrite_fontcollection
*collection
;
4728 static const WCHAR emptyW
[] = {0};
4729 WCHAR eudckeypathW
[16];
4737 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4741 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4742 if (!collection
) return E_OUTOFMEMORY
;
4744 hr
= init_font_collection(collection
, FALSE
);
4746 heap_free(collection
);
4750 *ret
= &collection
->IDWriteFontCollection3_iface
;
4751 collection
->factory
= factory
;
4752 IDWriteFactory7_AddRef(factory
);
4754 /* return empty collection if EUDC fonts are not configured */
4755 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4756 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4759 retval
= ERROR_SUCCESS
;
4761 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4762 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4763 DWORD type
, path_len
, name_len
;
4765 path_len
= ARRAY_SIZE(pathW
);
4766 name_len
= ARRAY_SIZE(keynameW
);
4767 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4768 if (retval
|| type
!= REG_SZ
)
4771 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4773 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4775 RegCloseKey(eudckey
);
4777 /* try to add global default if not defined for specific codepage */
4779 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4781 if (FAILED(hr
) || !exists
) {
4782 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4783 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4785 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4788 /* EUDC collection offers simulated faces too */
4789 for (i
= 0; i
< collection
->count
; ++i
)
4791 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4792 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4798 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4800 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
4802 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4805 IDWriteFontFile_AddRef(iface
);
4809 WARN("%s not implemented.\n", debugstr_guid(riid
));
4812 return E_NOINTERFACE
;
4815 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4817 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4818 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
4820 TRACE("%p, refcount %d.\n", iface
, refcount
);
4825 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4827 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4828 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
4830 TRACE("%p, refcount %d.\n", iface
, refcount
);
4834 IDWriteFontFileLoader_Release(file
->loader
);
4836 IDWriteFontFileStream_Release(file
->stream
);
4837 heap_free(file
->reference_key
);
4844 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
4846 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4848 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
4850 *key
= file
->reference_key
;
4851 *key_size
= file
->key_size
;
4856 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
4858 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4860 TRACE("%p, %p.\n", iface
, loader
);
4862 *loader
= file
->loader
;
4863 IDWriteFontFileLoader_AddRef(*loader
);
4868 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4869 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4871 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4872 IDWriteFontFileStream
*stream
;
4875 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
4877 *is_supported
= FALSE
;
4878 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4880 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4883 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
4887 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4889 /* TODO: Further Analysis */
4890 IDWriteFontFileStream_Release(stream
);
4894 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
4896 dwritefontfile_QueryInterface
,
4897 dwritefontfile_AddRef
,
4898 dwritefontfile_Release
,
4899 dwritefontfile_GetReferenceKey
,
4900 dwritefontfile_GetLoader
,
4901 dwritefontfile_Analyze
,
4904 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4905 IDWriteFontFile
**ret
)
4907 struct dwrite_fontfile
*file
;
4912 file
= heap_alloc(sizeof(*file
));
4913 key
= heap_alloc(key_size
);
4914 if (!file
|| !key
) {
4917 return E_OUTOFMEMORY
;
4920 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4922 IDWriteFontFileLoader_AddRef(loader
);
4923 file
->loader
= loader
;
4924 file
->stream
= NULL
;
4925 file
->reference_key
= key
;
4926 memcpy(file
->reference_key
, reference_key
, key_size
);
4927 file
->key_size
= key_size
;
4929 *ret
= &file
->IDWriteFontFile_iface
;
4934 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
4936 struct file_stream_desc stream_desc
;
4937 struct dwrite_font_data
*font_data
;
4938 struct dwrite_fontface
*fontface
;
4944 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4946 return E_OUTOFMEMORY
;
4948 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4949 if (!fontface
->files
) {
4950 heap_free(fontface
);
4951 return E_OUTOFMEMORY
;
4954 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
4955 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
4956 fontface
->refcount
= 1;
4957 fontface
->type
= desc
->face_type
;
4958 fontface
->file_count
= desc
->files_number
;
4959 fontface
->vdmx
.exists
= TRUE
;
4960 fontface
->gasp
.exists
= TRUE
;
4961 fontface
->cpal
.exists
= TRUE
;
4962 fontface
->colr
.exists
= TRUE
;
4963 fontface
->index
= desc
->index
;
4964 fontface
->simulations
= desc
->simulations
;
4965 fontface
->factory
= desc
->factory
;
4966 IDWriteFactory7_AddRef(fontface
->factory
);
4968 for (i
= 0; i
< fontface
->file_count
; i
++) {
4969 fontface
->files
[i
] = desc
->files
[i
];
4970 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4972 fontface
->stream
= desc
->stream
;
4973 IDWriteFontFileStream_AddRef(fontface
->stream
);
4975 stream_desc
.stream
= fontface
->stream
;
4976 stream_desc
.face_type
= desc
->face_type
;
4977 stream_desc
.face_index
= desc
->index
;
4978 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4979 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
4980 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4981 /* TODO: test what happens if caret is already slanted */
4982 if (fontface
->caret
.slopeRise
== 1) {
4983 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4984 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4988 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace5_iface
))
4989 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4990 if (opentype_has_vertical_variants(fontface
))
4991 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4992 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
4994 /* Font properties are reused from font object when 'normal' face creation path is used:
4995 collection -> family -> matching font -> fontface.
4997 If face is created directly from factory we have to go through properties resolution.
4999 if (desc
->font_data
)
5001 font_data
= desc
->font_data
;
5002 addref_font_data(font_data
);
5006 hr
= init_font_data(desc
, &font_data
);
5009 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5014 fontface
->weight
= font_data
->weight
;
5015 fontface
->style
= font_data
->style
;
5016 fontface
->stretch
= font_data
->stretch
;
5017 fontface
->panose
= font_data
->panose
;
5018 fontface
->fontsig
= font_data
->fontsig
;
5019 fontface
->lf
= font_data
->lf
;
5020 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5021 fontface
->names
= font_data
->names
;
5022 if (fontface
->names
)
5023 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5024 fontface
->family_names
= font_data
->family_names
;
5025 if (fontface
->family_names
)
5026 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5027 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5028 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5030 if (fontface
->info_strings
[i
])
5031 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5033 fontface
->cmap
.stream
= fontface
->stream
;
5034 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5035 release_font_data(font_data
);
5037 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5039 *ret
= &fontface
->IDWriteFontFace5_iface
;
5044 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5051 struct local_cached_stream
5054 IDWriteFontFileStream
*stream
;
5055 struct local_refkey
*key
;
5059 struct dwrite_localfontfilestream
5061 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5064 struct local_cached_stream
*entry
;
5065 const void *file_ptr
;
5069 struct dwrite_localfontfileloader
5071 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5074 struct list streams
;
5075 CRITICAL_SECTION cs
;
5078 static struct dwrite_localfontfileloader local_fontfile_loader
;
5080 struct dwrite_inmemory_stream_data
5088 struct dwrite_inmemory_filestream
5090 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5093 struct dwrite_inmemory_stream_data
*data
;
5096 struct dwrite_inmemory_fileloader
5098 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5101 struct dwrite_inmemory_stream_data
**streams
;
5106 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5108 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5111 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5113 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5116 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5118 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5121 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5123 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5126 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5128 if (InterlockedDecrement(&stream
->ref
) == 0) {
5130 IUnknown_Release(stream
->owner
);
5132 heap_free(stream
->data
);
5137 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5139 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5141 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5143 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5144 IsEqualIID(riid
, &IID_IUnknown
))
5147 if (InterlockedIncrement(&stream
->refcount
) == 1)
5149 InterlockedDecrement(&stream
->refcount
);
5156 WARN("%s not implemented.\n", debugstr_guid(riid
));
5159 return E_NOINTERFACE
;
5162 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5164 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5165 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5167 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5172 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5174 list_remove(&stream
->entry
);
5175 heap_free(stream
->key
);
5179 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5181 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5182 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5184 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5188 UnmapViewOfFile(stream
->file_ptr
);
5190 EnterCriticalSection(&local_fontfile_loader
.cs
);
5191 release_cached_stream(stream
->entry
);
5192 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5200 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5201 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5203 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5205 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5206 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5208 *fragment_context
= NULL
;
5210 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5212 *fragment_start
= NULL
;
5216 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5220 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5222 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5225 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5227 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5229 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5231 *size
= stream
->size
;
5235 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5237 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5240 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5242 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5243 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5244 *last_writetime
= li
.QuadPart
;
5249 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5251 localfontfilestream_QueryInterface
,
5252 localfontfilestream_AddRef
,
5253 localfontfilestream_Release
,
5254 localfontfilestream_ReadFileFragment
,
5255 localfontfilestream_ReleaseFileFragment
,
5256 localfontfilestream_GetFileSize
,
5257 localfontfilestream_GetLastWriteTime
5260 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5261 IDWriteFontFileStream
**ret
)
5263 struct dwrite_localfontfilestream
*object
;
5267 if (!(object
= heap_alloc(sizeof(*object
))))
5268 return E_OUTOFMEMORY
;
5270 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5271 object
->refcount
= 1;
5273 object
->file_ptr
= file_ptr
;
5274 object
->size
= size
;
5275 object
->entry
= entry
;
5277 *ret
= &object
->IDWriteFontFileStream_iface
;
5282 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5284 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5286 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5287 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5288 IsEqualIID(riid
, &IID_IUnknown
))
5291 IDWriteLocalFontFileLoader_AddRef(iface
);
5295 WARN("%s not implemented.\n", debugstr_guid(riid
));
5298 return E_NOINTERFACE
;
5301 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5303 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5304 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5306 TRACE("%p, refcount %d.\n", iface
, refcount
);
5311 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5313 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5314 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5316 TRACE("%p, refcount %d.\n", iface
, refcount
);
5321 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5323 const struct local_refkey
*refkey
= key
;
5324 struct local_cached_stream
*stream
;
5325 IDWriteFontFileStream
*filestream
;
5326 HANDLE file
, mapping
;
5333 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5334 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5335 if (file
== INVALID_HANDLE_VALUE
) {
5336 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5340 GetFileSizeEx(file
, &size
);
5341 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5346 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5347 CloseHandle(mapping
);
5349 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5353 stream
= heap_alloc(sizeof(*stream
));
5355 UnmapViewOfFile(file_ptr
);
5356 return E_OUTOFMEMORY
;
5359 stream
->key
= heap_alloc(key_size
);
5361 UnmapViewOfFile(file_ptr
);
5363 return E_OUTOFMEMORY
;
5366 stream
->key_size
= key_size
;
5367 memcpy(stream
->key
, key
, key_size
);
5369 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5371 UnmapViewOfFile(file_ptr
);
5372 heap_free(stream
->key
);
5377 stream
->stream
= filestream
;
5384 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5385 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5387 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5388 struct local_cached_stream
*stream
;
5391 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5393 EnterCriticalSection(&loader
->cs
);
5397 /* search cache first */
5398 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5400 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5401 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5406 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5408 list_add_head(&loader
->streams
, &stream
->entry
);
5409 *ret
= stream
->stream
;
5412 LeaveCriticalSection(&loader
->cs
);
5417 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5418 UINT32 key_size
, UINT32
*length
)
5420 const struct local_refkey
*refkey
= key
;
5422 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5424 *length
= strlenW(refkey
->name
);
5428 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5429 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5431 const struct local_refkey
*refkey
= key
;
5433 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5435 if (length
< strlenW(refkey
->name
))
5436 return E_INVALIDARG
;
5438 strcpyW(path
, refkey
->name
);
5442 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5443 UINT32 key_size
, FILETIME
*writetime
)
5445 const struct local_refkey
*refkey
= key
;
5447 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5449 *writetime
= refkey
->writetime
;
5453 static const IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5455 localfontfileloader_QueryInterface
,
5456 localfontfileloader_AddRef
,
5457 localfontfileloader_Release
,
5458 localfontfileloader_CreateStreamFromKey
,
5459 localfontfileloader_GetFilePathLengthFromKey
,
5460 localfontfileloader_GetFilePathFromKey
,
5461 localfontfileloader_GetLastWriteTimeFromKey
5464 void init_local_fontfile_loader(void)
5466 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5467 local_fontfile_loader
.refcount
= 1;
5468 list_init(&local_fontfile_loader
.streams
);
5469 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5470 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5473 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5475 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5478 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5480 struct local_refkey
*refkey
;
5483 return E_INVALIDARG
;
5485 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5488 refkey
= heap_alloc(*size
);
5490 return E_OUTOFMEMORY
;
5493 refkey
->writetime
= *writetime
;
5495 WIN32_FILE_ATTRIBUTE_DATA info
;
5497 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5498 refkey
->writetime
= info
.ftLastWriteTime
;
5500 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5502 strcpyW(refkey
->name
, path
);
5509 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5511 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5513 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5514 IsEqualIID(riid
, &IID_IUnknown
))
5517 IDWriteGlyphRunAnalysis_AddRef(iface
);
5521 WARN("%s not implemented.\n", debugstr_guid(riid
));
5524 return E_NOINTERFACE
;
5527 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5529 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5530 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
5532 TRACE("%p, refcount %d.\n", iface
, refcount
);
5537 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5539 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5540 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
5542 TRACE("%p, refcount %d.\n", iface
, refcount
);
5546 if (analysis
->run
.fontFace
)
5547 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5548 heap_free(analysis
->glyphs
);
5549 heap_free(analysis
->origins
);
5550 heap_free(analysis
->bitmap
);
5551 heap_free(analysis
);
5557 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5561 case DWRITE_RENDERING_MODE1_NATURAL
:
5562 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5563 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5570 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5572 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5575 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5577 struct dwrite_glyphbitmap glyph_bitmap
;
5578 IDWriteFontFace4
*fontface
;
5582 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5583 *bounds
= analysis
->bounds
;
5587 if (analysis
->run
.isSideways
)
5588 FIXME("sideways runs are not supported.\n");
5590 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5592 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5594 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5595 glyph_bitmap
.fontface
= fontface
;
5596 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5597 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5598 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5599 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5600 glyph_bitmap
.m
= &analysis
->m
;
5602 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5603 RECT
*bbox
= &glyph_bitmap
.bbox
;
5606 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5607 freetype_get_glyph_bbox(&glyph_bitmap
);
5609 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5610 (bbox
->bottom
- bbox
->top
);
5611 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5612 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5614 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5615 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5618 IDWriteFontFace4_Release(fontface
);
5620 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5621 *bounds
= analysis
->bounds
;
5624 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
5625 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5627 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5629 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
5631 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5632 SetRectEmpty(bounds
);
5633 return E_INVALIDARG
;
5636 if (type
!= analysis
->texture_type
)
5638 SetRectEmpty(bounds
);
5642 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
5646 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5648 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5649 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5650 (runbounds
->left
- bounds
->left
) * 3;
5652 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5653 runbounds
->left
- bounds
->left
;
5656 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5658 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5659 struct dwrite_glyphbitmap glyph_bitmap
;
5660 IDWriteFontFace4
*fontface
;
5661 D2D_POINT_2F origin
;
5666 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5668 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5672 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5673 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5675 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5676 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5677 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5678 IDWriteFontFace4_Release(fontface
);
5679 return E_OUTOFMEMORY
;
5682 origin
.x
= origin
.y
= 0.0f
;
5684 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5685 glyph_bitmap
.fontface
= fontface
;
5686 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5687 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5688 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5689 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5690 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5691 glyph_bitmap
.m
= &analysis
->m
;
5692 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5693 IDWriteFontFace4_Release(fontface
);
5694 return E_OUTOFMEMORY
;
5697 bbox
= &glyph_bitmap
.bbox
;
5699 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5700 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5701 int x
, y
, width
, height
;
5704 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5705 freetype_get_glyph_bbox(&glyph_bitmap
);
5707 if (IsRectEmpty(bbox
))
5710 width
= bbox
->right
- bbox
->left
;
5711 height
= bbox
->bottom
- bbox
->top
;
5713 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5714 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5715 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5717 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5719 /* blit to analysis bitmap */
5720 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5723 /* convert 1bpp to 8bpp/24bpp */
5724 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5725 for (y
= 0; y
< height
; y
++) {
5726 for (x
= 0; x
< width
; x
++)
5727 if (src
[x
/ 8] & masks
[x
% 8])
5728 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5729 src
+= glyph_bitmap
.pitch
;
5730 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5734 for (y
= 0; y
< height
; y
++) {
5735 for (x
= 0; x
< width
; x
++)
5736 if (src
[x
/ 8] & masks
[x
% 8])
5737 dst
[x
] = DWRITE_ALPHA_MAX
;
5738 src
+= glyph_bitmap
.pitch
;
5739 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5744 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5745 for (y
= 0; y
< height
; y
++) {
5746 for (x
= 0; x
< width
; x
++)
5747 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5748 src
+= glyph_bitmap
.pitch
;
5749 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5753 for (y
= 0; y
< height
; y
++) {
5754 for (x
= 0; x
< width
; x
++)
5756 src
+= glyph_bitmap
.pitch
;
5757 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5762 heap_free(glyph_bitmap
.buf
);
5764 IDWriteFontFace4_Release(fontface
);
5766 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5768 /* we don't need this anymore */
5769 heap_free(analysis
->glyphs
);
5770 heap_free(analysis
->origins
);
5771 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5773 analysis
->glyphs
= NULL
;
5774 analysis
->origins
= NULL
;
5775 analysis
->run
.glyphIndices
= NULL
;
5776 analysis
->run
.fontFace
= NULL
;
5781 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5782 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5784 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5788 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5790 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5791 return E_INVALIDARG
;
5793 /* make sure buffer is large enough for requested texture type */
5794 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5795 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5798 if (size
< required
)
5799 return E_NOT_SUFFICIENT_BUFFER
;
5801 /* validate requested texture type */
5802 if (analysis
->texture_type
!= type
)
5803 return DWRITE_E_UNSUPPORTEDOPERATION
;
5805 memset(bitmap
, 0, size
);
5806 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
5807 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
5809 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5810 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
5811 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5812 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5816 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
5820 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
5824 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
5825 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5827 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5828 memcpy(dst
, src
, draw_width
);
5837 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5838 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5840 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5842 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
5845 return E_INVALIDARG
;
5847 switch (analysis
->rendering_mode
)
5849 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5850 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5853 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5854 *gamma
= (FLOAT
)value
/ 1000.0f
;
5856 *cleartypelevel
= 1.0f
;
5859 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5860 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5862 case DWRITE_RENDERING_MODE1_ALIASED
:
5863 case DWRITE_RENDERING_MODE1_NATURAL
:
5864 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5865 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5866 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5867 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5876 static const IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
5878 glyphrunanalysis_QueryInterface
,
5879 glyphrunanalysis_AddRef
,
5880 glyphrunanalysis_Release
,
5881 glyphrunanalysis_GetAlphaTextureBounds
,
5882 glyphrunanalysis_CreateAlphaTexture
,
5883 glyphrunanalysis_GetAlphaBlendParams
5886 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5889 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5890 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5894 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5895 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5897 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5901 FIXME("Sideways mode is not supported.\n");
5903 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5905 switch (measuring_mode
)
5907 case DWRITE_MEASURING_MODE_NATURAL
:
5908 return (float)advance
* emsize
/ (float)upem
;
5909 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5910 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5911 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5913 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5918 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5920 struct dwrite_glyphrunanalysis
*analysis
;
5921 struct dwrite_fontface
*fontface
;
5922 D2D_POINT_2F origin
;
5928 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5929 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5930 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5931 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5932 return E_INVALIDARG
;
5934 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5935 return E_INVALIDARG
;
5937 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5938 return E_INVALIDARG
;
5940 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5941 return E_INVALIDARG
;
5943 analysis
= heap_alloc_zero(sizeof(*analysis
));
5945 return E_OUTOFMEMORY
;
5947 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5948 analysis
->refcount
= 1;
5949 analysis
->rendering_mode
= desc
->rendering_mode
;
5951 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5952 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5953 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5955 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5957 analysis
->run
= *desc
->run
;
5958 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5959 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
5960 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
5962 if (!analysis
->glyphs
|| !analysis
->origins
) {
5963 heap_free(analysis
->glyphs
);
5964 heap_free(analysis
->origins
);
5966 analysis
->glyphs
= NULL
;
5967 analysis
->origins
= NULL
;
5969 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5970 return E_OUTOFMEMORY
;
5973 /* check if transform is usable */
5974 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5975 analysis
->m
= *desc
->transform
;
5976 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5979 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5981 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5983 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5985 fontface
= unsafe_impl_from_IDWriteFontFace(desc
->run
->fontFace
);
5987 origin
.x
= desc
->origin
.x
;
5988 origin
.y
= desc
->origin
.y
;
5989 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
5993 /* Use nominal advances if not provided by caller. */
5994 if (desc
->run
->glyphAdvances
)
5995 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
];
5997 advance
= rtl_factor
* fontface_get_scaled_design_advance(fontface
, desc
->measuring_mode
,
5998 desc
->run
->fontEmSize
, 1.0f
, desc
->transform
, desc
->run
->glyphIndices
[i
], desc
->run
->isSideways
);
6000 analysis
->origins
[i
] = origin
;
6001 if (desc
->run
->bidiLevel
& 1)
6003 if (desc
->run
->isSideways
)
6004 analysis
->origins
[i
].y
+= advance
;
6006 analysis
->origins
[i
].x
+= advance
;
6009 /* Offsets are optional, appled to pre-transformed origin. */
6010 if (desc
->run
->glyphOffsets
) {
6011 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
;
6012 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
;
6014 if (desc
->run
->isSideways
) {
6015 analysis
->origins
[i
].x
+= ascenderoffset
;
6016 analysis
->origins
[i
].y
+= advanceoffset
;
6019 analysis
->origins
[i
].x
+= advanceoffset
;
6020 analysis
->origins
[i
].y
+= ascenderoffset
;
6024 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6025 transform_point(analysis
->origins
+ i
, &analysis
->m
);
6027 if (desc
->run
->isSideways
)
6028 origin
.y
+= advance
;
6030 origin
.x
+= advance
;
6033 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6037 /* IDWriteColorGlyphRunEnumerator1 */
6038 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6040 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6042 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6043 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6044 IsEqualIID(riid
, &IID_IUnknown
))
6047 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6051 WARN("%s not implemented.\n", debugstr_guid(riid
));
6054 return E_NOINTERFACE
;
6057 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6059 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6060 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6062 TRACE("%p, refcount %u.\n", iface
, refcount
);
6067 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6069 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6070 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6072 TRACE("%p, refcount %u.\n", iface
, refcount
);
6076 heap_free(glyphenum
->advances
);
6077 heap_free(glyphenum
->color_advances
);
6078 heap_free(glyphenum
->offsets
);
6079 heap_free(glyphenum
->color_offsets
);
6080 heap_free(glyphenum
->glyphindices
);
6081 heap_free(glyphenum
->glyphs
);
6082 if (glyphenum
->colr
.context
)
6083 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6084 IDWriteFontFace5_Release(glyphenum
->fontface
);
6085 heap_free(glyphenum
);
6091 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6093 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6094 FLOAT origin
= 0.0f
;
6100 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6104 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6106 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6107 FLOAT advance_adj
= 0.0f
;
6108 BOOL got_palette_index
;
6111 /* start with regular glyphs */
6112 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6113 UINT32 first_glyph
= 0;
6115 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6116 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6117 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6118 first_glyph
= min(first_glyph
, g
);
6121 glyphenum
->glyphindices
[g
] = 1;
6122 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6123 if (glyphenum
->color_offsets
)
6124 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6127 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6128 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6129 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6130 colorrun
->paletteIndex
= 0xffff;
6131 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6132 glyphenum
->has_regular_glyphs
= FALSE
;
6136 colorrun
->glyphRun
.glyphCount
= 0;
6137 got_palette_index
= FALSE
;
6141 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6143 glyphenum
->glyphindices
[g
] = 1;
6145 /* all glyph layers were returned */
6146 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6147 advance_adj
+= glyphenum
->advances
[g
];
6151 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6152 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6153 if (!got_palette_index
) {
6154 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6155 /* use foreground color or request one from the font */
6156 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6157 if (colorrun
->paletteIndex
!= 0xffff)
6159 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6160 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6162 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6163 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6165 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6166 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6167 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6168 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6169 got_palette_index
= TRUE
;
6172 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6173 /* offsets are relative to glyph origin, nothing to fix up */
6174 if (glyphenum
->color_offsets
)
6175 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6176 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6178 glyphenum
->color_advances
[index
-1] += advance_adj
;
6179 colorrun
->glyphRun
.glyphCount
++;
6183 advance_adj
+= glyphenum
->advances
[g
];
6186 /* reset last advance */
6187 if (colorrun
->glyphRun
.glyphCount
)
6188 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6190 return colorrun
->glyphRun
.glyphCount
> 0;
6193 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6195 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6197 TRACE("%p, %p.\n", iface
, has_run
);
6201 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6202 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6204 if (colorglyphenum_build_color_run(glyphenum
))
6207 glyphenum
->current_layer
++;
6210 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6215 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6216 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6218 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6221 return E_NOT_VALID_STATE
;
6224 *run
= &glyphenum
->colorrun
;
6228 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6229 DWRITE_COLOR_GLYPH_RUN
const **run
)
6231 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6233 TRACE("%p, %p.\n", iface
, run
);
6235 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6238 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6239 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6241 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6243 TRACE("%p, %p.\n", iface
, run
);
6245 return colorglyphenum_get_current_run(glyphenum
, run
);
6248 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6250 colorglyphenum_QueryInterface
,
6251 colorglyphenum_AddRef
,
6252 colorglyphenum_Release
,
6253 colorglyphenum_MoveNext
,
6254 colorglyphenum_GetCurrentRun
,
6255 colorglyphenum1_GetCurrentRun
,
6258 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6259 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6260 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6262 struct dwrite_colorglyphenum
*colorglyphenum
;
6263 BOOL colorfont
, has_colored_glyph
;
6264 struct dwrite_fontface
*fontface
;
6269 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6271 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6272 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6274 return DWRITE_E_NOCOLOR
;
6276 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6277 if (!colorglyphenum
)
6278 return E_OUTOFMEMORY
;
6280 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6281 colorglyphenum
->refcount
= 1;
6282 colorglyphenum
->origin_x
= originX
;
6283 colorglyphenum
->origin_y
= originY
;
6284 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6285 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6286 colorglyphenum
->glyphs
= NULL
;
6287 colorglyphenum
->run
= *run
;
6288 colorglyphenum
->run
.glyphIndices
= NULL
;
6289 colorglyphenum
->run
.glyphAdvances
= NULL
;
6290 colorglyphenum
->run
.glyphOffsets
= NULL
;
6291 colorglyphenum
->palette
= palette
;
6292 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6293 colorglyphenum
->colr
.exists
= TRUE
;
6294 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6295 colorglyphenum
->current_layer
= 0;
6296 colorglyphenum
->max_layer_num
= 0;
6298 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6300 has_colored_glyph
= FALSE
;
6301 colorglyphenum
->has_regular_glyphs
= FALSE
;
6302 for (i
= 0; i
< run
->glyphCount
; i
++) {
6303 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6304 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6305 has_colored_glyph
= TRUE
;
6307 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6308 colorglyphenum
->has_regular_glyphs
= TRUE
;
6311 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6312 is supposed to proceed normally, like if font had no color info at all. */
6313 if (!has_colored_glyph
) {
6314 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6315 return DWRITE_E_NOCOLOR
;
6318 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6319 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6320 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6321 if (run
->glyphOffsets
) {
6322 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6323 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6324 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6327 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6328 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6329 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6330 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6331 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6332 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6333 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6334 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6336 if (run
->glyphAdvances
)
6337 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6340 for (i
= 0; i
< run
->glyphCount
; ++i
)
6341 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6342 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6345 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6350 /* IDWriteFontFaceReference */
6351 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6353 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6355 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6356 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6357 IsEqualIID(riid
, &IID_IUnknown
))
6360 IDWriteFontFaceReference1_AddRef(iface
);
6364 WARN("%s not implemented.\n", debugstr_guid(riid
));
6368 return E_NOINTERFACE
;
6371 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6373 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6374 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6376 TRACE("%p, refcount %u.\n", iface
, refcount
);
6381 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6383 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6384 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6386 TRACE("%p, refcount %u.\n", iface
, refcount
);
6390 IDWriteFontFile_Release(reference
->file
);
6391 IDWriteFactory7_Release(reference
->factory
);
6392 heap_free(reference
->axis_values
);
6393 heap_free(reference
);
6399 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6401 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6403 TRACE("%p, %p.\n", iface
, fontface
);
6405 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6408 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6409 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6411 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6412 DWRITE_FONT_FILE_TYPE file_type
;
6413 DWRITE_FONT_FACE_TYPE face_type
;
6414 IDWriteFontFace
*fontface
;
6419 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6421 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6425 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6426 simulations
, &fontface
);
6429 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6430 IDWriteFontFace_Release(fontface
);
6436 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6438 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6439 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6442 TRACE("%p, %p.\n", iface
, ref
);
6444 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6445 reference
->simulations
== other
->simulations
;
6446 if (reference
->axis_values_count
)
6448 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6449 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6455 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6457 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6459 TRACE("%p.\n", iface
);
6461 return reference
->index
;
6464 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6466 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6468 TRACE("%p.\n", iface
);
6470 return reference
->simulations
;
6473 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6475 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6476 IDWriteFontFileLoader
*loader
;
6481 TRACE("%p, %p.\n", iface
, file
);
6483 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6487 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6491 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6492 IDWriteFontFileLoader_Release(loader
);
6497 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6499 FIXME("%p.\n", iface
);
6504 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6506 FIXME("%p.\n", iface
);
6511 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6513 FIXME("%p, %p.\n", iface
, writetime
);
6518 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6520 FIXME("%p.\n", iface
);
6522 return DWRITE_LOCALITY_LOCAL
;
6525 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6527 FIXME("%p.\n", iface
);
6532 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6533 WCHAR
const *chars
, UINT32 count
)
6535 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6540 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6541 UINT16
const *glyphs
, UINT32 count
)
6543 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6548 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6549 UINT64 offset
, UINT64 size
)
6551 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6556 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6558 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6559 IDWriteFontFace3
*fontface3
;
6562 TRACE("%p, %p.\n", iface
, fontface
);
6564 /* FIXME: created instance should likely respect given axis. */
6565 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6568 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6569 IDWriteFontFace3_Release(fontface3
);
6575 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6577 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6579 TRACE("%p.\n", iface
);
6581 return reference
->axis_values_count
;
6584 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6585 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6587 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6589 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6591 if (value_count
< reference
->axis_values_count
)
6592 return E_NOT_SUFFICIENT_BUFFER
;
6594 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6599 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6601 fontfacereference_QueryInterface
,
6602 fontfacereference_AddRef
,
6603 fontfacereference_Release
,
6604 fontfacereference_CreateFontFace
,
6605 fontfacereference_CreateFontFaceWithSimulations
,
6606 fontfacereference_Equals
,
6607 fontfacereference_GetFontFaceIndex
,
6608 fontfacereference_GetSimulations
,
6609 fontfacereference_GetFontFile
,
6610 fontfacereference_GetLocalFileSize
,
6611 fontfacereference_GetFileSize
,
6612 fontfacereference_GetFileTime
,
6613 fontfacereference_GetLocality
,
6614 fontfacereference_EnqueueFontDownloadRequest
,
6615 fontfacereference_EnqueueCharacterDownloadRequest
,
6616 fontfacereference_EnqueueGlyphDownloadRequest
,
6617 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6618 fontfacereference1_CreateFontFace
,
6619 fontfacereference1_GetFontAxisValueCount
,
6620 fontfacereference1_GetFontAxisValues
,
6623 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6624 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6625 IDWriteFontFaceReference1
**ret
)
6627 struct dwrite_fontfacereference
*object
;
6631 if (!is_simulation_valid(simulations
))
6632 return E_INVALIDARG
;
6634 object
= heap_alloc_zero(sizeof(*object
));
6636 return E_OUTOFMEMORY
;
6638 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6639 object
->refcount
= 1;
6641 object
->factory
= factory
;
6642 IDWriteFactory7_AddRef(object
->factory
);
6643 object
->file
= file
;
6644 IDWriteFontFile_AddRef(object
->file
);
6645 object
->index
= index
;
6646 object
->simulations
= simulations
;
6647 if (axis_values_count
)
6649 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6651 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6652 return E_OUTOFMEMORY
;
6654 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6655 object
->axis_values_count
= axis_values_count
;
6658 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6663 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6665 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6667 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6669 IDWriteFontFileStream_AddRef(iface
);
6675 WARN("%s not implemented.\n", debugstr_guid(riid
));
6676 return E_NOINTERFACE
;
6679 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6681 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6682 ULONG refcount
= InterlockedIncrement(&stream
->ref
);
6684 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6689 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6691 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6692 ULONG refcount
= InterlockedDecrement(&stream
->ref
);
6694 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6698 release_inmemory_stream(stream
->data
);
6705 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6706 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6708 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6710 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
6711 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6713 *fragment_context
= NULL
;
6715 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6716 *fragment_start
= NULL
;
6720 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6724 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6726 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
6729 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6731 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6733 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
6735 *size
= stream
->data
->size
;
6740 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6742 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
6744 *last_writetime
= 0;
6749 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6750 inmemoryfilestream_QueryInterface
,
6751 inmemoryfilestream_AddRef
,
6752 inmemoryfilestream_Release
,
6753 inmemoryfilestream_ReadFileFragment
,
6754 inmemoryfilestream_ReleaseFileFragment
,
6755 inmemoryfilestream_GetFileSize
,
6756 inmemoryfilestream_GetLastWriteTime
,
6759 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6760 REFIID riid
, void **obj
)
6762 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6764 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6765 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6766 IsEqualIID(riid
, &IID_IUnknown
))
6769 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6773 WARN("%s not implemented.\n", debugstr_guid(riid
));
6777 return E_NOINTERFACE
;
6780 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6782 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6783 ULONG refcount
= InterlockedIncrement(&loader
->ref
);
6785 TRACE("%p, refcount %u.\n", iface
, refcount
);
6790 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6792 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6793 ULONG refcount
= InterlockedDecrement(&loader
->ref
);
6796 TRACE("%p, refcount %u.\n", iface
, refcount
);
6800 for (i
= 0; i
< loader
->count
; ++i
)
6801 release_inmemory_stream(loader
->streams
[i
]);
6802 heap_free(loader
->streams
);
6809 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6810 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6812 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6813 struct dwrite_inmemory_filestream
*stream
;
6816 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
6820 if (key_size
!= sizeof(DWORD
))
6821 return E_INVALIDARG
;
6823 index
= *(DWORD
*)key
;
6825 if (index
>= loader
->count
)
6826 return E_INVALIDARG
;
6828 if (!(stream
= heap_alloc(sizeof(*stream
))))
6829 return E_OUTOFMEMORY
;
6831 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6833 stream
->data
= loader
->streams
[index
];
6834 InterlockedIncrement(&stream
->data
->ref
);
6836 *ret
= &stream
->IDWriteFontFileStream_iface
;
6841 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6842 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6844 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6845 struct dwrite_inmemory_stream_data
*stream
;
6848 TRACE("%p, %p, %p, %u, %p, %p.\n", iface
, factory
, data
, data_size
, owner
, fontfile
);
6852 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6853 return E_OUTOFMEMORY
;
6855 if (!(stream
= heap_alloc(sizeof(*stream
))))
6856 return E_OUTOFMEMORY
;
6859 stream
->size
= data_size
;
6860 stream
->owner
= owner
;
6861 if (stream
->owner
) {
6862 IUnknown_AddRef(stream
->owner
);
6863 stream
->data
= (void *)data
;
6866 if (!(stream
->data
= heap_alloc(data_size
))) {
6868 return E_OUTOFMEMORY
;
6870 memcpy(stream
->data
, data
, data_size
);
6873 key
= loader
->count
;
6874 loader
->streams
[loader
->count
++] = stream
;
6876 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6877 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6880 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6882 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6884 TRACE("%p.\n", iface
);
6886 return loader
->count
;
6889 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6891 inmemoryfontfileloader_QueryInterface
,
6892 inmemoryfontfileloader_AddRef
,
6893 inmemoryfontfileloader_Release
,
6894 inmemoryfontfileloader_CreateStreamFromKey
,
6895 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6896 inmemoryfontfileloader_GetFileCount
,
6899 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6901 struct dwrite_inmemory_fileloader
*loader
;
6905 loader
= heap_alloc_zero(sizeof(*loader
));
6907 return E_OUTOFMEMORY
;
6909 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6912 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6917 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6919 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6921 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6922 IsEqualIID(riid
, &IID_IUnknown
))
6925 IDWriteFontResource_AddRef(iface
);
6929 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6931 return E_NOINTERFACE
;
6934 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6936 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6937 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6939 TRACE("%p, refcount %u.\n", iface
, refcount
);
6944 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6946 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6947 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6949 TRACE("%p, refcount %u.\n", iface
, refcount
);
6953 IDWriteFactory7_Release(resource
->factory
);
6954 IDWriteFontFile_Release(resource
->file
);
6955 heap_free(resource
);
6961 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6963 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6965 TRACE("%p, %p.\n", iface
, fontfile
);
6967 *fontfile
= resource
->file
;
6968 IDWriteFontFile_AddRef(*fontfile
);
6973 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6975 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6977 TRACE("%p.\n", iface
);
6979 return resource
->face_index
;
6982 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6984 FIXME("%p.\n", iface
);
6989 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6990 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6992 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
6997 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
6998 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
7000 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
7005 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7008 FIXME("%p, %u.\n", iface
, axis
);
7010 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
7013 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7014 IDWriteLocalizedStrings
**names
)
7016 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7021 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7023 FIXME("%p, %u.\n", iface
, axis
);
7028 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7029 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7031 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7036 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7038 FIXME("%p.\n", iface
);
7043 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7044 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7045 IDWriteFontFace5
**fontface
)
7047 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7048 IDWriteFontFaceReference1
*reference
;
7051 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7053 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7054 simulations
, axis_values
, num_values
, &reference
);
7057 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7058 IDWriteFontFaceReference1_Release(reference
);
7064 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7065 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7066 IDWriteFontFaceReference1
**reference
)
7068 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7070 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7072 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7073 simulations
, axis_values
, num_values
, reference
);
7076 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7078 dwritefontresource_QueryInterface
,
7079 dwritefontresource_AddRef
,
7080 dwritefontresource_Release
,
7081 dwritefontresource_GetFontFile
,
7082 dwritefontresource_GetFontFaceIndex
,
7083 dwritefontresource_GetFontAxisCount
,
7084 dwritefontresource_GetDefaultFontAxisValues
,
7085 dwritefontresource_GetFontAxisRanges
,
7086 dwritefontresource_GetFontAxisAttributes
,
7087 dwritefontresource_GetAxisNames
,
7088 dwritefontresource_GetAxisValueNameCount
,
7089 dwritefontresource_GetAxisValueNames
,
7090 dwritefontresource_HasVariations
,
7091 dwritefontresource_CreateFontFace
,
7092 dwritefontresource_CreateFontFaceReference
,
7095 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7096 IDWriteFontResource
**ret
)
7098 struct dwrite_fontresource
*resource
;
7102 resource
= heap_alloc_zero(sizeof(*resource
));
7104 return E_OUTOFMEMORY
;
7106 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7107 resource
->refcount
= 1;
7108 resource
->face_index
= face_index
;
7109 resource
->file
= file
;
7110 IDWriteFontFile_AddRef(resource
->file
);
7111 resource
->factory
= factory
;
7112 IDWriteFactory7_AddRef(resource
->factory
);
7114 *ret
= &resource
->IDWriteFontResource_iface
;
7119 static HRESULT WINAPI
dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2
*iface
,
7120 REFIID riid
, void **obj
)
7122 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7124 if (IsEqualIID(riid
, &IID_IDWriteFontSetBuilder2
) ||
7125 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder1
) ||
7126 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder
) ||
7127 IsEqualIID(riid
, &IID_IUnknown
))
7130 IDWriteFontSetBuilder2_AddRef(iface
);
7134 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7136 return E_NOINTERFACE
;
7139 static ULONG WINAPI
dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2
*iface
)
7141 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7142 ULONG refcount
= InterlockedIncrement(&builder
->refcount
);
7144 TRACE("%p, refcount %u.\n", iface
, refcount
);
7149 static ULONG WINAPI
dwritefontsetbuilder_Release(IDWriteFontSetBuilder2
*iface
)
7151 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7152 ULONG refcount
= InterlockedDecrement(&builder
->refcount
);
7154 TRACE("%p, refcount %u.\n", iface
, refcount
);
7158 IDWriteFactory7_Release(builder
->factory
);
7165 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2
*iface
,
7166 IDWriteFontFaceReference
*ref
, DWRITE_FONT_PROPERTY
const *props
, UINT32 prop_count
)
7168 FIXME("%p, %p, %p, %u.\n", iface
, ref
, props
, prop_count
);
7173 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2
*iface
,
7174 IDWriteFontFaceReference
*ref
)
7176 FIXME("%p, %p.\n", iface
, ref
);
7181 static HRESULT WINAPI
dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
*fontset
)
7183 FIXME("%p, %p.\n", iface
, fontset
);
7188 static HRESULT WINAPI
dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
**fontset
)
7190 FIXME("%p, %p.\n", iface
, fontset
);
7195 static HRESULT WINAPI
dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
)
7197 FIXME("%p, %p.\n", iface
, file
);
7202 static HRESULT WINAPI
dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
,
7203 unsigned int face_index
, DWRITE_FONT_SIMULATIONS simulations
, const DWRITE_FONT_AXIS_VALUE
*axis_values
,
7204 unsigned int num_values
, const DWRITE_FONT_AXIS_RANGE
*axis_ranges
, unsigned int num_ranges
,
7205 const DWRITE_FONT_PROPERTY
*props
, unsigned int num_properties
)
7207 FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface
, file
, face_index
, simulations
, axis_values
, num_values
,
7208 axis_ranges
, num_ranges
, props
, num_properties
);
7213 static HRESULT WINAPI
dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2
*iface
, const WCHAR
*filepath
)
7215 FIXME("%p, %s.\n", iface
, debugstr_w(filepath
));
7220 static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl
=
7222 dwritefontsetbuilder_QueryInterface
,
7223 dwritefontsetbuilder_AddRef
,
7224 dwritefontsetbuilder_Release
,
7225 dwritefontsetbuilder_AddFontFaceReference_
,
7226 dwritefontsetbuilder_AddFontFaceReference
,
7227 dwritefontsetbuilder_AddFontSet
,
7228 dwritefontsetbuilder_CreateFontSet
,
7229 dwritefontsetbuilder1_AddFontFile
,
7230 dwritefontsetbuilder2_AddFont
,
7231 dwritefontsetbuilder2_AddFontFile
,
7234 HRESULT
create_fontset_builder(IDWriteFactory7
*factory
, IDWriteFontSetBuilder2
**ret
)
7236 struct dwrite_fontset_builder
*builder
;
7240 if (!(builder
= heap_alloc_zero(sizeof(*builder
))))
7241 return E_OUTOFMEMORY
;
7243 builder
->IDWriteFontSetBuilder2_iface
.lpVtbl
= &fontsetbuildervtbl
;
7244 builder
->refcount
= 1;
7245 builder
->factory
= factory
;
7246 IDWriteFactory7_AddRef(builder
->factory
);
7248 *ret
= &builder
->IDWriteFontSetBuilder2_iface
;