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_entry
256 IDWriteFontFile
*file
;
257 DWRITE_FONT_FACE_TYPE face_type
;
258 unsigned int face_index
;
259 unsigned int simulations
;
260 IDWriteLocalizedStrings
*props
[DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
+ 1];
263 struct dwrite_fontset
265 IDWriteFontSet3 IDWriteFontSet3_iface
;
267 IDWriteFactory7
*factory
;
269 struct dwrite_fontset_entry
**entries
;
273 struct dwrite_fontset_builder
275 IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface
;
277 IDWriteFactory7
*factory
;
279 struct dwrite_fontset_entry
**entries
;
284 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
285 unsigned int count
, IDWriteFontSet1
**ret
);
287 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
289 struct dwrite_fontface
*fontface
= context
;
292 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
293 size
, data_context
, &exists
)) || !exists
)
297 *data_context
= NULL
;
301 static void dwrite_release_font_table(void *context
, void *data_context
)
303 struct dwrite_fontface
*fontface
= context
;
304 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
307 static UINT16
dwrite_get_font_upem(void *context
)
309 struct dwrite_fontface
*fontface
= context
;
310 return fontface
->metrics
.designUnitsPerEm
;
313 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
315 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
316 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
319 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
321 struct dwrite_fontface
*fontface
= context
;
322 return !!dwritefontface_get_glyph(fontface
, codepoint
);
325 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
327 struct dwrite_fontface
*fontface
= context
;
328 return dwritefontface_get_glyph(fontface
, codepoint
);
331 static const struct shaping_font_ops dwrite_font_ops
=
333 dwrite_grab_font_table
,
334 dwrite_release_font_table
,
335 dwrite_get_font_upem
,
340 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
342 if (fontface
->shaping_cache
)
343 return fontface
->shaping_cache
;
345 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
348 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
350 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
353 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
355 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
358 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
360 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
363 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
365 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
367 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
370 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
372 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
375 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
377 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
380 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
382 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
385 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
387 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
390 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
392 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
395 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
397 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
400 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
402 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
405 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
407 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
410 static struct dwrite_fontset_builder
*impl_from_IDWriteFontSetBuilder2(IDWriteFontSetBuilder2
*iface
)
412 return CONTAINING_RECORD(iface
, struct dwrite_fontset_builder
, IDWriteFontSetBuilder2_iface
);
415 static struct dwrite_fontset
*impl_from_IDWriteFontSet3(IDWriteFontSet3
*iface
)
417 return CONTAINING_RECORD(iface
, struct dwrite_fontset
, IDWriteFontSet3_iface
);
420 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
422 static const DWRITE_GLYPH_METRICS nil
;
423 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
425 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
426 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
430 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
432 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
435 /* start new block */
436 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
438 return E_OUTOFMEMORY
;
441 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
445 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
449 if (table
->data
|| !table
->exists
)
452 table
->exists
= FALSE
;
453 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
455 if (FAILED(hr
) || !table
->exists
) {
456 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
463 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
464 struct dwrite_font_propvec
*vec
)
466 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
467 vec
->style
= style
* 7.0f
;
468 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
471 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
473 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
476 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
478 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
481 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
483 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
484 return &fontface
->vdmx
;
487 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
489 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
490 return &fontface
->gasp
;
493 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
495 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
496 return &fontface
->cpal
;
499 static struct dwrite_font_data
* addref_font_data(struct dwrite_font_data
*data
)
501 InterlockedIncrement(&data
->refcount
);
505 static void release_font_data(struct dwrite_font_data
*data
)
509 if (InterlockedDecrement(&data
->refcount
) > 0)
512 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
514 if (data
->info_strings
[i
])
515 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
518 IDWriteLocalizedStrings_Release(data
->names
);
520 if (data
->family_names
)
521 IDWriteLocalizedStrings_Release(data
->family_names
);
523 dwrite_cmap_release(&data
->cmap
);
524 IDWriteFontFile_Release(data
->file
);
525 heap_free(data
->facename
);
529 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
533 if (InterlockedDecrement(&data
->refcount
) > 0)
536 for (i
= 0; i
< data
->count
; ++i
)
537 release_font_data(data
->fonts
[i
]);
538 heap_free(data
->fonts
);
539 IDWriteLocalizedStrings_Release(data
->familyname
);
543 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
545 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
546 fontface
->cached
= NULL
;
549 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
551 UINT32 left_key_size
, right_key_size
;
552 const void *left_key
, *right_key
;
558 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
562 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
566 if (left_key_size
!= right_key_size
)
569 return !memcmp(left_key
, right_key
, left_key_size
);
572 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
574 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
576 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
578 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
579 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
580 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
581 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
582 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
583 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
584 IsEqualIID(riid
, &IID_IUnknown
))
588 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
589 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
595 if (InterlockedIncrement(&fontface
->refcount
) == 1)
597 InterlockedDecrement(&fontface
->refcount
);
604 WARN("%s not implemented.\n", debugstr_guid(riid
));
606 return E_NOINTERFACE
;
609 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
611 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
612 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
614 TRACE("%p, refcount %u.\n", iface
, refcount
);
619 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
621 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
622 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
624 TRACE("%p, refcount %u.\n", iface
, refcount
);
630 if (fontface
->cached
)
632 factory_lock(fontface
->factory
);
633 list_remove(&fontface
->cached
->entry
);
634 factory_unlock(fontface
->factory
);
635 heap_free(fontface
->cached
);
637 release_scriptshaping_cache(fontface
->shaping_cache
);
638 if (fontface
->vdmx
.context
)
639 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
640 if (fontface
->gasp
.context
)
641 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
642 if (fontface
->cpal
.context
)
643 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
644 if (fontface
->colr
.context
)
645 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
646 if (fontface
->kern
.context
)
647 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->kern
.context
);
649 IDWriteFontFile_Release(fontface
->file
);
650 if (fontface
->stream
)
651 IDWriteFontFileStream_Release(fontface
->stream
);
653 IDWriteLocalizedStrings_Release(fontface
->names
);
654 if (fontface
->family_names
)
655 IDWriteLocalizedStrings_Release(fontface
->family_names
);
656 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
658 if (fontface
->info_strings
[i
])
659 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
662 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
663 heap_free(fontface
->glyphs
[i
]);
665 freetype_notify_cacheremove(iface
);
667 dwrite_cmap_release(&fontface
->cmap
);
668 IDWriteFactory7_Release(fontface
->factory
);
675 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
677 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
679 TRACE("%p.\n", iface
);
681 return fontface
->type
;
684 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
685 IDWriteFontFile
**fontfiles
)
687 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
689 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
693 *number_of_files
= 1;
697 if (!*number_of_files
)
700 IDWriteFontFile_AddRef(fontface
->file
);
701 *fontfiles
= fontface
->file
;
706 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
708 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
710 TRACE("%p.\n", iface
);
712 return fontface
->index
;
715 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
717 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
719 TRACE("%p.\n", iface
);
721 return fontface
->simulations
;
724 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
726 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
728 TRACE("%p.\n", iface
);
730 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
733 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
735 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
737 TRACE("%p, %p.\n", iface
, metrics
);
739 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
742 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
744 TRACE("%p.\n", iface
);
746 return freetype_get_glyphcount(iface
);
749 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
750 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
752 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
756 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
762 FIXME("sideways metrics are not supported.\n");
764 for (i
= 0; i
< glyph_count
; i
++) {
765 DWRITE_GLYPH_METRICS metrics
;
767 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
769 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
770 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
780 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
781 UINT32 count
, UINT16
*glyphs
)
783 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
786 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
793 memset(glyphs
, 0, count
* sizeof(*glyphs
));
797 for (i
= 0; i
< count
; ++i
)
798 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
803 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
804 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
806 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
807 struct file_stream_desc stream_desc
;
809 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
811 stream_desc
.stream
= fontface
->stream
;
812 stream_desc
.face_type
= fontface
->type
;
813 stream_desc
.face_index
= fontface
->index
;
814 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
817 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
819 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
821 TRACE("%p, %p.\n", iface
, table_context
);
823 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
826 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
827 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
828 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
830 D2D1_POINT_2F
*origins
, baseline_origin
= { 0 };
831 DWRITE_GLYPH_RUN run
;
835 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
836 count
, is_sideways
, is_rtl
, sink
);
838 if (!glyphs
|| !sink
)
844 run
.fontFace
= (IDWriteFontFace
*)iface
;
845 run
.fontEmSize
= emSize
;
846 run
.glyphCount
= count
;
847 run
.glyphIndices
= glyphs
;
848 run
.glyphAdvances
= advances
;
849 run
.glyphOffsets
= offsets
;
850 run
.isSideways
= is_sideways
;
851 run
.bidiLevel
= is_rtl
? 1 : 0;
853 if (!(origins
= heap_alloc(sizeof(*origins
) * count
)))
854 return E_OUTOFMEMORY
;
856 if (FAILED(hr
= compute_glyph_origins(&run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
, NULL
, origins
)))
862 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
864 for (i
= 0; i
< count
; ++i
)
866 if (FAILED(hr
= freetype_get_glyph_outline(iface
, emSize
, glyphs
[i
], origins
[i
], sink
)))
867 WARN("Failed to get glyph outline for glyph %u.\n", glyphs
[i
]);
875 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
876 float ppem
, unsigned int gasp
)
878 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
882 case DWRITE_MEASURING_MODE_NATURAL
:
884 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
885 mode
= DWRITE_RENDERING_MODE_NATURAL
;
887 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
890 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
891 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
893 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
894 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
903 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
904 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
906 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
910 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
913 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
917 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
918 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
921 ppem
= emSize
* ppdip
;
923 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
924 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
928 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
929 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
933 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
934 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
936 DWRITE_FONT_METRICS1 metrics1
;
937 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
938 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
942 static inline int round_metric(FLOAT metric
)
944 return (int)floorf(metric
+ 0.5f
);
947 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
949 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
952 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
955 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
956 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
957 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
959 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
960 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
961 DWRITE_MEASURING_MODE mode
;
966 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
967 glyph_count
, metrics
, is_sideways
);
969 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
970 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
972 size
= emSize
* ppdip
;
973 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
974 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
976 for (i
= 0; i
< glyph_count
; i
++) {
977 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
978 DWRITE_GLYPH_METRICS design
;
981 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
985 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
987 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
989 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
991 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
992 SCALE_METRIC(leftSideBearing
);
993 SCALE_METRIC(rightSideBearing
);
994 SCALE_METRIC(topSideBearing
);
995 SCALE_METRIC(advanceHeight
);
996 SCALE_METRIC(bottomSideBearing
);
997 SCALE_METRIC(verticalOriginY
);
1004 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1006 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1008 TRACE("%p, %p.\n", iface
, metrics
);
1010 *metrics
= fontface
->metrics
;
1013 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
1014 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
1016 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1017 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
1018 UINT16 ascent
, descent
;
1021 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
1023 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
1024 memset(metrics
, 0, sizeof(*metrics
));
1025 return E_INVALIDARG
;
1028 em_size
*= pixels_per_dip
;
1029 if (m
&& m
->m22
!= 0.0f
)
1030 em_size
*= fabs(m
->m22
);
1032 scale
= em_size
/ design
->designUnitsPerEm
;
1033 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
1035 ascent
= round_metric(design
->ascent
* scale
);
1036 descent
= round_metric(design
->descent
* scale
);
1039 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
1040 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
1041 metrics
->ascent
= round_metric(ascent
/ scale
);
1042 metrics
->descent
= round_metric(descent
/ scale
);
1044 SCALE_METRIC(lineGap
);
1045 SCALE_METRIC(capHeight
);
1046 SCALE_METRIC(xHeight
);
1047 SCALE_METRIC(underlinePosition
);
1048 SCALE_METRIC(underlineThickness
);
1049 SCALE_METRIC(strikethroughPosition
);
1050 SCALE_METRIC(strikethroughThickness
);
1051 SCALE_METRIC(glyphBoxLeft
);
1052 SCALE_METRIC(glyphBoxTop
);
1053 SCALE_METRIC(glyphBoxRight
);
1054 SCALE_METRIC(glyphBoxBottom
);
1055 SCALE_METRIC(subscriptPositionX
);
1056 SCALE_METRIC(subscriptPositionY
);
1057 SCALE_METRIC(subscriptSizeX
);
1058 SCALE_METRIC(subscriptSizeY
);
1059 SCALE_METRIC(superscriptPositionX
);
1060 SCALE_METRIC(superscriptPositionY
);
1061 SCALE_METRIC(superscriptSizeX
);
1062 SCALE_METRIC(superscriptSizeY
);
1064 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
1070 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1072 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1074 TRACE("%p, %p.\n", iface
, metrics
);
1076 *metrics
= fontface
->caret
;
1079 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1080 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1082 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1084 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1087 if (max_count
&& !ranges
)
1088 return E_INVALIDARG
;
1090 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1091 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1094 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1096 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1098 TRACE("%p.\n", iface
);
1100 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1103 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1104 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1106 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1111 FIXME("Sideways mode is not supported.\n");
1113 switch (measuring_mode
)
1115 case DWRITE_MEASURING_MODE_NATURAL
:
1116 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1117 glyph
, measuring_mode
, &has_contours
);
1119 advance
+= adjustment
;
1122 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1123 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1128 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1129 FIXME("Transform is not supported.\n");
1131 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1134 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1136 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1140 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1145 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1146 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1148 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1151 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1154 FIXME("sideways mode not supported\n");
1156 for (i
= 0; i
< glyph_count
; ++i
)
1158 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1159 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1165 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1166 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1167 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1169 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1170 DWRITE_MEASURING_MODE measuring_mode
;
1173 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1174 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1176 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1177 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1178 return E_INVALIDARG
;
1181 if (em_size
== 0.0f
) {
1182 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1186 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1187 for (i
= 0; i
< glyph_count
; ++i
)
1189 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1190 glyphs
[i
], is_sideways
);
1196 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1197 const UINT16
*glyphs
, INT32
*values
)
1199 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1201 TRACE("%p, %u, %p, %p.\n", iface
, count
, glyphs
, values
);
1203 if (!(glyphs
|| values
) || !count
)
1204 return E_INVALIDARG
;
1206 if (!glyphs
|| count
== 1)
1208 memset(values
, 0, count
* sizeof(*values
));
1209 return E_INVALIDARG
;
1212 return opentype_get_kerning_pairs(fontface
, count
, glyphs
, values
);
1215 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1217 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1219 TRACE("%p.\n", iface
);
1221 return opentype_has_kerning_pairs(fontface
);
1224 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1225 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1226 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1228 DWRITE_GRID_FIT_MODE gridfitmode
;
1229 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1230 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1233 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1234 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1236 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1238 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1240 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1243 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1245 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1247 TRACE("%p.\n", iface
);
1249 return opentype_has_vertical_variants(fontface
);
1252 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1254 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1256 TRACE("%p.\n", iface
);
1258 return !!(fontface
->flags
& FONT_IS_COLORED
);
1261 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1263 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1265 TRACE("%p.\n", iface
);
1267 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1270 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1272 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1274 TRACE("%p.\n", iface
);
1276 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1279 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1280 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1282 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1284 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1286 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1289 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1290 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1291 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1292 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1294 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1298 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1299 measuringmode
, params
, renderingmode
, gridfitmode
);
1301 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1302 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1305 FIXME("sideways mode not supported\n");
1307 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1309 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1310 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1312 IDWriteRenderingParams2
*params2
;
1315 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1317 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1318 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1319 IDWriteRenderingParams2_Release(params2
);
1322 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1325 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1327 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1329 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1330 if (emSize
>= emthreshold
)
1331 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1333 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1336 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1337 if (emSize
>= emthreshold
)
1338 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1339 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1340 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1342 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1343 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1349 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1350 IDWriteFontFaceReference
**reference
)
1352 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1354 TRACE("%p, %p.\n", iface
, reference
);
1356 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1357 IDWriteFontFaceReference_AddRef(*reference
);
1362 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1364 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1366 TRACE("%p, %p.\n", iface
, panose
);
1368 *panose
= fontface
->panose
;
1371 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1373 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1375 TRACE("%p.\n", iface
);
1377 return fontface
->weight
;
1380 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1382 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1384 TRACE("%p.\n", iface
);
1386 return fontface
->stretch
;
1389 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1391 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1393 TRACE("%p.\n", iface
);
1395 return fontface
->style
;
1398 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1400 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1402 TRACE("%p, %p.\n", iface
, names
);
1404 return clone_localizedstrings(fontface
->family_names
, names
);
1407 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1409 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1411 TRACE("%p, %p.\n", iface
, names
);
1413 return clone_localizedstrings(fontface
->names
, names
);
1416 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1417 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1418 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1425 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1426 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1431 if (!strings_cache
[stringid
])
1433 struct file_stream_desc desc
= *stream_desc
;
1436 hr
= get_filestream_from_file(file
, &desc
.stream
);
1438 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1440 if (!stream_desc
->stream
&& desc
.stream
)
1441 IDWriteFontFileStream_Release(desc
.stream
);
1444 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1446 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1454 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1455 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1457 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1458 struct file_stream_desc stream_desc
;
1460 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1462 stream_desc
.stream
= fontface
->stream
;
1463 stream_desc
.face_index
= fontface
->index
;
1464 stream_desc
.face_type
= fontface
->type
;
1465 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1468 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1470 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1472 TRACE("%p, %#x.\n", iface
, ch
);
1474 return !!dwritefontface_get_glyph(fontface
, ch
);
1477 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1478 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1479 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1481 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1485 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1486 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1488 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1489 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1492 FIXME("sideways mode not supported\n");
1494 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1496 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1497 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1499 IDWriteRenderingParams3
*params3
;
1502 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1504 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1505 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1506 IDWriteRenderingParams3_Release(params3
);
1509 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1512 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1514 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1516 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1517 if (emSize
>= emthreshold
)
1518 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1520 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1523 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1524 if (emSize
>= emthreshold
)
1525 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1526 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1527 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1529 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1530 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1536 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1538 FIXME("%p, %#x: stub\n", iface
, ch
);
1543 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1545 FIXME("%p, %u: stub\n", iface
, glyph
);
1550 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1551 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1553 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1558 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1559 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1561 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1566 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1567 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1569 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1574 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1576 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1578 TRACE("%p.\n", iface
);
1580 return fontface
->glyph_image_formats
;
1583 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1584 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1586 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1591 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1593 FIXME("%p, %p: stub\n", iface
, context
);
1596 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1598 FIXME("%p: stub\n", iface
);
1603 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1606 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1611 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1616 FIXME("%p: stub\n", iface
);
1621 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1623 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1625 TRACE("%p, %p.\n", iface
, resource
);
1627 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->file
, fontface
->index
, resource
);
1630 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1632 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1634 TRACE("%p, %p.\n", iface
, other
);
1636 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1639 /* TODO: add variations support */
1641 return fontface
->index
== other_face
->index
&&
1642 fontface
->simulations
== other_face
->simulations
&&
1643 is_same_fontfile(fontface
->file
, other_face
->file
);
1646 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1648 dwritefontface_QueryInterface
,
1649 dwritefontface_AddRef
,
1650 dwritefontface_Release
,
1651 dwritefontface_GetType
,
1652 dwritefontface_GetFiles
,
1653 dwritefontface_GetIndex
,
1654 dwritefontface_GetSimulations
,
1655 dwritefontface_IsSymbolFont
,
1656 dwritefontface_GetMetrics
,
1657 dwritefontface_GetGlyphCount
,
1658 dwritefontface_GetDesignGlyphMetrics
,
1659 dwritefontface_GetGlyphIndices
,
1660 dwritefontface_TryGetFontTable
,
1661 dwritefontface_ReleaseFontTable
,
1662 dwritefontface_GetGlyphRunOutline
,
1663 dwritefontface_GetRecommendedRenderingMode
,
1664 dwritefontface_GetGdiCompatibleMetrics
,
1665 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1666 dwritefontface1_GetMetrics
,
1667 dwritefontface1_GetGdiCompatibleMetrics
,
1668 dwritefontface1_GetCaretMetrics
,
1669 dwritefontface1_GetUnicodeRanges
,
1670 dwritefontface1_IsMonospacedFont
,
1671 dwritefontface1_GetDesignGlyphAdvances
,
1672 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1673 dwritefontface1_GetKerningPairAdjustments
,
1674 dwritefontface1_HasKerningPairs
,
1675 dwritefontface1_GetRecommendedRenderingMode
,
1676 dwritefontface1_GetVerticalGlyphVariants
,
1677 dwritefontface1_HasVerticalGlyphVariants
,
1678 dwritefontface2_IsColorFont
,
1679 dwritefontface2_GetColorPaletteCount
,
1680 dwritefontface2_GetPaletteEntryCount
,
1681 dwritefontface2_GetPaletteEntries
,
1682 dwritefontface2_GetRecommendedRenderingMode
,
1683 dwritefontface3_GetFontFaceReference
,
1684 dwritefontface3_GetPanose
,
1685 dwritefontface3_GetWeight
,
1686 dwritefontface3_GetStretch
,
1687 dwritefontface3_GetStyle
,
1688 dwritefontface3_GetFamilyNames
,
1689 dwritefontface3_GetFaceNames
,
1690 dwritefontface3_GetInformationalStrings
,
1691 dwritefontface3_HasCharacter
,
1692 dwritefontface3_GetRecommendedRenderingMode
,
1693 dwritefontface3_IsCharacterLocal
,
1694 dwritefontface3_IsGlyphLocal
,
1695 dwritefontface3_AreCharactersLocal
,
1696 dwritefontface3_AreGlyphsLocal
,
1697 dwritefontface4_GetGlyphImageFormats_
,
1698 dwritefontface4_GetGlyphImageFormats
,
1699 dwritefontface4_GetGlyphImageData
,
1700 dwritefontface4_ReleaseGlyphImageData
,
1701 dwritefontface5_GetFontAxisValueCount
,
1702 dwritefontface5_GetFontAxisValues
,
1703 dwritefontface5_HasVariations
,
1704 dwritefontface5_GetFontResource
,
1705 dwritefontface5_Equals
,
1708 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1710 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1711 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1714 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1716 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1717 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1720 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1722 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1723 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1726 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1727 IDWriteFontFace3
**ret
)
1729 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1731 TRACE("%p, %p.\n", iface
, ret
);
1733 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1734 IDWriteFontFace3_AddRef(*ret
);
1739 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1740 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1742 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1743 DWRITE_FONT_FILE_TYPE file_type
;
1744 DWRITE_FONT_FACE_TYPE face_type
;
1745 IDWriteFontFace
*face
;
1750 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1752 hr
= IDWriteFontFile_Analyze(fontface
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
1756 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, &fontface
->file
, fontface
->index
,
1757 simulations
, &face
);
1760 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1761 IDWriteFontFace_Release(face
);
1767 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1769 FIXME("%p, %p.\n", iface
, ref
);
1774 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1776 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1778 TRACE("%p.\n", iface
);
1780 return fontface
->index
;
1783 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1785 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1787 TRACE("%p.\n", iface
);
1789 return fontface
->simulations
;
1792 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1794 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1796 TRACE("%p, %p.\n", iface
, file
);
1798 *file
= fontface
->file
;
1799 IDWriteFontFile_AddRef(*file
);
1804 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1806 FIXME("%p.\n", iface
);
1811 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1813 FIXME("%p.\n", iface
);
1818 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1820 FIXME("%p, %p.\n", iface
, writetime
);
1825 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1827 FIXME("%p.\n", iface
);
1829 return DWRITE_LOCALITY_LOCAL
;
1832 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1834 FIXME("%p.\n", iface
);
1839 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1840 WCHAR
const *chars
, UINT32 count
)
1842 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1847 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1848 UINT16
const *glyphs
, UINT32 count
)
1850 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1855 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1856 UINT64 offset
, UINT64 size
)
1858 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1863 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1865 dwritefontface_reference_QueryInterface
,
1866 dwritefontface_reference_AddRef
,
1867 dwritefontface_reference_Release
,
1868 dwritefontface_reference_CreateFontFace
,
1869 dwritefontface_reference_CreateFontFaceWithSimulations
,
1870 dwritefontface_reference_Equals
,
1871 dwritefontface_reference_GetFontFaceIndex
,
1872 dwritefontface_reference_GetSimulations
,
1873 dwritefontface_reference_GetFontFile
,
1874 dwritefontface_reference_GetLocalFileSize
,
1875 dwritefontface_reference_GetFileSize
,
1876 dwritefontface_reference_GetFileTime
,
1877 dwritefontface_reference_GetLocality
,
1878 dwritefontface_reference_EnqueueFontDownloadRequest
,
1879 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1880 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1881 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1884 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1886 struct dwrite_font_data
*data
= font
->data
;
1887 struct fontface_desc desc
;
1888 struct list
*cached_list
;
1893 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1894 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1898 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1901 desc
.factory
= font
->family
->collection
->factory
;
1902 desc
.face_type
= data
->face_type
;
1903 desc
.file
= data
->file
;
1904 desc
.index
= data
->face_index
;
1905 desc
.simulations
= data
->simulations
;
1906 desc
.font_data
= data
;
1907 hr
= create_fontface(&desc
, cached_list
, fontface
);
1909 IDWriteFontFileStream_Release(desc
.stream
);
1913 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1915 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1917 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1918 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1919 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1920 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1921 IsEqualIID(riid
, &IID_IUnknown
))
1924 IDWriteFont3_AddRef(iface
);
1928 WARN("%s not implemented.\n", debugstr_guid(riid
));
1931 return E_NOINTERFACE
;
1934 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1936 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1937 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
1939 TRACE("%p, refcount %d.\n", iface
, refcount
);
1944 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1946 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1947 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
1949 TRACE("%p, refcount %d.\n", iface
, refcount
);
1953 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
1954 release_font_data(font
->data
);
1961 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1963 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1965 TRACE("%p, %p.\n", iface
, family
);
1967 *family
= (IDWriteFontFamily
*)font
->family
;
1968 IDWriteFontFamily_AddRef(*family
);
1972 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1974 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1976 TRACE("%p.\n", iface
);
1978 return font
->data
->weight
;
1981 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1983 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1985 TRACE("%p.\n", iface
);
1987 return font
->data
->stretch
;
1990 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1992 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1994 TRACE("%p.\n", iface
);
1999 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
2001 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2003 TRACE("%p.\n", iface
);
2005 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
2008 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
2010 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2012 TRACE("%p, %p.\n", iface
, names
);
2014 return clone_localizedstrings(font
->data
->names
, names
);
2017 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
2018 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
2020 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2021 struct dwrite_font_data
*data
= font
->data
;
2022 struct file_stream_desc stream_desc
;
2024 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
2026 /* Stream will be created if necessary. */
2027 stream_desc
.stream
= NULL
;
2028 stream_desc
.face_index
= data
->face_index
;
2029 stream_desc
.face_type
= data
->face_type
;
2030 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
2033 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
2035 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2037 TRACE("%p.\n", iface
);
2039 return font
->data
->simulations
;
2042 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
2044 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2046 TRACE("%p, %p.\n", iface
, metrics
);
2048 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
2051 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
2054 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2055 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
2059 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2061 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2063 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2065 *exists
= dwritefont_has_character(font
, ch
);
2070 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2072 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2074 TRACE("%p, %p.\n", iface
, fontface
);
2076 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2079 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2081 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2083 TRACE("%p, %p.\n", iface
, metrics
);
2085 *metrics
= font
->data
->metrics
;
2088 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2090 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2092 TRACE("%p, %p.\n", iface
, panose
);
2094 *panose
= font
->data
->panose
;
2097 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2100 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2102 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2105 if (max_count
&& !ranges
)
2106 return E_INVALIDARG
;
2108 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2109 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2112 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2114 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2116 TRACE("%p.\n", iface
);
2118 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2121 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2123 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2125 TRACE("%p.\n", iface
);
2127 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2130 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2132 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2134 TRACE("%p, %p.\n", iface
, fontface
);
2136 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2139 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2141 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2143 TRACE("%p, %p.\n", iface
, other
);
2145 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2148 return font
->data
->face_index
== other_font
->data
->face_index
2149 && font
->data
->simulations
== other_font
->data
->simulations
2150 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2153 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2155 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2157 TRACE("%p, %p.\n", iface
, reference
);
2159 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2160 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2161 (IDWriteFontFaceReference1
**)reference
);
2164 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2166 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2168 TRACE("%p, %#x.\n", iface
, ch
);
2170 return dwritefont_has_character(font
, ch
);
2173 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2175 FIXME("%p: stub.\n", iface
);
2177 return DWRITE_LOCALITY_LOCAL
;
2180 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2181 dwritefont_QueryInterface
,
2184 dwritefont_GetFontFamily
,
2185 dwritefont_GetWeight
,
2186 dwritefont_GetStretch
,
2187 dwritefont_GetStyle
,
2188 dwritefont_IsSymbolFont
,
2189 dwritefont_GetFaceNames
,
2190 dwritefont_GetInformationalStrings
,
2191 dwritefont_GetSimulations
,
2192 dwritefont_GetMetrics
,
2193 dwritefont_HasCharacter
,
2194 dwritefont_CreateFontFace
,
2195 dwritefont1_GetMetrics
,
2196 dwritefont1_GetPanose
,
2197 dwritefont1_GetUnicodeRanges
,
2198 dwritefont1_IsMonospacedFont
,
2199 dwritefont2_IsColorFont
,
2200 dwritefont3_CreateFontFace
,
2202 dwritefont3_GetFontFaceReference
,
2203 dwritefont3_HasCharacter
,
2204 dwritefont3_GetLocality
2207 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2211 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2212 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2215 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2219 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2220 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2223 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2227 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2229 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2230 IDWriteFontFaceReference1_iface
);
2233 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2235 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2236 *lf
= font
->data
->lf
;
2239 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2241 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2245 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2247 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2248 *fontsig
= font
->data
->fontsig
;
2252 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2254 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2255 *fontsig
= fontface
->fontsig
;
2259 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2261 struct dwrite_font
*object
;
2265 if (!(object
= heap_alloc(sizeof(*object
))))
2266 return E_OUTOFMEMORY
;
2268 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2269 object
->refcount
= 1;
2270 object
->family
= family
;
2271 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2272 object
->data
= family
->data
->fonts
[index
];
2273 object
->style
= object
->data
->style
;
2274 addref_font_data(object
->data
);
2276 *font
= &object
->IDWriteFont3_iface
;
2281 /* IDWriteFontList2 */
2282 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2284 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2286 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2287 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2288 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2289 IsEqualIID(riid
, &IID_IUnknown
))
2292 IDWriteFontList2_AddRef(iface
);
2296 WARN("%s not implemented.\n", debugstr_guid(riid
));
2299 return E_NOINTERFACE
;
2302 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2304 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2305 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2307 TRACE("%p, refcount %u.\n", iface
, refcount
);
2312 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2314 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2315 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2317 TRACE("%p, refcount %u.\n", iface
, refcount
);
2323 for (i
= 0; i
< fontlist
->font_count
; i
++)
2324 release_font_data(fontlist
->fonts
[i
]);
2325 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2326 heap_free(fontlist
->fonts
);
2327 heap_free(fontlist
);
2333 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2335 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2336 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2339 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2341 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2343 TRACE("%p.\n", iface
);
2345 return fontlist
->font_count
;
2348 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2350 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2352 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2356 if (fontlist
->font_count
== 0)
2359 if (index
>= fontlist
->font_count
)
2360 return E_INVALIDARG
;
2362 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2365 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2367 FIXME("%p, %u.\n", iface
, index
);
2369 return DWRITE_LOCALITY_LOCAL
;
2372 static HRESULT
fontlist_get_font(const struct dwrite_fontlist
*fontlist
, unsigned int index
,
2373 IDWriteFont3
**font
)
2377 if (fontlist
->font_count
== 0)
2380 if (index
>= fontlist
->font_count
)
2383 return create_font(fontlist
->family
, index
, font
);
2386 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2388 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2390 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2392 return fontlist_get_font(fontlist
, index
, font
);
2395 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2396 IDWriteFontFaceReference
**reference
)
2398 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2402 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2406 if (SUCCEEDED(hr
= fontlist_get_font(fontlist
, index
, &font
)))
2408 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2409 IDWriteFont3_Release(font
);
2415 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2417 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2419 TRACE("%p, %p.\n", iface
, fontset
);
2421 return fontset_create_from_font_data(fontlist
->family
->collection
->factory
, fontlist
->fonts
,
2422 fontlist
->font_count
, fontset
);
2425 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2427 dwritefontlist_QueryInterface
,
2428 dwritefontlist_AddRef
,
2429 dwritefontlist_Release
,
2430 dwritefontlist_GetFontCollection
,
2431 dwritefontlist_GetFontCount
,
2432 dwritefontlist_GetFont
,
2433 dwritefontlist1_GetFontLocality
,
2434 dwritefontlist1_GetFont
,
2435 dwritefontlist1_GetFontFaceReference
,
2436 dwritefontlist2_GetFontSet
,
2439 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2441 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2443 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2445 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2446 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2447 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2448 IsEqualIID(riid
, &IID_IUnknown
))
2452 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2453 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2454 IsEqualIID(riid
, &IID_IDWriteFontList
))
2456 *obj
= &family
->IDWriteFontList2_iface
;
2460 WARN("%s not implemented.\n", debugstr_guid(riid
));
2462 return E_NOINTERFACE
;
2465 IUnknown_AddRef((IUnknown
*)*obj
);
2469 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2471 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2472 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2474 TRACE("%p, %u.\n", iface
, refcount
);
2479 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2481 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2482 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2484 TRACE("%p, %u.\n", iface
, refcount
);
2488 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2489 release_fontfamily_data(family
->data
);
2496 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2498 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2500 TRACE("%p, %p.\n", iface
, collection
);
2502 *collection
= (IDWriteFontCollection
*)family
->collection
;
2503 IDWriteFontCollection_AddRef(*collection
);
2507 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2509 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2511 TRACE("%p.\n", iface
);
2513 return family
->data
->count
;
2516 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2518 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2520 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2524 if (!family
->data
->count
)
2527 if (index
>= family
->data
->count
)
2528 return E_INVALIDARG
;
2530 return create_font(family
, index
, (IDWriteFont3
**)font
);
2533 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2535 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2537 TRACE("%p, %p.\n", iface
, names
);
2539 return clone_localizedstrings(family
->data
->familyname
, names
);
2542 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2543 const struct dwrite_font_propvec
*req
)
2545 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2546 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2547 FLOAT cur_req_prod
, next_req_prod
;
2549 if (next_to_req
< cur_to_req
)
2552 if (next_to_req
> cur_to_req
)
2555 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2556 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2558 if (next_req_prod
> cur_req_prod
)
2561 if (next_req_prod
< cur_req_prod
)
2564 if (next
->stretch
> cur
->stretch
)
2566 if (next
->stretch
< cur
->stretch
)
2569 if (next
->style
> cur
->style
)
2571 if (next
->style
< cur
->style
)
2574 if (next
->weight
> cur
->weight
)
2576 if (next
->weight
< cur
->weight
)
2579 /* full match, no reason to prefer new variant */
2583 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2584 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2586 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2587 struct dwrite_font_propvec req
;
2590 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2592 if (!family
->data
->count
)
2595 return DWRITE_E_NOFONT
;
2598 init_font_prop_vec(weight
, stretch
, style
, &req
);
2601 for (i
= 1; i
< family
->data
->count
; ++i
)
2603 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2607 return create_font(family
, match
, (IDWriteFont3
**)font
);
2610 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2612 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2614 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2617 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2619 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2622 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2624 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2629 for (j
= 0; j
< b
; j
++) {
2630 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2631 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2632 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2633 fonts
->fonts
[j
+1] = s
;
2644 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2645 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2647 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2648 matching_filter_func func
= NULL
;
2649 struct dwrite_font_propvec req
;
2650 struct dwrite_fontlist
*fonts
;
2653 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2657 fonts
= heap_alloc(sizeof(*fonts
));
2659 return E_OUTOFMEMORY
;
2661 /* Allocate as many as family has, not all of them will be necessary used. */
2662 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2663 if (!fonts
->fonts
) {
2665 return E_OUTOFMEMORY
;
2668 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2669 fonts
->refcount
= 1;
2670 fonts
->family
= family
;
2671 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2672 fonts
->font_count
= 0;
2674 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2675 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2676 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2677 func
= is_font_acceptable_for_normal
;
2679 else /* requested oblique or italic */ {
2680 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2681 func
= is_font_acceptable_for_oblique_italic
;
2684 for (i
= 0; i
< family
->data
->count
; ++i
)
2686 if (!func
|| func(family
->data
->fonts
[i
]))
2688 fonts
->fonts
[fonts
->font_count
++] = addref_font_data(family
->data
->fonts
[i
]);
2692 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2693 init_font_prop_vec(weight
, stretch
, style
, &req
);
2694 matchingfonts_sort(fonts
, &req
);
2696 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2700 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2702 FIXME("%p, %u.\n", iface
, index
);
2704 return DWRITE_LOCALITY_LOCAL
;
2707 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2709 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2711 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2715 if (!family
->data
->count
)
2718 if (index
>= family
->data
->count
)
2721 return create_font(family
, index
, font
);
2724 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2725 IDWriteFontFaceReference
**reference
)
2727 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2728 const struct dwrite_font_data
*font
;
2730 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2734 if (index
>= family
->data
->count
)
2737 font
= family
->data
->fonts
[index
];
2738 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2739 font
->file
, font
->face_index
, font
->simulations
, reference
);
2742 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2743 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2745 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2750 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2752 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2754 TRACE("%p, %p.\n", iface
, fontset
);
2756 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
2757 family
->data
->count
, fontset
);
2760 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2762 dwritefontfamily_QueryInterface
,
2763 dwritefontfamily_AddRef
,
2764 dwritefontfamily_Release
,
2765 dwritefontfamily_GetFontCollection
,
2766 dwritefontfamily_GetFontCount
,
2767 dwritefontfamily_GetFont
,
2768 dwritefontfamily_GetFamilyNames
,
2769 dwritefontfamily_GetFirstMatchingFont
,
2770 dwritefontfamily_GetMatchingFonts
,
2771 dwritefontfamily1_GetFontLocality
,
2772 dwritefontfamily1_GetFont
,
2773 dwritefontfamily1_GetFontFaceReference
,
2774 dwritefontfamily2_GetMatchingFonts
,
2775 dwritefontfamily2_GetFontSet
,
2778 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2780 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2781 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2784 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2786 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2787 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2790 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2792 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2793 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2796 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2797 IDWriteFontCollection
**collection
)
2799 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2800 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2803 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2805 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2806 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2809 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2811 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2812 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2815 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2817 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2818 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2821 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2823 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2824 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2827 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2828 IDWriteFontFaceReference
**reference
)
2830 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2831 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2834 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2836 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2838 TRACE("%p, %p.\n", iface
, fontset
);
2840 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
2841 family
->data
->count
, fontset
);
2844 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2846 dwritefontfamilylist_QueryInterface
,
2847 dwritefontfamilylist_AddRef
,
2848 dwritefontfamilylist_Release
,
2849 dwritefontfamilylist_GetFontCollection
,
2850 dwritefontfamilylist_GetFontCount
,
2851 dwritefontfamilylist_GetFont
,
2852 dwritefontfamilylist1_GetFontLocality
,
2853 dwritefontfamilylist1_GetFont
,
2854 dwritefontfamilylist1_GetFontFaceReference
,
2855 dwritefontfamilylist2_GetFontSet
,
2858 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2859 struct dwrite_fontfamily
**family
)
2861 struct dwrite_fontfamily
*object
;
2865 object
= heap_alloc(sizeof(*object
));
2867 return E_OUTOFMEMORY
;
2869 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2870 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2871 object
->refcount
= 1;
2872 object
->collection
= collection
;
2873 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2874 object
->data
= collection
->family_data
[index
];
2875 InterlockedIncrement(&object
->data
->refcount
);
2882 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2885 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2888 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2890 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2892 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2894 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2895 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2896 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2897 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2898 IsEqualIID(riid
, &IID_IUnknown
))
2901 IDWriteFontCollection3_AddRef(iface
);
2907 if (IsEqualIID(riid
, &IID_issystemcollection
))
2910 WARN("%s not implemented.\n", debugstr_guid(riid
));
2912 return E_NOINTERFACE
;
2915 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2917 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2919 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2920 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2921 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2922 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2923 IsEqualIID(riid
, &IID_IUnknown
))
2926 IDWriteFontCollection3_AddRef(iface
);
2930 WARN("%s not implemented.\n", debugstr_guid(riid
));
2934 return E_NOINTERFACE
;
2937 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2939 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2940 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2942 TRACE("%p, refcount %d.\n", collection
, refcount
);
2947 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2949 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2950 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2953 TRACE("%p, refcount %d.\n", iface
, refcount
);
2957 factory_detach_fontcollection(collection
->factory
, iface
);
2958 for (i
= 0; i
< collection
->count
; ++i
)
2959 release_fontfamily_data(collection
->family_data
[i
]);
2960 heap_free(collection
->family_data
);
2961 heap_free(collection
);
2967 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2969 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2971 TRACE("%p.\n", iface
);
2973 return collection
->count
;
2976 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2977 IDWriteFontFamily
**ret
)
2979 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2980 struct dwrite_fontfamily
*family
;
2983 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2987 if (index
>= collection
->count
)
2990 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2991 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2996 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
3000 for (i
= 0; i
< collection
->count
; ++i
)
3002 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
3003 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
3006 for (j
= 0; j
< count
; j
++) {
3008 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
3009 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
3017 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
3018 UINT32
*index
, BOOL
*exists
)
3020 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3022 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
3024 *index
= collection_find_family(collection
, name
);
3025 *exists
= *index
!= ~0u;
3029 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
3032 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3033 struct dwrite_fontfamily
*family
;
3034 BOOL found_font
= FALSE
;
3035 IDWriteFontFile
*file
;
3036 UINT32 face_index
, count
;
3040 TRACE("%p, %p, %p.\n", iface
, face
, font
);
3045 return E_INVALIDARG
;
3048 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
3051 face_index
= IDWriteFontFace_GetIndex(face
);
3054 for (i
= 0; i
< collection
->count
; ++i
)
3056 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
3058 for (j
= 0; j
< family_data
->count
; ++j
)
3060 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
3062 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
3071 IDWriteFontFile_Release(file
);
3074 return DWRITE_E_NOFONT
;
3076 hr
= create_fontfamily(collection
, i
, &family
);
3080 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3081 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3085 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3087 FIXME("%p, %p.\n", iface
, fontset
);
3092 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3093 IDWriteFontFamily1
**ret
)
3095 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3096 struct dwrite_fontfamily
*family
;
3099 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3103 if (index
>= collection
->count
)
3106 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3107 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3112 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3113 UINT32 index
, IDWriteFontFamily2
**ret
)
3115 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3116 struct dwrite_fontfamily
*family
;
3119 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3123 if (index
>= collection
->count
)
3126 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3127 *ret
= &family
->IDWriteFontFamily2_iface
;
3132 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3133 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3134 IDWriteFontList2
**fontlist
)
3136 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3141 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3143 FIXME("%p.\n", iface
);
3145 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3148 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3150 FIXME("%p, %p.\n", iface
, fontset
);
3155 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3157 FIXME("%p.\n", iface
);
3162 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3164 dwritefontcollection_QueryInterface
,
3165 dwritefontcollection_AddRef
,
3166 dwritefontcollection_Release
,
3167 dwritefontcollection_GetFontFamilyCount
,
3168 dwritefontcollection_GetFontFamily
,
3169 dwritefontcollection_FindFamilyName
,
3170 dwritefontcollection_GetFontFromFontFace
,
3171 dwritefontcollection1_GetFontSet
,
3172 dwritefontcollection1_GetFontFamily
,
3173 dwritefontcollection2_GetFontFamily
,
3174 dwritefontcollection2_GetMatchingFonts
,
3175 dwritefontcollection2_GetFontFamilyModel
,
3176 dwritefontcollection2_GetFontSet
,
3177 dwritefontcollection3_GetExpirationEvent
,
3180 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3182 dwritesystemfontcollection_QueryInterface
,
3183 dwritefontcollection_AddRef
,
3184 dwritefontcollection_Release
,
3185 dwritefontcollection_GetFontFamilyCount
,
3186 dwritefontcollection_GetFontFamily
,
3187 dwritefontcollection_FindFamilyName
,
3188 dwritefontcollection_GetFontFromFontFace
,
3189 dwritefontcollection1_GetFontSet
,
3190 dwritefontcollection1_GetFontFamily
,
3191 dwritefontcollection2_GetFontFamily
,
3192 dwritefontcollection2_GetMatchingFonts
,
3193 dwritefontcollection2_GetFontFamilyModel
,
3194 dwritefontcollection2_GetFontSet
,
3195 dwritefontcollection3_GetExpirationEvent
,
3198 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3200 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3201 sizeof(*family_data
->fonts
)))
3203 return E_OUTOFMEMORY
;
3206 family_data
->fonts
[family_data
->count
++] = font_data
;
3207 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3208 family_data
->has_normal_face
= 1;
3209 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3210 family_data
->has_oblique_face
= 1;
3212 family_data
->has_italic_face
= 1;
3216 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3217 struct dwrite_fontfamily_data
*family
)
3219 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3220 sizeof(*collection
->family_data
)))
3222 return E_OUTOFMEMORY
;
3225 collection
->family_data
[collection
->count
++] = family
;
3229 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3231 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3232 collection
->refcount
= 1;
3233 collection
->count
= 0;
3234 collection
->size
= 0;
3235 collection
->family_data
= NULL
;
3240 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3242 IDWriteFontFileLoader
*loader
;
3249 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3253 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3257 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3258 IDWriteFontFileLoader_Release(loader
);
3265 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3267 BOOL exists
= FALSE
;
3272 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3273 if (FAILED(hr
) || !exists
)
3276 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3279 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3283 while (isspaceW(*in
))
3287 if (!(len
= strlenW(in
)))
3290 while (isspaceW(in
[len
-1]))
3293 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3302 INT len
; /* token length */
3303 INT fulllen
; /* full length including following separators */
3306 static inline BOOL
is_name_separator_char(WCHAR ch
)
3308 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3311 struct name_pattern
{
3312 const WCHAR
*part1
; /* NULL indicates end of list */
3313 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3316 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3318 const struct name_pattern
*pattern
;
3319 struct name_token
*token
;
3322 while ((pattern
= &patterns
[i
++])->part1
) {
3323 int len_part1
= strlenW(pattern
->part1
);
3324 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3326 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3327 if (len_part2
== 0) {
3328 /* simple case with single part pattern */
3329 if (token
->len
!= len_part1
)
3332 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3333 if (match
) *match
= *token
;
3334 list_remove(&token
->entry
);
3340 struct name_token
*next_token
;
3341 struct list
*next_entry
;
3343 /* pattern parts are stored in reading order, tokens list is reversed */
3344 if (token
->len
< len_part2
)
3347 /* it's possible to have combined string as a token, like ExtraCondensed */
3348 if (token
->len
== len_part1
+ len_part2
) {
3349 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3352 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3355 /* combined string match */
3356 if (match
) *match
= *token
;
3357 list_remove(&token
->entry
);
3362 /* now it's only possible to have two tokens matched to respective pattern parts */
3363 if (token
->len
!= len_part2
)
3366 next_entry
= list_next(tokens
, &token
->entry
);
3368 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3369 if (next_token
->len
!= len_part1
)
3372 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3375 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3378 /* both parts matched, remove tokens */
3380 match
->ptr
= next_token
->ptr
;
3381 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3383 list_remove(&token
->entry
);
3384 list_remove(&next_token
->entry
);
3385 heap_free(next_token
);
3400 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3402 static const WCHAR itaW
[] = {'i','t','a',0};
3403 static const WCHAR italW
[] = {'i','t','a','l',0};
3404 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3405 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3407 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3408 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3409 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3410 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3412 static const struct name_pattern italic_patterns
[] = {
3421 static const struct name_pattern oblique_patterns
[] = {
3430 /* italic patterns first */
3431 if (match_pattern_list(tokens
, italic_patterns
, match
))
3432 return DWRITE_FONT_STYLE_ITALIC
;
3434 /* oblique patterns */
3435 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3436 return DWRITE_FONT_STYLE_OBLIQUE
;
3441 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3442 struct name_token
*match
)
3444 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3445 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3446 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3447 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3448 static const WCHAR wideW
[] = {'w','i','d','e',0};
3449 static const WCHAR condW
[] = {'c','o','n','d',0};
3451 static const struct name_pattern ultracondensed_patterns
[] = {
3452 { extraW
, compressedW
},
3453 { extW
, compressedW
},
3454 { ultraW
, compressedW
},
3455 { ultraW
, condensedW
},
3460 static const struct name_pattern extracondensed_patterns
[] = {
3462 { extraW
, condensedW
},
3463 { extW
, condensedW
},
3469 static const struct name_pattern semicondensed_patterns
[] = {
3472 { semiW
, condensedW
},
3477 static const struct name_pattern semiexpanded_patterns
[] = {
3479 { semiW
, expandedW
},
3480 { semiW
, extendedW
},
3484 static const struct name_pattern extraexpanded_patterns
[] = {
3485 { extraW
, expandedW
},
3486 { extW
, expandedW
},
3487 { extraW
, extendedW
},
3488 { extW
, extendedW
},
3492 static const struct name_pattern ultraexpanded_patterns
[] = {
3493 { ultraW
, expandedW
},
3494 { ultraW
, extendedW
},
3498 static const struct name_pattern condensed_patterns
[] = {
3504 static const struct name_pattern expanded_patterns
[] = {
3510 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3511 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3513 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3514 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3516 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3517 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3519 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3520 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3522 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3523 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3525 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3526 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3528 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3529 return DWRITE_FONT_STRETCH_CONDENSED
;
3531 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3532 return DWRITE_FONT_STRETCH_EXPANDED
;
3537 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3538 struct name_token
*match
)
3540 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3541 static const WCHAR nordW
[] = {'n','o','r','d',0};
3543 static const struct name_pattern thin_patterns
[] = {
3550 static const struct name_pattern extralight_patterns
[] = {
3557 static const struct name_pattern semilight_patterns
[] = {
3562 static const struct name_pattern demibold_patterns
[] = {
3568 static const struct name_pattern extrabold_patterns
[] = {
3575 static const struct name_pattern extrablack_patterns
[] = {
3582 static const struct name_pattern bold_patterns
[] = {
3587 static const struct name_pattern thin2_patterns
[] = {
3592 static const struct name_pattern light_patterns
[] = {
3597 static const struct name_pattern medium_patterns
[] = {
3602 static const struct name_pattern black_patterns
[] = {
3609 static const struct name_pattern demibold2_patterns
[] = {
3614 static const struct name_pattern extrabold2_patterns
[] = {
3619 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3620 matching pattern. */
3622 if (match_pattern_list(tokens
, thin_patterns
, match
))
3623 return DWRITE_FONT_WEIGHT_THIN
;
3625 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3626 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3628 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3629 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3631 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3632 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3634 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3635 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3637 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3638 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3640 if (match_pattern_list(tokens
, bold_patterns
, match
))
3641 return DWRITE_FONT_WEIGHT_BOLD
;
3643 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3644 return DWRITE_FONT_WEIGHT_THIN
;
3646 if (match_pattern_list(tokens
, light_patterns
, match
))
3647 return DWRITE_FONT_WEIGHT_LIGHT
;
3649 if (match_pattern_list(tokens
, medium_patterns
, match
))
3650 return DWRITE_FONT_WEIGHT_MEDIUM
;
3652 if (match_pattern_list(tokens
, black_patterns
, match
))
3653 return DWRITE_FONT_WEIGHT_BLACK
;
3655 if (match_pattern_list(tokens
, black_patterns
, match
))
3656 return DWRITE_FONT_WEIGHT_BLACK
;
3658 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3659 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3661 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3662 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3664 /* FIXME: use abbreviated names to extract weight */
3669 struct knownweight_entry
{
3671 DWRITE_FONT_WEIGHT weight
;
3674 static int compare_knownweights(const void *a
, const void* b
)
3676 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3677 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3680 if (target
> entry
->weight
)
3682 else if (target
< entry
->weight
)
3688 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3690 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3691 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3692 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3693 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3694 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3695 static const WCHAR thinW
[] = {'T','h','i','n',0};
3696 static const WCHAR lightW
[] = {'L','i','g','h','t',0};
3697 static const WCHAR mediumW
[] = {'M','e','d','i','u','m',0};
3698 static const WCHAR blackW
[] = {'B','l','a','c','k',0};
3699 const struct knownweight_entry
*ptr
;
3701 static const struct knownweight_entry knownweights
[] = {
3702 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3703 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3704 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3705 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3706 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3707 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3708 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3709 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3710 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3711 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3714 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3715 compare_knownweights
);
3721 strcpyW(nameW
, ptr
->nameW
);
3725 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3727 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3728 strW
[name
->len
] = 0;
3731 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3732 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3734 static const WCHAR bookW
[] = {'B','o','o','k',0};
3735 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3736 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3737 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3738 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3740 static const WCHAR
*regular_patterns
[] = {
3749 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3753 len
= strlenW(facenameW
);
3755 /* remove rightmost regular variant from face name */
3756 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3757 int pattern_len
= strlenW(ptr
);
3760 if (pattern_len
> len
)
3763 src
= facenameW
+ len
- pattern_len
;
3764 while (src
>= facenameW
) {
3765 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3766 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3767 len
= strlenW(facenameW
);
3779 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3787 struct name_token
*token
= heap_alloc(sizeof(*token
));
3792 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3798 /* skip separators */
3799 while (is_name_separator_char(*ptr
)) {
3804 list_add_head(tokens
, &token
->entry
);
3808 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3810 struct name_token
*token
, *token2
;
3811 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3814 list_remove(&token
->entry
);
3816 /* don't include last separator */
3817 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3818 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3826 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3828 struct name_token stretch_name
, weight_name
, style_name
;
3829 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3830 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3831 const WCHAR
*regular_ptr
= NULL
;
3832 DWRITE_FONT_STRETCH stretch
;
3833 DWRITE_FONT_WEIGHT weight
;
3837 /* remove leading and trailing spaces from family and face name */
3838 trim_spaces(familyW
, familynameW
);
3839 len
= trim_spaces(faceW
, facenameW
);
3841 /* remove rightmost regular variant from face name */
3842 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3844 /* append face name to family name, FIXME check if face name is a substring of family name */
3846 strcatW(familynameW
, spaceW
);
3847 strcatW(familynameW
, facenameW
);
3850 /* tokenize with " .-_" */
3851 fontname_tokenize(&tokens
, familynameW
);
3853 /* extract and resolve style */
3854 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3856 /* extract stretch */
3857 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3859 /* extract weight */
3860 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3862 /* resolve weight */
3863 if (weight
!= font
->weight
) {
3864 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3865 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3866 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3867 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3868 !(abs(weight
- font
->weight
) <= 150 &&
3869 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3870 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3871 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3873 font
->weight
= weight
;
3877 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3878 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3879 stretch itself is normal (extracted stretch is never normal). */
3880 if (stretch
!= font
->stretch
) {
3881 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3882 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3883 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3885 font
->stretch
= stretch
;
3889 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3891 /* get final combined string from what's left in token list, list is released */
3892 fontname_tokens_to_str(&tokens
, finalW
);
3894 if (!strcmpW(familyW
, finalW
))
3897 /* construct face name */
3898 strcpyW(familyW
, finalW
);
3900 /* resolved weight name */
3901 if (weight_name
.ptr
)
3902 font_name_token_to_str(&weight_name
, weightW
);
3903 /* ignore normal weight */
3904 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3906 /* for known weight values use appropriate names */
3907 else if (is_known_weight_value(font
->weight
, weightW
)) {
3909 /* use Wnnn format as a fallback in case weight is not one of known values */
3911 static const WCHAR fmtW
[] = {'W','%','d',0};
3912 sprintfW(weightW
, fmtW
, font
->weight
);
3915 /* resolved stretch name */
3916 if (stretch_name
.ptr
)
3917 font_name_token_to_str(&stretch_name
, stretchW
);
3918 /* ignore normal stretch */
3919 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3921 /* use predefined stretch names */
3923 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3924 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3925 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3926 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3927 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3928 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3930 static const WCHAR
*stretchnamesW
[] = {
3931 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3936 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3942 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3945 /* resolved style name */
3947 font_name_token_to_str(&style_name
, styleW
);
3948 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3950 /* use predefined names */
3952 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3953 strcpyW(styleW
, italicW
);
3955 strcpyW(styleW
, obliqueW
);
3958 /* use Regular match if it was found initially */
3959 if (!*weightW
&& !*stretchW
&& !*styleW
)
3960 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3964 strcpyW(faceW
, stretchW
);
3967 strcatW(faceW
, spaceW
);
3968 strcatW(faceW
, weightW
);
3972 strcatW(faceW
, spaceW
);
3973 strcatW(faceW
, styleW
);
3977 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3981 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3983 static const float width_axis_values
[] =
3985 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3986 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
3987 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
3988 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
3989 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
3990 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
3991 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
3992 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
3993 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
3994 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
3997 struct file_stream_desc stream_desc
;
3998 struct dwrite_font_props props
;
3999 struct dwrite_font_data
*data
;
4000 WCHAR familyW
[255], faceW
[255];
4005 data
= heap_alloc_zero(sizeof(*data
));
4007 return E_OUTOFMEMORY
;
4010 data
->file
= desc
->file
;
4011 data
->face_index
= desc
->index
;
4012 data
->face_type
= desc
->face_type
;
4013 IDWriteFontFile_AddRef(data
->file
);
4015 stream_desc
.stream
= desc
->stream
;
4016 stream_desc
.face_type
= desc
->face_type
;
4017 stream_desc
.face_index
= desc
->index
;
4018 opentype_get_font_properties(&stream_desc
, &props
);
4019 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
4020 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
4022 /* get family name from font file */
4023 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
4025 WARN("unable to get family name from font\n");
4026 release_font_data(data
);
4030 data
->style
= props
.style
;
4031 data
->stretch
= props
.stretch
;
4032 data
->weight
= props
.weight
;
4033 data
->panose
= props
.panose
;
4034 data
->fontsig
= props
.fontsig
;
4035 data
->lf
= props
.lf
;
4036 data
->flags
= props
.flags
;
4038 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4039 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
4040 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
4041 set_en_localizedstring(data
->family_names
, familyW
);
4042 set_en_localizedstring(data
->names
, faceW
);
4045 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4047 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
4048 data
->axis
[0].value
= props
.weight
;
4049 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
4050 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
4051 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
4052 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
4058 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS simulations
,
4059 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
4061 struct dwrite_font_data
*data
;
4065 data
= heap_alloc_zero(sizeof(*data
));
4067 return E_OUTOFMEMORY
;
4071 data
->simulations
|= simulations
;
4072 if (simulations
& DWRITE_FONT_SIMULATIONS_BOLD
)
4073 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
4074 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4075 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4076 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4078 IDWriteFontFile_AddRef(data
->file
);
4079 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4081 create_localizedstrings(&data
->names
);
4082 add_localizedstring(data
->names
, enusW
, facenameW
);
4084 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4090 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4092 struct dwrite_fontfamily_data
*data
;
4094 data
= heap_alloc_zero(sizeof(*data
));
4096 return E_OUTOFMEMORY
;
4099 data
->familyname
= familyname
;
4100 IDWriteLocalizedStrings_AddRef(familyname
);
4107 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4109 size_t i
, j
, heaviest
;
4111 for (i
= 0; i
< family
->count
; ++i
)
4113 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4116 if (family
->fonts
[i
]->bold_sim_tested
)
4119 family
->fonts
[i
]->bold_sim_tested
= 1;
4120 for (j
= i
; j
< family
->count
; ++j
)
4122 if (family
->fonts
[j
]->bold_sim_tested
)
4125 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4126 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4127 if (family
->fonts
[j
]->weight
> weight
) {
4128 weight
= family
->fonts
[j
]->weight
;
4131 family
->fonts
[j
]->bold_sim_tested
= 1;
4135 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4136 static const struct name_pattern weightsim_patterns
[] = {
4151 WCHAR facenameW
[255], initialW
[255];
4152 struct dwrite_font_data
*boldface
;
4155 /* add Bold simulation based on heaviest face data */
4157 /* Simulated face name should only contain Bold as weight term,
4158 so remove existing regular and weight terms. */
4159 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4160 facename_remove_regular_term(initialW
, -1);
4162 /* remove current weight pattern */
4163 fontname_tokenize(&tokens
, initialW
);
4164 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4165 fontname_tokens_to_str(&tokens
, facenameW
);
4167 /* Bold suffix for new name */
4169 strcatW(facenameW
, spaceW
);
4170 strcatW(facenameW
, boldW
);
4172 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4173 boldface
->bold_sim_tested
= 1;
4174 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4175 fontfamily_add_font(family
, boldface
);
4181 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4185 for (i
= 0; i
< family
->count
; ++i
)
4187 UINT32 regular
= ~0u, oblique
= ~0u;
4188 struct dwrite_font_data
*obliqueface
;
4189 WCHAR facenameW
[255];
4191 if (family
->fonts
[i
]->oblique_sim_tested
)
4194 family
->fonts
[i
]->oblique_sim_tested
= 1;
4195 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4197 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4200 /* find regular style with same weight/stretch values */
4201 for (j
= i
; j
< family
->count
; ++j
)
4203 if (family
->fonts
[j
]->oblique_sim_tested
)
4206 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4207 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4209 family
->fonts
[j
]->oblique_sim_tested
= 1;
4210 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4213 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4217 if (regular
!= ~0u && oblique
!= ~0u)
4221 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4225 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4229 /* add oblique simulation based on this regular face */
4231 /* remove regular term if any, append 'Oblique' */
4232 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4233 facename_remove_regular_term(facenameW
, -1);
4236 strcatW(facenameW
, spaceW
);
4237 strcatW(facenameW
, obliqueW
);
4239 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4240 obliqueface
->oblique_sim_tested
= 1;
4241 obliqueface
->lf
.lfItalic
= 1;
4242 fontfamily_add_font(family
, obliqueface
);
4247 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4248 const WCHAR
*replacement_name
)
4250 UINT32 i
= collection_find_family(collection
, replacement_name
);
4251 struct dwrite_fontfamily_data
*target
;
4252 IDWriteLocalizedStrings
*strings
;
4255 /* replacement does not exist */
4259 hr
= create_localizedstrings(&strings
);
4263 /* add a new family with target name, reuse font data from replacement */
4264 add_localizedstring(strings
, enusW
, target_name
);
4265 hr
= init_fontfamily_data(strings
, &target
);
4267 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4270 for (i
= 0; i
< replacement
->count
; ++i
)
4272 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4273 addref_font_data(replacement
->fonts
[i
]);
4276 fontcollection_add_family(collection
, target
);
4277 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4278 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4280 IDWriteLocalizedStrings_Release(strings
);
4284 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4285 system font collections. */
4286 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4288 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4293 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4296 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4301 max_namelen
++; /* returned value doesn't include room for '\0' */
4302 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4303 data
= heap_alloc(max_datalen
);
4305 datalen
= max_datalen
;
4306 namelen
= max_namelen
;
4307 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4308 if (collection_find_family(collection
, name
) == ~0u) {
4309 if (type
== REG_MULTI_SZ
) {
4310 WCHAR
*replacement
= data
;
4311 while (*replacement
) {
4312 if (fontcollection_add_replacement(collection
, name
, replacement
))
4314 replacement
+= strlenW(replacement
) + 1;
4317 else if (type
== REG_SZ
)
4318 fontcollection_add_replacement(collection
, name
, data
);
4321 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4323 datalen
= max_datalen
;
4324 namelen
= max_namelen
;
4332 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4333 IDWriteFontCollection3
**ret
)
4335 struct fontfile_enum
{
4337 IDWriteFontFile
*file
;
4339 struct fontfile_enum
*fileenum
, *fileenum2
;
4340 struct dwrite_fontcollection
*collection
;
4341 struct list scannedfiles
;
4342 BOOL current
= FALSE
;
4348 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4349 if (!collection
) return E_OUTOFMEMORY
;
4351 hr
= init_font_collection(collection
, is_system
);
4353 heap_free(collection
);
4357 *ret
= &collection
->IDWriteFontCollection3_iface
;
4359 TRACE("building font collection:\n");
4361 list_init(&scannedfiles
);
4362 while (hr
== S_OK
) {
4363 DWRITE_FONT_FACE_TYPE face_type
;
4364 DWRITE_FONT_FILE_TYPE file_type
;
4365 BOOL supported
, same
= FALSE
;
4366 IDWriteFontFileStream
*stream
;
4367 IDWriteFontFile
*file
;
4371 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4372 if (FAILED(hr
) || !current
)
4375 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4379 /* check if we've scanned this file already */
4380 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4381 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4386 IDWriteFontFile_Release(file
);
4390 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4391 IDWriteFontFile_Release(file
);
4395 /* Unsupported formats are skipped. */
4396 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4397 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4398 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4399 IDWriteFontFileStream_Release(stream
);
4400 IDWriteFontFile_Release(file
);
4405 /* add to scanned list */
4406 fileenum
= heap_alloc(sizeof(*fileenum
));
4407 fileenum
->file
= file
;
4408 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4410 for (i
= 0; i
< face_count
; ++i
)
4412 struct dwrite_font_data
*font_data
;
4413 struct fontface_desc desc
;
4417 desc
.factory
= factory
;
4418 desc
.face_type
= face_type
;
4420 desc
.stream
= stream
;
4422 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4423 desc
.font_data
= NULL
;
4425 /* Allocate an initialize new font data structure. */
4426 hr
= init_font_data(&desc
, &font_data
);
4429 /* move to next one */
4434 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4436 /* ignore dot named faces */
4437 if (familyW
[0] == '.')
4439 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4440 release_font_data(font_data
);
4444 index
= collection_find_family(collection
, familyW
);
4446 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4448 struct dwrite_fontfamily_data
*family_data
;
4450 /* create and init new family */
4451 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4453 /* add font to family, family - to collection */
4454 hr
= fontfamily_add_font(family_data
, font_data
);
4456 hr
= fontcollection_add_family(collection
, family_data
);
4459 release_fontfamily_data(family_data
);
4467 IDWriteFontFileStream_Release(stream
);
4470 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4471 IDWriteFontFile_Release(fileenum
->file
);
4472 list_remove(&fileenum
->entry
);
4473 heap_free(fileenum
);
4476 for (i
= 0; i
< collection
->count
; ++i
)
4478 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4479 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4483 fontcollection_add_replacements(collection
);
4485 collection
->factory
= factory
;
4486 IDWriteFactory7_AddRef(factory
);
4491 struct system_fontfile_enumerator
4493 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4496 IDWriteFactory7
*factory
;
4501 DWORD filename_size
;
4504 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4506 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4509 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4511 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4512 IDWriteFontFileEnumerator_AddRef(iface
);
4517 WARN("%s not implemented.\n", debugstr_guid(riid
));
4521 return E_NOINTERFACE
;
4524 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4526 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4527 return InterlockedIncrement(&enumerator
->refcount
);
4530 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4532 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4533 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
4537 IDWriteFactory7_Release(enumerator
->factory
);
4538 RegCloseKey(enumerator
->hkey
);
4539 heap_free(enumerator
->filename
);
4540 heap_free(enumerator
);
4546 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4550 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4551 if (!strchrW(filename
, '\\')) {
4552 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4553 WCHAR fullpathW
[MAX_PATH
];
4555 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4556 strcatW(fullpathW
, fontsW
);
4557 strcatW(fullpathW
, filename
);
4559 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4562 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4567 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4569 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4573 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4576 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4579 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4581 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4582 WCHAR name_buf
[256], *name
= name_buf
;
4583 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4588 enumerator
->index
++;
4590 /* iterate until we find next string value */
4593 name_count
= max_name_count
;
4594 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4596 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4597 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4598 if (r
== ERROR_MORE_DATA
) {
4599 if (name_count
>= max_name_count
) {
4600 if (name
!= name_buf
) heap_free(name
);
4601 max_name_count
*= 2;
4602 name
= heap_alloc(max_name_count
* sizeof(*name
));
4603 if (!name
) return E_OUTOFMEMORY
;
4605 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4606 heap_free(enumerator
->filename
);
4607 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4608 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4609 if (!enumerator
->filename
) {
4615 } while (r
== ERROR_MORE_DATA
);
4617 if (r
!= ERROR_SUCCESS
) {
4618 enumerator
->filename
[0] = 0;
4621 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4622 if (type
== REG_SZ
&& *name
!= '@') {
4626 enumerator
->index
++;
4628 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4631 if (name
!= name_buf
) heap_free(name
);
4635 static const IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4637 systemfontfileenumerator_QueryInterface
,
4638 systemfontfileenumerator_AddRef
,
4639 systemfontfileenumerator_Release
,
4640 systemfontfileenumerator_MoveNext
,
4641 systemfontfileenumerator_GetCurrentFontFile
4644 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4646 struct system_fontfile_enumerator
*enumerator
;
4647 static const WCHAR fontslistW
[] = {
4648 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4649 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4650 'F','o','n','t','s',0
4655 enumerator
= heap_alloc(sizeof(*enumerator
));
4657 return E_OUTOFMEMORY
;
4659 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4660 enumerator
->refcount
= 1;
4661 enumerator
->factory
= factory
;
4662 enumerator
->index
= -1;
4663 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4664 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4665 if (!enumerator
->filename
) {
4666 heap_free(enumerator
);
4667 return E_OUTOFMEMORY
;
4670 IDWriteFactory7_AddRef(factory
);
4672 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4674 ERR("failed to open fonts list key\n");
4675 IDWriteFactory7_Release(factory
);
4676 heap_free(enumerator
->filename
);
4677 heap_free(enumerator
);
4681 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4686 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4688 IDWriteFontFileEnumerator
*enumerator
;
4693 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4697 TRACE("building system font collection for factory %p\n", factory
);
4698 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4699 IDWriteFontFileEnumerator_Release(enumerator
);
4703 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4704 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4706 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};
4707 static const WCHAR emptyW
[] = {0};
4708 struct dwrite_fontfamily_data
*family_data
;
4709 IDWriteLocalizedStrings
*names
;
4710 DWRITE_FONT_FACE_TYPE face_type
;
4711 DWRITE_FONT_FILE_TYPE file_type
;
4712 IDWriteFontFileStream
*stream
;
4713 IDWriteFontFile
*file
;
4714 UINT32 face_count
, i
;
4718 /* create font file from this path */
4719 hr
= create_local_file_reference(factory
, pathW
, &file
);
4723 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4724 IDWriteFontFile_Release(file
);
4728 /* Unsupported formats are skipped. */
4729 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4730 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4731 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4732 IDWriteFontFileStream_Release(stream
);
4733 IDWriteFontFile_Release(file
);
4737 /* create and init new family */
4739 /* Family names are added for non-specific locale, represented with empty string.
4740 Default family appears with empty family name. */
4741 create_localizedstrings(&names
);
4742 if (!strcmpiW(keynameW
, defaultfontW
))
4743 add_localizedstring(names
, emptyW
, emptyW
);
4745 add_localizedstring(names
, emptyW
, keynameW
);
4747 hr
= init_fontfamily_data(names
, &family_data
);
4748 IDWriteLocalizedStrings_Release(names
);
4750 IDWriteFontFile_Release(file
);
4754 /* fill with faces */
4755 for (i
= 0; i
< face_count
; i
++) {
4756 struct dwrite_font_data
*font_data
;
4757 struct fontface_desc desc
;
4759 /* Allocate new font data structure. */
4760 desc
.factory
= factory
;
4761 desc
.face_type
= face_type
;
4764 desc
.stream
= stream
;
4765 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4766 desc
.font_data
= NULL
;
4768 hr
= init_font_data(&desc
, &font_data
);
4772 /* add font to family */
4773 hr
= fontfamily_add_font(family_data
, font_data
);
4775 release_font_data(font_data
);
4778 /* add family to collection */
4779 hr
= fontcollection_add_family(collection
, family_data
);
4781 release_fontfamily_data(family_data
);
4782 IDWriteFontFileStream_Release(stream
);
4783 IDWriteFontFile_Release(file
);
4788 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4790 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4791 struct dwrite_fontcollection
*collection
;
4792 static const WCHAR emptyW
[] = {0};
4793 WCHAR eudckeypathW
[16];
4801 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4805 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4806 if (!collection
) return E_OUTOFMEMORY
;
4808 hr
= init_font_collection(collection
, FALSE
);
4810 heap_free(collection
);
4814 *ret
= &collection
->IDWriteFontCollection3_iface
;
4815 collection
->factory
= factory
;
4816 IDWriteFactory7_AddRef(factory
);
4818 /* return empty collection if EUDC fonts are not configured */
4819 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4820 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4823 retval
= ERROR_SUCCESS
;
4825 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4826 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4827 DWORD type
, path_len
, name_len
;
4829 path_len
= ARRAY_SIZE(pathW
);
4830 name_len
= ARRAY_SIZE(keynameW
);
4831 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4832 if (retval
|| type
!= REG_SZ
)
4835 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4837 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4839 RegCloseKey(eudckey
);
4841 /* try to add global default if not defined for specific codepage */
4843 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4845 if (FAILED(hr
) || !exists
) {
4846 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4847 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4849 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4852 /* EUDC collection offers simulated faces too */
4853 for (i
= 0; i
< collection
->count
; ++i
)
4855 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4856 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4862 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4864 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
4866 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4869 IDWriteFontFile_AddRef(iface
);
4873 WARN("%s not implemented.\n", debugstr_guid(riid
));
4876 return E_NOINTERFACE
;
4879 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4881 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4882 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
4884 TRACE("%p, refcount %d.\n", iface
, refcount
);
4889 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4891 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4892 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
4894 TRACE("%p, refcount %d.\n", iface
, refcount
);
4898 IDWriteFontFileLoader_Release(file
->loader
);
4900 IDWriteFontFileStream_Release(file
->stream
);
4901 heap_free(file
->reference_key
);
4908 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
4910 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4912 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
4914 *key
= file
->reference_key
;
4915 *key_size
= file
->key_size
;
4920 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
4922 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4924 TRACE("%p, %p.\n", iface
, loader
);
4926 *loader
= file
->loader
;
4927 IDWriteFontFileLoader_AddRef(*loader
);
4932 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4933 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4935 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4936 IDWriteFontFileStream
*stream
;
4939 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
4941 *is_supported
= FALSE
;
4942 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4944 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4947 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
4951 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4953 /* TODO: Further Analysis */
4954 IDWriteFontFileStream_Release(stream
);
4958 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
4960 dwritefontfile_QueryInterface
,
4961 dwritefontfile_AddRef
,
4962 dwritefontfile_Release
,
4963 dwritefontfile_GetReferenceKey
,
4964 dwritefontfile_GetLoader
,
4965 dwritefontfile_Analyze
,
4968 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4969 IDWriteFontFile
**ret
)
4971 struct dwrite_fontfile
*file
;
4976 file
= heap_alloc(sizeof(*file
));
4977 key
= heap_alloc(key_size
);
4978 if (!file
|| !key
) {
4981 return E_OUTOFMEMORY
;
4984 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4986 IDWriteFontFileLoader_AddRef(loader
);
4987 file
->loader
= loader
;
4988 file
->stream
= NULL
;
4989 file
->reference_key
= key
;
4990 memcpy(file
->reference_key
, reference_key
, key_size
);
4991 file
->key_size
= key_size
;
4993 *ret
= &file
->IDWriteFontFile_iface
;
4998 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
5000 struct file_stream_desc stream_desc
;
5001 struct dwrite_font_data
*font_data
;
5002 struct dwrite_fontface
*fontface
;
5008 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
5010 return E_OUTOFMEMORY
;
5012 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
5013 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
5014 fontface
->refcount
= 1;
5015 fontface
->type
= desc
->face_type
;
5016 fontface
->vdmx
.exists
= TRUE
;
5017 fontface
->gasp
.exists
= TRUE
;
5018 fontface
->cpal
.exists
= TRUE
;
5019 fontface
->colr
.exists
= TRUE
;
5020 fontface
->kern
.exists
= TRUE
;
5021 fontface
->index
= desc
->index
;
5022 fontface
->simulations
= desc
->simulations
;
5023 fontface
->factory
= desc
->factory
;
5024 IDWriteFactory7_AddRef(fontface
->factory
);
5025 fontface
->file
= desc
->file
;
5026 IDWriteFontFile_AddRef(fontface
->file
);
5027 fontface
->stream
= desc
->stream
;
5028 IDWriteFontFileStream_AddRef(fontface
->stream
);
5030 stream_desc
.stream
= fontface
->stream
;
5031 stream_desc
.face_type
= desc
->face_type
;
5032 stream_desc
.face_index
= desc
->index
;
5033 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
5034 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
5035 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
5036 /* TODO: test what happens if caret is already slanted */
5037 if (fontface
->caret
.slopeRise
== 1) {
5038 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
5039 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
5042 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
5044 /* Font properties are reused from font object when 'normal' face creation path is used:
5045 collection -> family -> matching font -> fontface.
5047 If face is created directly from factory we have to go through properties resolution.
5049 if (desc
->font_data
)
5051 font_data
= addref_font_data(desc
->font_data
);
5055 hr
= init_font_data(desc
, &font_data
);
5058 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5063 fontface
->weight
= font_data
->weight
;
5064 fontface
->style
= font_data
->style
;
5065 fontface
->stretch
= font_data
->stretch
;
5066 fontface
->panose
= font_data
->panose
;
5067 fontface
->fontsig
= font_data
->fontsig
;
5068 fontface
->lf
= font_data
->lf
;
5069 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5070 fontface
->names
= font_data
->names
;
5071 if (fontface
->names
)
5072 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5073 fontface
->family_names
= font_data
->family_names
;
5074 if (fontface
->family_names
)
5075 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5076 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5077 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5079 if (fontface
->info_strings
[i
])
5080 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5082 fontface
->cmap
.stream
= fontface
->stream
;
5083 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5084 release_font_data(font_data
);
5086 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5088 *ret
= &fontface
->IDWriteFontFace5_iface
;
5093 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5100 struct local_cached_stream
5103 IDWriteFontFileStream
*stream
;
5104 struct local_refkey
*key
;
5108 struct dwrite_localfontfilestream
5110 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5113 struct local_cached_stream
*entry
;
5114 const void *file_ptr
;
5118 struct dwrite_localfontfileloader
5120 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5123 struct list streams
;
5124 CRITICAL_SECTION cs
;
5127 static struct dwrite_localfontfileloader local_fontfile_loader
;
5129 struct dwrite_inmemory_stream_data
5137 struct dwrite_inmemory_filestream
5139 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5142 struct dwrite_inmemory_stream_data
*data
;
5145 struct dwrite_inmemory_fileloader
5147 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5150 struct dwrite_inmemory_stream_data
**streams
;
5155 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5157 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5160 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5162 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5165 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5167 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5170 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5172 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5175 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5177 if (InterlockedDecrement(&stream
->refcount
) == 0)
5180 IUnknown_Release(stream
->owner
);
5182 heap_free(stream
->data
);
5187 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5189 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5191 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5193 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5194 IsEqualIID(riid
, &IID_IUnknown
))
5197 if (InterlockedIncrement(&stream
->refcount
) == 1)
5199 InterlockedDecrement(&stream
->refcount
);
5206 WARN("%s not implemented.\n", debugstr_guid(riid
));
5209 return E_NOINTERFACE
;
5212 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5214 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5215 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5217 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5222 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5224 list_remove(&stream
->entry
);
5225 heap_free(stream
->key
);
5229 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5231 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5232 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5234 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5238 UnmapViewOfFile(stream
->file_ptr
);
5240 EnterCriticalSection(&local_fontfile_loader
.cs
);
5241 release_cached_stream(stream
->entry
);
5242 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5250 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5251 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5253 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5255 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5256 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5258 *fragment_context
= NULL
;
5260 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5262 *fragment_start
= NULL
;
5266 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5270 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5272 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5275 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5277 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5279 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5281 *size
= stream
->size
;
5285 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5287 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5290 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5292 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5293 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5294 *last_writetime
= li
.QuadPart
;
5299 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5301 localfontfilestream_QueryInterface
,
5302 localfontfilestream_AddRef
,
5303 localfontfilestream_Release
,
5304 localfontfilestream_ReadFileFragment
,
5305 localfontfilestream_ReleaseFileFragment
,
5306 localfontfilestream_GetFileSize
,
5307 localfontfilestream_GetLastWriteTime
5310 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5311 IDWriteFontFileStream
**ret
)
5313 struct dwrite_localfontfilestream
*object
;
5317 if (!(object
= heap_alloc(sizeof(*object
))))
5318 return E_OUTOFMEMORY
;
5320 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5321 object
->refcount
= 1;
5323 object
->file_ptr
= file_ptr
;
5324 object
->size
= size
;
5325 object
->entry
= entry
;
5327 *ret
= &object
->IDWriteFontFileStream_iface
;
5332 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5334 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5336 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5337 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5338 IsEqualIID(riid
, &IID_IUnknown
))
5341 IDWriteLocalFontFileLoader_AddRef(iface
);
5345 WARN("%s not implemented.\n", debugstr_guid(riid
));
5348 return E_NOINTERFACE
;
5351 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5353 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5354 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5356 TRACE("%p, refcount %d.\n", iface
, refcount
);
5361 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5363 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5364 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5366 TRACE("%p, refcount %d.\n", iface
, refcount
);
5371 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5373 const struct local_refkey
*refkey
= key
;
5374 struct local_cached_stream
*stream
;
5375 IDWriteFontFileStream
*filestream
;
5376 HANDLE file
, mapping
;
5383 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5384 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5385 if (file
== INVALID_HANDLE_VALUE
) {
5386 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5390 GetFileSizeEx(file
, &size
);
5391 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5396 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5397 CloseHandle(mapping
);
5399 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5403 stream
= heap_alloc(sizeof(*stream
));
5405 UnmapViewOfFile(file_ptr
);
5406 return E_OUTOFMEMORY
;
5409 stream
->key
= heap_alloc(key_size
);
5411 UnmapViewOfFile(file_ptr
);
5413 return E_OUTOFMEMORY
;
5416 stream
->key_size
= key_size
;
5417 memcpy(stream
->key
, key
, key_size
);
5419 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5421 UnmapViewOfFile(file_ptr
);
5422 heap_free(stream
->key
);
5427 stream
->stream
= filestream
;
5434 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5435 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5437 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5438 struct local_cached_stream
*stream
;
5441 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5443 EnterCriticalSection(&loader
->cs
);
5447 /* search cache first */
5448 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5450 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5451 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5456 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5458 list_add_head(&loader
->streams
, &stream
->entry
);
5459 *ret
= stream
->stream
;
5462 LeaveCriticalSection(&loader
->cs
);
5467 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5468 UINT32 key_size
, UINT32
*length
)
5470 const struct local_refkey
*refkey
= key
;
5472 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5474 *length
= strlenW(refkey
->name
);
5478 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5479 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5481 const struct local_refkey
*refkey
= key
;
5483 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5485 if (length
< strlenW(refkey
->name
))
5486 return E_INVALIDARG
;
5488 strcpyW(path
, refkey
->name
);
5492 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5493 UINT32 key_size
, FILETIME
*writetime
)
5495 const struct local_refkey
*refkey
= key
;
5497 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5499 *writetime
= refkey
->writetime
;
5503 static const IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5505 localfontfileloader_QueryInterface
,
5506 localfontfileloader_AddRef
,
5507 localfontfileloader_Release
,
5508 localfontfileloader_CreateStreamFromKey
,
5509 localfontfileloader_GetFilePathLengthFromKey
,
5510 localfontfileloader_GetFilePathFromKey
,
5511 localfontfileloader_GetLastWriteTimeFromKey
5514 void init_local_fontfile_loader(void)
5516 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5517 local_fontfile_loader
.refcount
= 1;
5518 list_init(&local_fontfile_loader
.streams
);
5519 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5520 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5523 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5525 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5528 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5530 struct local_refkey
*refkey
;
5533 return E_INVALIDARG
;
5535 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5538 refkey
= heap_alloc(*size
);
5540 return E_OUTOFMEMORY
;
5543 refkey
->writetime
= *writetime
;
5545 WIN32_FILE_ATTRIBUTE_DATA info
;
5547 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5548 refkey
->writetime
= info
.ftLastWriteTime
;
5550 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5552 strcpyW(refkey
->name
, path
);
5559 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5561 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5563 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5564 IsEqualIID(riid
, &IID_IUnknown
))
5567 IDWriteGlyphRunAnalysis_AddRef(iface
);
5571 WARN("%s not implemented.\n", debugstr_guid(riid
));
5574 return E_NOINTERFACE
;
5577 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5579 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5580 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
5582 TRACE("%p, refcount %d.\n", iface
, refcount
);
5587 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5589 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5590 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
5592 TRACE("%p, refcount %d.\n", iface
, refcount
);
5596 if (analysis
->run
.fontFace
)
5597 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5598 heap_free(analysis
->glyphs
);
5599 heap_free(analysis
->origins
);
5600 heap_free(analysis
->bitmap
);
5601 heap_free(analysis
);
5607 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5611 case DWRITE_RENDERING_MODE1_NATURAL
:
5612 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5613 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5620 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5622 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5625 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5627 struct dwrite_glyphbitmap glyph_bitmap
;
5628 IDWriteFontFace4
*fontface
;
5632 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5633 *bounds
= analysis
->bounds
;
5637 if (analysis
->run
.isSideways
)
5638 FIXME("sideways runs are not supported.\n");
5640 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5642 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5644 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5645 glyph_bitmap
.fontface
= fontface
;
5646 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5647 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5648 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5649 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5650 glyph_bitmap
.m
= &analysis
->m
;
5652 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5653 RECT
*bbox
= &glyph_bitmap
.bbox
;
5656 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5657 freetype_get_glyph_bbox(&glyph_bitmap
);
5659 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5660 (bbox
->bottom
- bbox
->top
);
5661 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5662 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5664 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5665 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5668 IDWriteFontFace4_Release(fontface
);
5670 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5671 *bounds
= analysis
->bounds
;
5674 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
5675 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5677 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5679 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
5681 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5682 SetRectEmpty(bounds
);
5683 return E_INVALIDARG
;
5686 if (type
!= analysis
->texture_type
)
5688 SetRectEmpty(bounds
);
5692 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
5696 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5698 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5699 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5700 (runbounds
->left
- bounds
->left
) * 3;
5702 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5703 runbounds
->left
- bounds
->left
;
5706 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5708 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5709 struct dwrite_glyphbitmap glyph_bitmap
;
5710 IDWriteFontFace4
*fontface
;
5711 D2D_POINT_2F origin
;
5716 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5718 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5722 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5723 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5725 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5726 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5727 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5728 IDWriteFontFace4_Release(fontface
);
5729 return E_OUTOFMEMORY
;
5732 origin
.x
= origin
.y
= 0.0f
;
5734 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5735 glyph_bitmap
.fontface
= fontface
;
5736 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5737 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5738 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5739 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5740 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5741 glyph_bitmap
.m
= &analysis
->m
;
5742 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5743 IDWriteFontFace4_Release(fontface
);
5744 return E_OUTOFMEMORY
;
5747 bbox
= &glyph_bitmap
.bbox
;
5749 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5750 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5751 int x
, y
, width
, height
;
5754 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5755 freetype_get_glyph_bbox(&glyph_bitmap
);
5757 if (IsRectEmpty(bbox
))
5760 width
= bbox
->right
- bbox
->left
;
5761 height
= bbox
->bottom
- bbox
->top
;
5763 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5764 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5765 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5767 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5769 /* blit to analysis bitmap */
5770 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5773 /* convert 1bpp to 8bpp/24bpp */
5774 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5775 for (y
= 0; y
< height
; y
++) {
5776 for (x
= 0; x
< width
; x
++)
5777 if (src
[x
/ 8] & masks
[x
% 8])
5778 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5779 src
+= glyph_bitmap
.pitch
;
5780 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5784 for (y
= 0; y
< height
; y
++) {
5785 for (x
= 0; x
< width
; x
++)
5786 if (src
[x
/ 8] & masks
[x
% 8])
5787 dst
[x
] = DWRITE_ALPHA_MAX
;
5788 src
+= glyph_bitmap
.pitch
;
5789 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5794 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5795 for (y
= 0; y
< height
; y
++) {
5796 for (x
= 0; x
< width
; x
++)
5797 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5798 src
+= glyph_bitmap
.pitch
;
5799 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5803 for (y
= 0; y
< height
; y
++) {
5804 for (x
= 0; x
< width
; x
++)
5806 src
+= glyph_bitmap
.pitch
;
5807 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5812 heap_free(glyph_bitmap
.buf
);
5814 IDWriteFontFace4_Release(fontface
);
5816 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5818 /* we don't need this anymore */
5819 heap_free(analysis
->glyphs
);
5820 heap_free(analysis
->origins
);
5821 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5823 analysis
->glyphs
= NULL
;
5824 analysis
->origins
= NULL
;
5825 analysis
->run
.glyphIndices
= NULL
;
5826 analysis
->run
.fontFace
= NULL
;
5831 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5832 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5834 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5838 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5840 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5841 return E_INVALIDARG
;
5843 /* make sure buffer is large enough for requested texture type */
5844 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5845 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5848 if (size
< required
)
5849 return E_NOT_SUFFICIENT_BUFFER
;
5851 /* validate requested texture type */
5852 if (analysis
->texture_type
!= type
)
5853 return DWRITE_E_UNSUPPORTEDOPERATION
;
5855 memset(bitmap
, 0, size
);
5856 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
5857 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
5859 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5860 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
5861 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5862 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5866 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
5870 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
5874 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
5875 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5877 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5878 memcpy(dst
, src
, draw_width
);
5887 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5888 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5890 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5892 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
5895 return E_INVALIDARG
;
5897 switch (analysis
->rendering_mode
)
5899 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5900 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5903 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5904 *gamma
= (FLOAT
)value
/ 1000.0f
;
5906 *cleartypelevel
= 1.0f
;
5909 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5910 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5912 case DWRITE_RENDERING_MODE1_ALIASED
:
5913 case DWRITE_RENDERING_MODE1_NATURAL
:
5914 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5915 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5916 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5917 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5926 static const IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
5928 glyphrunanalysis_QueryInterface
,
5929 glyphrunanalysis_AddRef
,
5930 glyphrunanalysis_Release
,
5931 glyphrunanalysis_GetAlphaTextureBounds
,
5932 glyphrunanalysis_CreateAlphaTexture
,
5933 glyphrunanalysis_GetAlphaBlendParams
5936 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5939 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5940 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5944 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5945 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5947 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5951 FIXME("Sideways mode is not supported.\n");
5953 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5955 switch (measuring_mode
)
5957 case DWRITE_MEASURING_MODE_NATURAL
:
5958 return (float)advance
* emsize
/ (float)upem
;
5959 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5960 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5961 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5963 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5968 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5970 struct dwrite_glyphrunanalysis
*analysis
;
5975 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5976 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5977 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5978 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5979 return E_INVALIDARG
;
5981 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5982 return E_INVALIDARG
;
5984 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5985 return E_INVALIDARG
;
5987 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5988 return E_INVALIDARG
;
5990 analysis
= heap_alloc_zero(sizeof(*analysis
));
5992 return E_OUTOFMEMORY
;
5994 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5995 analysis
->refcount
= 1;
5996 analysis
->rendering_mode
= desc
->rendering_mode
;
5998 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5999 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6000 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
6002 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
6004 analysis
->run
= *desc
->run
;
6005 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
6006 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
6007 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
6009 if (!analysis
->glyphs
|| !analysis
->origins
) {
6010 heap_free(analysis
->glyphs
);
6011 heap_free(analysis
->origins
);
6013 analysis
->glyphs
= NULL
;
6014 analysis
->origins
= NULL
;
6016 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
6017 return E_OUTOFMEMORY
;
6020 /* check if transform is usable */
6021 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
6022 analysis
->m
= *desc
->transform
;
6023 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
6026 analysis
->run
.glyphIndices
= analysis
->glyphs
;
6027 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
6029 compute_glyph_origins(desc
->run
, desc
->measuring_mode
, desc
->origin
, desc
->transform
, analysis
->origins
);
6030 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6032 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
6033 transform_point(&analysis
->origins
[i
], &analysis
->m
);
6036 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6040 /* IDWriteColorGlyphRunEnumerator1 */
6041 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6043 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6045 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6046 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6047 IsEqualIID(riid
, &IID_IUnknown
))
6050 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6054 WARN("%s not implemented.\n", debugstr_guid(riid
));
6057 return E_NOINTERFACE
;
6060 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6062 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6063 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6065 TRACE("%p, refcount %u.\n", iface
, refcount
);
6070 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6072 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6073 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6075 TRACE("%p, refcount %u.\n", iface
, refcount
);
6079 heap_free(glyphenum
->advances
);
6080 heap_free(glyphenum
->color_advances
);
6081 heap_free(glyphenum
->offsets
);
6082 heap_free(glyphenum
->color_offsets
);
6083 heap_free(glyphenum
->glyphindices
);
6084 heap_free(glyphenum
->glyphs
);
6085 if (glyphenum
->colr
.context
)
6086 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6087 IDWriteFontFace5_Release(glyphenum
->fontface
);
6088 heap_free(glyphenum
);
6094 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6096 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6097 FLOAT origin
= 0.0f
;
6103 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6107 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6109 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6110 FLOAT advance_adj
= 0.0f
;
6111 BOOL got_palette_index
;
6114 /* start with regular glyphs */
6115 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6116 UINT32 first_glyph
= 0;
6118 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6119 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6120 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6121 first_glyph
= min(first_glyph
, g
);
6124 glyphenum
->glyphindices
[g
] = 1;
6125 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6126 if (glyphenum
->color_offsets
)
6127 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6130 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6131 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6132 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6133 colorrun
->paletteIndex
= 0xffff;
6134 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6135 glyphenum
->has_regular_glyphs
= FALSE
;
6139 colorrun
->glyphRun
.glyphCount
= 0;
6140 got_palette_index
= FALSE
;
6144 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6146 glyphenum
->glyphindices
[g
] = 1;
6148 /* all glyph layers were returned */
6149 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6150 advance_adj
+= glyphenum
->advances
[g
];
6154 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6155 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6156 if (!got_palette_index
) {
6157 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6158 /* use foreground color or request one from the font */
6159 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6160 if (colorrun
->paletteIndex
!= 0xffff)
6162 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6163 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6165 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6166 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6168 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6169 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6170 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6171 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6172 got_palette_index
= TRUE
;
6175 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6176 /* offsets are relative to glyph origin, nothing to fix up */
6177 if (glyphenum
->color_offsets
)
6178 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6179 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6181 glyphenum
->color_advances
[index
-1] += advance_adj
;
6182 colorrun
->glyphRun
.glyphCount
++;
6186 advance_adj
+= glyphenum
->advances
[g
];
6189 /* reset last advance */
6190 if (colorrun
->glyphRun
.glyphCount
)
6191 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6193 return colorrun
->glyphRun
.glyphCount
> 0;
6196 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6198 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6200 TRACE("%p, %p.\n", iface
, has_run
);
6204 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6205 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6207 if (colorglyphenum_build_color_run(glyphenum
))
6210 glyphenum
->current_layer
++;
6213 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6218 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6219 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6221 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6224 return E_NOT_VALID_STATE
;
6227 *run
= &glyphenum
->colorrun
;
6231 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6232 DWRITE_COLOR_GLYPH_RUN
const **run
)
6234 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6236 TRACE("%p, %p.\n", iface
, run
);
6238 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6241 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6242 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6244 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6246 TRACE("%p, %p.\n", iface
, run
);
6248 return colorglyphenum_get_current_run(glyphenum
, run
);
6251 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6253 colorglyphenum_QueryInterface
,
6254 colorglyphenum_AddRef
,
6255 colorglyphenum_Release
,
6256 colorglyphenum_MoveNext
,
6257 colorglyphenum_GetCurrentRun
,
6258 colorglyphenum1_GetCurrentRun
,
6261 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6262 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6263 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6265 struct dwrite_colorglyphenum
*colorglyphenum
;
6266 BOOL colorfont
, has_colored_glyph
;
6267 struct dwrite_fontface
*fontface
;
6272 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6274 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6275 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6277 return DWRITE_E_NOCOLOR
;
6279 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6280 if (!colorglyphenum
)
6281 return E_OUTOFMEMORY
;
6283 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6284 colorglyphenum
->refcount
= 1;
6285 colorglyphenum
->origin_x
= originX
;
6286 colorglyphenum
->origin_y
= originY
;
6287 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6288 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6289 colorglyphenum
->glyphs
= NULL
;
6290 colorglyphenum
->run
= *run
;
6291 colorglyphenum
->run
.glyphIndices
= NULL
;
6292 colorglyphenum
->run
.glyphAdvances
= NULL
;
6293 colorglyphenum
->run
.glyphOffsets
= NULL
;
6294 colorglyphenum
->palette
= palette
;
6295 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6296 colorglyphenum
->colr
.exists
= TRUE
;
6297 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6298 colorglyphenum
->current_layer
= 0;
6299 colorglyphenum
->max_layer_num
= 0;
6301 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6303 has_colored_glyph
= FALSE
;
6304 colorglyphenum
->has_regular_glyphs
= FALSE
;
6305 for (i
= 0; i
< run
->glyphCount
; i
++) {
6306 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6307 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6308 has_colored_glyph
= TRUE
;
6310 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6311 colorglyphenum
->has_regular_glyphs
= TRUE
;
6314 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6315 is supposed to proceed normally, like if font had no color info at all. */
6316 if (!has_colored_glyph
) {
6317 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6318 return DWRITE_E_NOCOLOR
;
6321 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6322 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6323 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6324 if (run
->glyphOffsets
) {
6325 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6326 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6327 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6330 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6331 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6332 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6333 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6334 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6335 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6336 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6337 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6339 if (run
->glyphAdvances
)
6340 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6343 for (i
= 0; i
< run
->glyphCount
; ++i
)
6344 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6345 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6348 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6353 /* IDWriteFontFaceReference */
6354 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6356 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6358 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6359 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6360 IsEqualIID(riid
, &IID_IUnknown
))
6363 IDWriteFontFaceReference1_AddRef(iface
);
6367 WARN("%s not implemented.\n", debugstr_guid(riid
));
6371 return E_NOINTERFACE
;
6374 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6376 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6377 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6379 TRACE("%p, refcount %u.\n", iface
, refcount
);
6384 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6386 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6387 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6389 TRACE("%p, refcount %u.\n", iface
, refcount
);
6393 IDWriteFontFile_Release(reference
->file
);
6394 IDWriteFactory7_Release(reference
->factory
);
6395 heap_free(reference
->axis_values
);
6396 heap_free(reference
);
6402 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6404 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6406 TRACE("%p, %p.\n", iface
, fontface
);
6408 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6411 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6412 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6414 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6415 DWRITE_FONT_FILE_TYPE file_type
;
6416 DWRITE_FONT_FACE_TYPE face_type
;
6417 IDWriteFontFace
*fontface
;
6422 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6424 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6428 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6429 simulations
, &fontface
);
6432 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6433 IDWriteFontFace_Release(fontface
);
6439 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6441 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6442 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6445 TRACE("%p, %p.\n", iface
, ref
);
6447 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6448 reference
->simulations
== other
->simulations
;
6449 if (reference
->axis_values_count
)
6451 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6452 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6458 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6460 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6462 TRACE("%p.\n", iface
);
6464 return reference
->index
;
6467 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6469 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6471 TRACE("%p.\n", iface
);
6473 return reference
->simulations
;
6476 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6478 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6479 IDWriteFontFileLoader
*loader
;
6484 TRACE("%p, %p.\n", iface
, file
);
6486 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6490 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6494 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6495 IDWriteFontFileLoader_Release(loader
);
6500 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6502 FIXME("%p.\n", iface
);
6507 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6509 FIXME("%p.\n", iface
);
6514 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6516 FIXME("%p, %p.\n", iface
, writetime
);
6521 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6523 FIXME("%p.\n", iface
);
6525 return DWRITE_LOCALITY_LOCAL
;
6528 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6530 FIXME("%p.\n", iface
);
6535 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6536 WCHAR
const *chars
, UINT32 count
)
6538 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6543 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6544 UINT16
const *glyphs
, UINT32 count
)
6546 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6551 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6552 UINT64 offset
, UINT64 size
)
6554 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6559 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6561 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6562 IDWriteFontFace3
*fontface3
;
6565 TRACE("%p, %p.\n", iface
, fontface
);
6567 /* FIXME: created instance should likely respect given axis. */
6568 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6571 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6572 IDWriteFontFace3_Release(fontface3
);
6578 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6580 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6582 TRACE("%p.\n", iface
);
6584 return reference
->axis_values_count
;
6587 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6588 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6590 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6592 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6594 if (value_count
< reference
->axis_values_count
)
6595 return E_NOT_SUFFICIENT_BUFFER
;
6597 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6602 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6604 fontfacereference_QueryInterface
,
6605 fontfacereference_AddRef
,
6606 fontfacereference_Release
,
6607 fontfacereference_CreateFontFace
,
6608 fontfacereference_CreateFontFaceWithSimulations
,
6609 fontfacereference_Equals
,
6610 fontfacereference_GetFontFaceIndex
,
6611 fontfacereference_GetSimulations
,
6612 fontfacereference_GetFontFile
,
6613 fontfacereference_GetLocalFileSize
,
6614 fontfacereference_GetFileSize
,
6615 fontfacereference_GetFileTime
,
6616 fontfacereference_GetLocality
,
6617 fontfacereference_EnqueueFontDownloadRequest
,
6618 fontfacereference_EnqueueCharacterDownloadRequest
,
6619 fontfacereference_EnqueueGlyphDownloadRequest
,
6620 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6621 fontfacereference1_CreateFontFace
,
6622 fontfacereference1_GetFontAxisValueCount
,
6623 fontfacereference1_GetFontAxisValues
,
6626 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6627 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6628 IDWriteFontFaceReference1
**ret
)
6630 struct dwrite_fontfacereference
*object
;
6634 if (!is_simulation_valid(simulations
))
6635 return E_INVALIDARG
;
6637 object
= heap_alloc_zero(sizeof(*object
));
6639 return E_OUTOFMEMORY
;
6641 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6642 object
->refcount
= 1;
6644 object
->factory
= factory
;
6645 IDWriteFactory7_AddRef(object
->factory
);
6646 object
->file
= file
;
6647 IDWriteFontFile_AddRef(object
->file
);
6648 object
->index
= index
;
6649 object
->simulations
= simulations
;
6650 if (axis_values_count
)
6652 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6654 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6655 return E_OUTOFMEMORY
;
6657 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6658 object
->axis_values_count
= axis_values_count
;
6661 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6666 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6668 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6670 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6672 IDWriteFontFileStream_AddRef(iface
);
6678 WARN("%s not implemented.\n", debugstr_guid(riid
));
6679 return E_NOINTERFACE
;
6682 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6684 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6685 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
6687 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6692 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6694 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6695 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
6697 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6701 release_inmemory_stream(stream
->data
);
6708 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6709 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6711 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6713 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
6714 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6716 *fragment_context
= NULL
;
6718 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6719 *fragment_start
= NULL
;
6723 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6727 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6729 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
6732 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6734 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6736 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
6738 *size
= stream
->data
->size
;
6743 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6745 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
6747 *last_writetime
= 0;
6752 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6753 inmemoryfilestream_QueryInterface
,
6754 inmemoryfilestream_AddRef
,
6755 inmemoryfilestream_Release
,
6756 inmemoryfilestream_ReadFileFragment
,
6757 inmemoryfilestream_ReleaseFileFragment
,
6758 inmemoryfilestream_GetFileSize
,
6759 inmemoryfilestream_GetLastWriteTime
,
6762 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6763 REFIID riid
, void **obj
)
6765 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6767 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6768 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6769 IsEqualIID(riid
, &IID_IUnknown
))
6772 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6776 WARN("%s not implemented.\n", debugstr_guid(riid
));
6780 return E_NOINTERFACE
;
6783 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6785 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6786 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
6788 TRACE("%p, refcount %u.\n", iface
, refcount
);
6793 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6795 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6796 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
6799 TRACE("%p, refcount %u.\n", iface
, refcount
);
6803 for (i
= 0; i
< loader
->count
; ++i
)
6804 release_inmemory_stream(loader
->streams
[i
]);
6805 heap_free(loader
->streams
);
6812 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6813 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6815 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6816 struct dwrite_inmemory_filestream
*stream
;
6819 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
6823 if (key_size
!= sizeof(DWORD
))
6824 return E_INVALIDARG
;
6826 index
= *(DWORD
*)key
;
6828 if (index
>= loader
->count
)
6829 return E_INVALIDARG
;
6831 if (!(stream
= heap_alloc(sizeof(*stream
))))
6832 return E_OUTOFMEMORY
;
6834 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6835 stream
->refcount
= 1;
6836 stream
->data
= loader
->streams
[index
];
6837 InterlockedIncrement(&stream
->data
->refcount
);
6839 *ret
= &stream
->IDWriteFontFileStream_iface
;
6844 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6845 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6847 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6848 struct dwrite_inmemory_stream_data
*stream
;
6851 TRACE("%p, %p, %p, %u, %p, %p.\n", iface
, factory
, data
, data_size
, owner
, fontfile
);
6855 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6856 return E_OUTOFMEMORY
;
6858 if (!(stream
= heap_alloc(sizeof(*stream
))))
6859 return E_OUTOFMEMORY
;
6861 stream
->refcount
= 1;
6862 stream
->size
= data_size
;
6863 stream
->owner
= owner
;
6864 if (stream
->owner
) {
6865 IUnknown_AddRef(stream
->owner
);
6866 stream
->data
= (void *)data
;
6869 if (!(stream
->data
= heap_alloc(data_size
))) {
6871 return E_OUTOFMEMORY
;
6873 memcpy(stream
->data
, data
, data_size
);
6876 key
= loader
->count
;
6877 loader
->streams
[loader
->count
++] = stream
;
6879 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6880 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6883 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6885 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6887 TRACE("%p.\n", iface
);
6889 return loader
->count
;
6892 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6894 inmemoryfontfileloader_QueryInterface
,
6895 inmemoryfontfileloader_AddRef
,
6896 inmemoryfontfileloader_Release
,
6897 inmemoryfontfileloader_CreateStreamFromKey
,
6898 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6899 inmemoryfontfileloader_GetFileCount
,
6902 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6904 struct dwrite_inmemory_fileloader
*loader
;
6908 loader
= heap_alloc_zero(sizeof(*loader
));
6910 return E_OUTOFMEMORY
;
6912 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6913 loader
->refcount
= 1;
6915 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6920 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6922 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6924 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6925 IsEqualIID(riid
, &IID_IUnknown
))
6928 IDWriteFontResource_AddRef(iface
);
6932 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6934 return E_NOINTERFACE
;
6937 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6939 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6940 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6942 TRACE("%p, refcount %u.\n", iface
, refcount
);
6947 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6949 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6950 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6952 TRACE("%p, refcount %u.\n", iface
, refcount
);
6956 IDWriteFactory7_Release(resource
->factory
);
6957 IDWriteFontFile_Release(resource
->file
);
6958 heap_free(resource
);
6964 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6966 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6968 TRACE("%p, %p.\n", iface
, fontfile
);
6970 *fontfile
= resource
->file
;
6971 IDWriteFontFile_AddRef(*fontfile
);
6976 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6978 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6980 TRACE("%p.\n", iface
);
6982 return resource
->face_index
;
6985 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6987 FIXME("%p.\n", iface
);
6992 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6993 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6995 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
7000 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
7001 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
7003 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
7008 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7011 FIXME("%p, %u.\n", iface
, axis
);
7013 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
7016 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7017 IDWriteLocalizedStrings
**names
)
7019 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7024 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7026 FIXME("%p, %u.\n", iface
, axis
);
7031 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7032 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7034 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7039 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7041 FIXME("%p.\n", iface
);
7046 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7047 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7048 IDWriteFontFace5
**fontface
)
7050 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7051 IDWriteFontFaceReference1
*reference
;
7054 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7056 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7057 simulations
, axis_values
, num_values
, &reference
);
7060 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7061 IDWriteFontFaceReference1_Release(reference
);
7067 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7068 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7069 IDWriteFontFaceReference1
**reference
)
7071 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7073 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7075 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7076 simulations
, axis_values
, num_values
, reference
);
7079 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7081 dwritefontresource_QueryInterface
,
7082 dwritefontresource_AddRef
,
7083 dwritefontresource_Release
,
7084 dwritefontresource_GetFontFile
,
7085 dwritefontresource_GetFontFaceIndex
,
7086 dwritefontresource_GetFontAxisCount
,
7087 dwritefontresource_GetDefaultFontAxisValues
,
7088 dwritefontresource_GetFontAxisRanges
,
7089 dwritefontresource_GetFontAxisAttributes
,
7090 dwritefontresource_GetAxisNames
,
7091 dwritefontresource_GetAxisValueNameCount
,
7092 dwritefontresource_GetAxisValueNames
,
7093 dwritefontresource_HasVariations
,
7094 dwritefontresource_CreateFontFace
,
7095 dwritefontresource_CreateFontFaceReference
,
7098 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7099 IDWriteFontResource
**ret
)
7101 struct dwrite_fontresource
*resource
;
7105 resource
= heap_alloc_zero(sizeof(*resource
));
7107 return E_OUTOFMEMORY
;
7109 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7110 resource
->refcount
= 1;
7111 resource
->face_index
= face_index
;
7112 resource
->file
= file
;
7113 IDWriteFontFile_AddRef(resource
->file
);
7114 resource
->factory
= factory
;
7115 IDWriteFactory7_AddRef(resource
->factory
);
7117 *ret
= &resource
->IDWriteFontResource_iface
;
7122 static HRESULT WINAPI
dwritefontset_QueryInterface(IDWriteFontSet3
*iface
, REFIID riid
, void **obj
)
7124 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7126 if (IsEqualIID(riid
, &IID_IDWriteFontSet3
) ||
7127 IsEqualIID(riid
, &IID_IDWriteFontSet2
) ||
7128 IsEqualIID(riid
, &IID_IDWriteFontSet1
) ||
7129 IsEqualIID(riid
, &IID_IDWriteFontSet
))
7132 IDWriteFontSet3_AddRef(iface
);
7136 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7138 return E_NOINTERFACE
;
7141 static ULONG WINAPI
dwritefontset_AddRef(IDWriteFontSet3
*iface
)
7143 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7144 ULONG refcount
= InterlockedIncrement(&set
->refcount
);
7146 TRACE("%p, refcount %u.\n", iface
, refcount
);
7151 #define MISSING_SET_PROP ((void *)0x1)
7153 static void release_fontset_entry(struct dwrite_fontset_entry
*entry
)
7157 if (InterlockedDecrement(&entry
->refcount
) > 0)
7159 IDWriteFontFile_Release(entry
->file
);
7160 for (i
= 0; i
< ARRAY_SIZE(entry
->props
); ++i
)
7162 if (entry
->props
[i
] && entry
->props
[i
] != MISSING_SET_PROP
)
7163 IDWriteLocalizedStrings_Release(entry
->props
[i
]);
7168 static struct dwrite_fontset_entry
* addref_fontset_entry(struct dwrite_fontset_entry
*entry
)
7170 InterlockedIncrement(&entry
->refcount
);
7174 static IDWriteLocalizedStrings
* fontset_entry_get_property(struct dwrite_fontset_entry
*entry
,
7175 DWRITE_FONT_PROPERTY_ID property
)
7177 struct file_stream_desc stream_desc
= { 0 };
7178 IDWriteLocalizedStrings
*value
;
7180 assert(property
> DWRITE_FONT_PROPERTY_ID_NONE
&& property
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
);
7182 if (entry
->props
[property
] == MISSING_SET_PROP
)
7185 if ((value
= entry
->props
[property
]))
7187 IDWriteLocalizedStrings_AddRef(value
);
7191 get_filestream_from_file(entry
->file
, &stream_desc
.stream
);
7192 stream_desc
.face_type
= entry
->face_type
;
7193 stream_desc
.face_index
= entry
->face_index
;
7195 if (property
== DWRITE_FONT_PROPERTY_ID_FULL_NAME
)
7196 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_FULL_NAME
, &value
);
7197 else if (property
== DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
)
7198 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME
, &value
);
7199 else if (property
== DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
)
7200 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG
, &value
);
7201 else if (property
== DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
)
7202 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
, &value
);
7204 WARN("Unsupported property %u.\n", property
);
7206 if (stream_desc
.stream
)
7207 IDWriteFontFileStream_Release(stream_desc
.stream
);
7211 entry
->props
[property
] = value
;
7212 IDWriteLocalizedStrings_AddRef(value
);
7215 entry
->props
[property
] = MISSING_SET_PROP
;
7220 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7221 struct dwrite_fontset_entry
**entries
, unsigned int count
);
7223 static ULONG WINAPI
dwritefontset_Release(IDWriteFontSet3
*iface
)
7225 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7226 ULONG refcount
= InterlockedDecrement(&set
->refcount
);
7229 TRACE("%p, refcount %u.\n", iface
, refcount
);
7233 IDWriteFactory7_Release(set
->factory
);
7234 for (i
= 0; i
< set
->count
; ++i
)
7235 release_fontset_entry(set
->entries
[i
]);
7236 heap_free(set
->entries
);
7243 static UINT32 WINAPI
dwritefontset_GetFontCount(IDWriteFontSet3
*iface
)
7245 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7247 TRACE("%p.\n", iface
);
7252 static HRESULT WINAPI
dwritefontset_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7253 IDWriteFontFaceReference
**reference
)
7255 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7257 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
7261 if (index
>= set
->count
)
7262 return E_INVALIDARG
;
7264 return IDWriteFactory7_CreateFontFaceReference_(set
->factory
, set
->entries
[index
]->file
,
7265 set
->entries
[index
]->face_index
, set
->entries
[index
]->simulations
, reference
);
7268 static HRESULT WINAPI
dwritefontset_FindFontFaceReference(IDWriteFontSet3
*iface
,
7269 IDWriteFontFaceReference
*reference
, UINT32
*index
, BOOL
*exists
)
7271 FIXME("%p, %p, %p, %p.\n", iface
, reference
, index
, exists
);
7276 static HRESULT WINAPI
dwritefontset_FindFontFace(IDWriteFontSet3
*iface
, IDWriteFontFace
*fontface
,
7277 UINT32
*index
, BOOL
*exists
)
7279 FIXME("%p, %p, %p, %p.\n", iface
, fontface
, index
, exists
);
7284 static HRESULT WINAPI
dwritefontset_GetPropertyValues__(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7285 IDWriteStringList
**values
)
7287 FIXME("%p, %d, %p.\n", iface
, id
, values
);
7292 static HRESULT WINAPI
dwritefontset_GetPropertyValues_(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7293 WCHAR
const *preferred_locales
, IDWriteStringList
**values
)
7295 FIXME("%p, %d, %s, %p.\n", iface
, id
, debugstr_w(preferred_locales
), values
);
7300 static HRESULT WINAPI
dwritefontset_GetPropertyValues(IDWriteFontSet3
*iface
, UINT32 index
, DWRITE_FONT_PROPERTY_ID id
,
7301 BOOL
*exists
, IDWriteLocalizedStrings
**values
)
7303 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7305 TRACE("%p, %u, %d, %p, %p.\n", iface
, index
, id
, exists
, values
);
7307 if (!(id
> DWRITE_FONT_PROPERTY_ID_NONE
&& id
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
) ||
7308 index
>= set
->count
)
7312 return E_INVALIDARG
;
7315 *values
= fontset_entry_get_property(set
->entries
[index
], id
);
7316 *exists
= !!*values
;
7321 static HRESULT WINAPI
dwritefontset_GetPropertyOccurrenceCount(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7324 FIXME("%p, %p, %p.\n", iface
, property
, count
);
7329 static BOOL
fontset_entry_is_matching(struct dwrite_fontset_entry
*entry
, DWRITE_FONT_PROPERTY
const *props
,
7332 IDWriteLocalizedStrings
*value
;
7336 for (i
= 0; i
< count
; ++i
)
7338 switch (props
[i
].propertyId
)
7340 case DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
:
7341 case DWRITE_FONT_PROPERTY_ID_FULL_NAME
:
7342 case DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
:
7343 case DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
:
7344 if (!(value
= fontset_entry_get_property(entry
, props
[i
].propertyId
)))
7347 ret
= localizedstrings_contains(value
, props
[i
].propertyValue
);
7348 IDWriteLocalizedStrings_Release(value
);
7349 if (!ret
) return FALSE
;
7351 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
:
7352 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME
:
7353 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME
:
7354 case DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME
:
7355 case DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG
:
7356 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
7357 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
7358 case DWRITE_FONT_PROPERTY_ID_STYLE
:
7359 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
:
7360 FIXME("Unsupported property %d.\n", props
[i
].propertyId
);
7370 static HRESULT WINAPI
dwritefontset_GetMatchingFonts_(IDWriteFontSet3
*iface
, WCHAR
const *family
, DWRITE_FONT_WEIGHT weight
,
7371 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontSet
**fontset
)
7373 FIXME("%p, %s, %d, %d, %d, %p.\n", iface
, debugstr_w(family
), weight
, stretch
, style
, fontset
);
7378 static HRESULT WINAPI
dwritefontset_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
, UINT32 count
,
7379 IDWriteFontSet
**filtered_set
)
7381 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7382 struct dwrite_fontset_entry
**entries
;
7383 unsigned int i
, matched_count
= 0;
7384 struct dwrite_fontset
*object
;
7386 TRACE("%p, %p, %u, %p.\n", iface
, props
, count
, filtered_set
);
7388 if (!props
&& count
)
7389 return E_INVALIDARG
;
7391 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7392 return E_OUTOFMEMORY
;
7394 if (!(entries
= heap_calloc(set
->count
, sizeof(*entries
))))
7397 return E_OUTOFMEMORY
;
7400 for (i
= 0; i
< set
->count
; ++i
)
7402 if (fontset_entry_is_matching(set
->entries
[i
], props
, count
))
7404 entries
[matched_count
++] = addref_fontset_entry(set
->entries
[i
]);
7414 init_fontset(object
, set
->factory
, entries
, matched_count
);
7416 *filtered_set
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7421 static HRESULT WINAPI
dwritefontset1_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7422 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontSet1
**fontset
)
7424 FIXME("%p, %p, %p, %u, %p.\n", iface
, property
, axis_values
, num_values
, fontset
);
7429 static HRESULT WINAPI
dwritefontset1_GetFirstFontResources(IDWriteFontSet3
*iface
, IDWriteFontSet1
**fontset
)
7431 FIXME("%p, %p.\n", iface
, fontset
);
7436 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts__(IDWriteFontSet3
*iface
, UINT32
const *indices
,
7437 UINT32 num_indices
, IDWriteFontSet1
**fontset
)
7439 FIXME("%p, %p, %u, %p.\n", iface
, indices
, num_indices
, fontset
);
7444 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *axis_ranges
,
7445 UINT32 num_ranges
, BOOL select_any_range
, IDWriteFontSet1
**fontset
)
7447 FIXME("%p, %p, %u, %d, %p.\n", iface
, axis_ranges
, num_ranges
, select_any_range
, fontset
);
7452 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7453 UINT32 num_properties
, BOOL select_any_property
, IDWriteFontSet1
**fontset
)
7455 FIXME("%p, %p, %u, %d, %p.\n", iface
, props
, num_properties
, select_any_property
, fontset
);
7460 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *ranges
,
7461 UINT32 num_ranges
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7463 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, ranges
, num_ranges
, select_any_range
, indices
, num_indices
, actual_num_indices
);
7468 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7469 UINT32 num_properties
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7471 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, props
, num_properties
, select_any_range
, indices
,
7472 num_indices
, actual_num_indices
);
7477 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges_(IDWriteFontSet3
*iface
, UINT32 font_index
,
7478 DWRITE_FONT_AXIS_RANGE
*axis_ranges
, UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7480 FIXME("%p, %u, %p, %u, %p.\n", iface
, font_index
, axis_ranges
, num_ranges
, actual_num_ranges
);
7485 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
*axis_ranges
,
7486 UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7488 FIXME("%p, %p, %u, %p.\n", iface
, axis_ranges
, num_ranges
, actual_num_ranges
);
7493 static HRESULT WINAPI
dwritefontset1_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7494 IDWriteFontFaceReference1
**reference
)
7496 FIXME("%p, %u, %p.\n", iface
, index
, reference
);
7501 static HRESULT WINAPI
dwritefontset1_CreateFontResource(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontResource
**resource
)
7503 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7505 TRACE("%p, %u, %p.\n", iface
, index
, resource
);
7509 if (index
>= set
->count
)
7510 return E_INVALIDARG
;
7512 return IDWriteFactory7_CreateFontResource(set
->factory
, set
->entries
[index
]->file
,
7513 set
->entries
[index
]->face_index
, resource
);
7516 static HRESULT WINAPI
dwritefontset1_CreateFontFace(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontFace5
**fontface
)
7518 FIXME("%p, %u, %p.\n", iface
, index
, fontface
);
7523 static DWRITE_LOCALITY WINAPI
dwritefontset1_GetFontLocality(IDWriteFontSet3
*iface
, UINT32 index
)
7525 FIXME("%p, %u.\n", iface
, index
);
7527 return DWRITE_LOCALITY_LOCAL
;
7530 static HANDLE WINAPI
dwritefontset2_GetExpirationEvent(IDWriteFontSet3
*iface
)
7532 FIXME("%p.\n", iface
);
7537 static DWRITE_FONT_SOURCE_TYPE WINAPI
dwritefontset3_GetFontSourceType(IDWriteFontSet3
*iface
, UINT32 index
)
7539 FIXME("%p, %u.\n", iface
, index
);
7541 return DWRITE_FONT_SOURCE_TYPE_UNKNOWN
;
7544 static UINT32 WINAPI
dwritefontset3_GetFontSourceNameLength(IDWriteFontSet3
*iface
, UINT32 index
)
7546 FIXME("%p, %u.\n", iface
, index
);
7551 static HRESULT WINAPI
dwritefontset3_GetFontSourceName(IDWriteFontSet3
*iface
, UINT32 index
, WCHAR
*buffer
, UINT32 buffer_size
)
7553 FIXME("%p, %u, %p, %u.\n", iface
, index
, buffer
, buffer_size
);
7558 static const IDWriteFontSet3Vtbl fontsetvtbl
=
7560 dwritefontset_QueryInterface
,
7561 dwritefontset_AddRef
,
7562 dwritefontset_Release
,
7563 dwritefontset_GetFontCount
,
7564 dwritefontset_GetFontFaceReference
,
7565 dwritefontset_FindFontFaceReference
,
7566 dwritefontset_FindFontFace
,
7567 dwritefontset_GetPropertyValues__
,
7568 dwritefontset_GetPropertyValues_
,
7569 dwritefontset_GetPropertyValues
,
7570 dwritefontset_GetPropertyOccurrenceCount
,
7571 dwritefontset_GetMatchingFonts_
,
7572 dwritefontset_GetMatchingFonts
,
7573 dwritefontset1_GetMatchingFonts
,
7574 dwritefontset1_GetFirstFontResources
,
7575 dwritefontset1_GetFilteredFonts__
,
7576 dwritefontset1_GetFilteredFonts_
,
7577 dwritefontset1_GetFilteredFonts
,
7578 dwritefontset1_GetFilteredFontIndices_
,
7579 dwritefontset1_GetFilteredFontIndices
,
7580 dwritefontset1_GetFontAxisRanges_
,
7581 dwritefontset1_GetFontAxisRanges
,
7582 dwritefontset1_GetFontFaceReference
,
7583 dwritefontset1_CreateFontResource
,
7584 dwritefontset1_CreateFontFace
,
7585 dwritefontset1_GetFontLocality
,
7586 dwritefontset2_GetExpirationEvent
,
7587 dwritefontset3_GetFontSourceType
,
7588 dwritefontset3_GetFontSourceNameLength
,
7589 dwritefontset3_GetFontSourceName
,
7592 static HRESULT
fontset_create_entry(IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
,
7593 unsigned int face_index
, unsigned int simulations
, struct dwrite_fontset_entry
**ret
)
7595 struct dwrite_fontset_entry
*entry
;
7597 if (!(entry
= heap_alloc_zero(sizeof(*entry
))))
7598 return E_OUTOFMEMORY
;
7600 entry
->refcount
= 1;
7602 IDWriteFontFile_AddRef(entry
->file
);
7603 entry
->face_type
= face_type
;
7604 entry
->face_index
= face_index
;
7605 entry
->simulations
= simulations
;
7612 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7613 struct dwrite_fontset_entry
**entries
, unsigned int count
)
7615 object
->IDWriteFontSet3_iface
.lpVtbl
= &fontsetvtbl
;
7616 object
->refcount
= 1;
7617 object
->factory
= factory
;
7618 IDWriteFactory7_AddRef(object
->factory
);
7619 object
->entries
= entries
;
7620 object
->count
= count
;
7623 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
7624 unsigned int count
, IDWriteFontSet1
**ret
)
7626 struct dwrite_fontset_entry
**entries
= NULL
;
7627 struct dwrite_fontset
*object
;
7630 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7631 return E_OUTOFMEMORY
;
7635 entries
= heap_calloc(count
, sizeof(*entries
));
7637 /* FIXME: set available properties too */
7639 for (i
= 0; i
< count
; ++i
)
7641 fontset_create_entry(fonts
[i
]->file
, fonts
[i
]->face_type
, fonts
[i
]->face_index
,
7642 fonts
[i
]->simulations
, &entries
[i
]);
7645 init_fontset(object
, factory
, entries
, count
);
7647 *ret
= (IDWriteFontSet1
*)&object
->IDWriteFontSet3_iface
;
7652 static HRESULT
fontset_builder_create_fontset(IDWriteFactory7
*factory
, struct dwrite_fontset_entry
**src_entries
,
7653 unsigned int count
, IDWriteFontSet
**ret
)
7655 struct dwrite_fontset_entry
**entries
= NULL
;
7656 struct dwrite_fontset
*object
;
7659 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7660 return E_OUTOFMEMORY
;
7664 entries
= heap_calloc(count
, sizeof(*entries
));
7666 for (i
= 0; i
< count
; ++i
)
7667 entries
[i
] = addref_fontset_entry(src_entries
[i
]);
7669 init_fontset(object
, factory
, entries
, count
);
7671 *ret
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7676 static HRESULT WINAPI
dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2
*iface
,
7677 REFIID riid
, void **obj
)
7679 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7681 if (IsEqualIID(riid
, &IID_IDWriteFontSetBuilder2
) ||
7682 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder1
) ||
7683 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder
) ||
7684 IsEqualIID(riid
, &IID_IUnknown
))
7687 IDWriteFontSetBuilder2_AddRef(iface
);
7691 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7693 return E_NOINTERFACE
;
7696 static ULONG WINAPI
dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2
*iface
)
7698 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7699 ULONG refcount
= InterlockedIncrement(&builder
->refcount
);
7701 TRACE("%p, refcount %u.\n", iface
, refcount
);
7706 static ULONG WINAPI
dwritefontsetbuilder_Release(IDWriteFontSetBuilder2
*iface
)
7708 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7709 ULONG refcount
= InterlockedDecrement(&builder
->refcount
);
7712 TRACE("%p, refcount %u.\n", iface
, refcount
);
7716 IDWriteFactory7_Release(builder
->factory
);
7717 for (i
= 0; i
< builder
->count
; ++i
)
7718 release_fontset_entry(builder
->entries
[i
]);
7719 heap_free(builder
->entries
);
7726 static HRESULT
fontset_builder_add_entry(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
,
7727 DWRITE_FONT_FACE_TYPE face_type
, unsigned int face_index
, unsigned int simulations
)
7729 struct dwrite_fontset_entry
*entry
;
7732 if (!dwrite_array_reserve((void **)&builder
->entries
, &builder
->capacity
, builder
->count
+ 1,
7733 sizeof(*builder
->entries
)))
7735 return E_OUTOFMEMORY
;
7738 if (FAILED(hr
= fontset_create_entry(file
, face_type
, face_index
, simulations
, &entry
)))
7741 builder
->entries
[builder
->count
++] = entry
;
7746 static HRESULT
fontset_builder_add_file(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
)
7748 DWRITE_FONT_FILE_TYPE filetype
;
7749 DWRITE_FONT_FACE_TYPE facetype
;
7750 unsigned int i
, face_count
;
7751 BOOL supported
= FALSE
;
7754 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &filetype
, &facetype
, &face_count
)))
7758 return DWRITE_E_FILEFORMAT
;
7760 for (i
= 0; i
< face_count
; ++i
)
7762 if (FAILED(hr
= fontset_builder_add_entry(builder
, file
, facetype
, i
, DWRITE_FONT_SIMULATIONS_NONE
)))
7769 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2
*iface
,
7770 IDWriteFontFaceReference
*ref
, DWRITE_FONT_PROPERTY
const *props
, UINT32 prop_count
)
7772 FIXME("%p, %p, %p, %u.\n", iface
, ref
, props
, prop_count
);
7777 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2
*iface
,
7778 IDWriteFontFaceReference
*ref
)
7780 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7781 unsigned int face_count
, face_index
, simulations
;
7782 DWRITE_FONT_FILE_TYPE file_type
;
7783 DWRITE_FONT_FACE_TYPE face_type
;
7784 IDWriteFontFile
*file
;
7788 TRACE("%p, %p.\n", iface
, ref
);
7790 if (FAILED(hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
))) return hr
;
7791 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
)))
7796 hr
= DWRITE_E_FILEFORMAT
;
7800 face_index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
7801 simulations
= IDWriteFontFaceReference_GetSimulations(ref
);
7802 hr
= fontset_builder_add_entry(builder
, file
, face_type
, face_index
, simulations
);
7805 IDWriteFontFile_Release(file
);
7810 static HRESULT WINAPI
dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
*fontset
)
7812 FIXME("%p, %p.\n", iface
, fontset
);
7817 static HRESULT WINAPI
dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
**fontset
)
7819 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7821 TRACE("%p, %p.\n", iface
, fontset
);
7823 return fontset_builder_create_fontset(builder
->factory
, builder
->entries
, builder
->count
, fontset
);
7826 static HRESULT WINAPI
dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
)
7828 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7830 TRACE("%p, %p.\n", iface
, file
);
7832 return fontset_builder_add_file(builder
, file
);
7835 static HRESULT WINAPI
dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
,
7836 unsigned int face_index
, DWRITE_FONT_SIMULATIONS simulations
, const DWRITE_FONT_AXIS_VALUE
*axis_values
,
7837 unsigned int num_values
, const DWRITE_FONT_AXIS_RANGE
*axis_ranges
, unsigned int num_ranges
,
7838 const DWRITE_FONT_PROPERTY
*props
, unsigned int num_properties
)
7840 FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface
, file
, face_index
, simulations
, axis_values
, num_values
,
7841 axis_ranges
, num_ranges
, props
, num_properties
);
7846 static HRESULT WINAPI
dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2
*iface
, const WCHAR
*filepath
)
7848 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7849 IDWriteFontFile
*file
;
7852 TRACE("%p, %s.\n", iface
, debugstr_w(filepath
));
7854 if (FAILED(hr
= IDWriteFactory7_CreateFontFileReference(builder
->factory
, filepath
, NULL
, &file
)))
7857 hr
= fontset_builder_add_file(builder
, file
);
7858 IDWriteFontFile_Release(file
);
7862 static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl
=
7864 dwritefontsetbuilder_QueryInterface
,
7865 dwritefontsetbuilder_AddRef
,
7866 dwritefontsetbuilder_Release
,
7867 dwritefontsetbuilder_AddFontFaceReference_
,
7868 dwritefontsetbuilder_AddFontFaceReference
,
7869 dwritefontsetbuilder_AddFontSet
,
7870 dwritefontsetbuilder_CreateFontSet
,
7871 dwritefontsetbuilder1_AddFontFile
,
7872 dwritefontsetbuilder2_AddFont
,
7873 dwritefontsetbuilder2_AddFontFile
,
7876 HRESULT
create_fontset_builder(IDWriteFactory7
*factory
, IDWriteFontSetBuilder2
**ret
)
7878 struct dwrite_fontset_builder
*builder
;
7882 if (!(builder
= heap_alloc_zero(sizeof(*builder
))))
7883 return E_OUTOFMEMORY
;
7885 builder
->IDWriteFontSetBuilder2_iface
.lpVtbl
= &fontsetbuildervtbl
;
7886 builder
->refcount
= 1;
7887 builder
->factory
= factory
;
7888 IDWriteFactory7_AddRef(builder
->factory
);
7890 *ret
= &builder
->IDWriteFontSetBuilder2_iface
;