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 int dwrite_outline_push_tag(struct dwrite_outline
*outline
, unsigned char tag
)
828 if (!dwrite_array_reserve((void **)&outline
->tags
.values
, &outline
->tags
.size
, outline
->tags
.count
+ 1,
829 sizeof(*outline
->tags
.values
)))
834 outline
->tags
.values
[outline
->tags
.count
++] = tag
;
839 int dwrite_outline_push_points(struct dwrite_outline
*outline
, const D2D1_POINT_2F
*points
, unsigned int count
)
841 if (!dwrite_array_reserve((void **)&outline
->points
.values
, &outline
->points
.size
, outline
->points
.count
+ count
,
842 sizeof(*outline
->points
.values
)))
847 memcpy(&outline
->points
.values
[outline
->points
.count
], points
, sizeof(*points
) * count
);
848 outline
->points
.count
+= count
;
853 static void apply_outline_point_offset(const D2D1_POINT_2F
*src
, const D2D1_POINT_2F
*offset
,
856 dst
->x
= src
->x
+ offset
->x
;
857 dst
->y
= src
->y
+ offset
->y
;
860 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
861 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
862 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
864 D2D1_POINT_2F
*origins
, baseline_origin
= { 0 };
865 struct dwrite_outline outline
= {{ 0 }};
866 D2D1_BEZIER_SEGMENT segment
;
868 DWRITE_GLYPH_RUN run
;
869 unsigned int i
, j
, p
;
872 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
873 count
, is_sideways
, is_rtl
, sink
);
875 if (!glyphs
|| !sink
)
881 run
.fontFace
= (IDWriteFontFace
*)iface
;
882 run
.fontEmSize
= emSize
;
883 run
.glyphCount
= count
;
884 run
.glyphIndices
= glyphs
;
885 run
.glyphAdvances
= advances
;
886 run
.glyphOffsets
= offsets
;
887 run
.isSideways
= is_sideways
;
888 run
.bidiLevel
= is_rtl
? 1 : 0;
890 if (!(origins
= heap_alloc(sizeof(*origins
) * count
)))
891 return E_OUTOFMEMORY
;
893 if (FAILED(hr
= compute_glyph_origins(&run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
, NULL
, origins
)))
899 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
901 for (i
= 0; i
< count
; ++i
)
903 outline
.tags
.count
= outline
.points
.count
= 0;
904 if (freetype_get_glyph_outline(iface
, emSize
, glyphs
[i
], &outline
))
906 WARN("Failed to get glyph outline for glyph %u.\n", glyphs
[i
]);
910 for (j
= 0, p
= 0; j
< outline
.tags
.count
; ++j
)
912 switch (outline
.tags
.values
[j
])
914 case OUTLINE_BEGIN_FIGURE
:
915 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
916 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, point
, D2D1_FIGURE_BEGIN_FILLED
);
918 case OUTLINE_END_FIGURE
:
919 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
922 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
923 ID2D1SimplifiedGeometrySink_AddLines(sink
, &point
, 1);
926 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point1
);
927 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point2
);
928 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point3
);
929 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, &segment
, 1);
935 heap_free(outline
.tags
.values
);
936 heap_free(outline
.points
.values
);
942 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
943 float ppem
, unsigned int gasp
)
945 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
949 case DWRITE_MEASURING_MODE_NATURAL
:
951 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
952 mode
= DWRITE_RENDERING_MODE_NATURAL
;
954 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
957 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
958 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
960 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
961 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
970 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
971 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
973 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
977 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
980 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
984 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
985 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
988 ppem
= emSize
* ppdip
;
990 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
991 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
995 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
996 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
1000 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
1001 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
1003 DWRITE_FONT_METRICS1 metrics1
;
1004 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
1005 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
1009 static inline int round_metric(FLOAT metric
)
1011 return (int)floorf(metric
+ 0.5f
);
1014 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
1016 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
1019 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
1022 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
1023 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
1024 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
1026 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1027 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1028 DWRITE_MEASURING_MODE mode
;
1033 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
1034 glyph_count
, metrics
, is_sideways
);
1036 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1037 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
1039 size
= emSize
* ppdip
;
1040 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
1041 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1043 for (i
= 0; i
< glyph_count
; i
++) {
1044 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
1045 DWRITE_GLYPH_METRICS design
;
1048 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
1052 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
1054 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
1056 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
1058 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
1059 SCALE_METRIC(leftSideBearing
);
1060 SCALE_METRIC(rightSideBearing
);
1061 SCALE_METRIC(topSideBearing
);
1062 SCALE_METRIC(advanceHeight
);
1063 SCALE_METRIC(bottomSideBearing
);
1064 SCALE_METRIC(verticalOriginY
);
1071 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1073 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1075 TRACE("%p, %p.\n", iface
, metrics
);
1077 *metrics
= fontface
->metrics
;
1080 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
1081 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
1083 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1084 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
1085 UINT16 ascent
, descent
;
1088 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
1090 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
1091 memset(metrics
, 0, sizeof(*metrics
));
1092 return E_INVALIDARG
;
1095 em_size
*= pixels_per_dip
;
1096 if (m
&& m
->m22
!= 0.0f
)
1097 em_size
*= fabs(m
->m22
);
1099 scale
= em_size
/ design
->designUnitsPerEm
;
1100 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
1102 ascent
= round_metric(design
->ascent
* scale
);
1103 descent
= round_metric(design
->descent
* scale
);
1106 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
1107 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
1108 metrics
->ascent
= round_metric(ascent
/ scale
);
1109 metrics
->descent
= round_metric(descent
/ scale
);
1111 SCALE_METRIC(lineGap
);
1112 SCALE_METRIC(capHeight
);
1113 SCALE_METRIC(xHeight
);
1114 SCALE_METRIC(underlinePosition
);
1115 SCALE_METRIC(underlineThickness
);
1116 SCALE_METRIC(strikethroughPosition
);
1117 SCALE_METRIC(strikethroughThickness
);
1118 SCALE_METRIC(glyphBoxLeft
);
1119 SCALE_METRIC(glyphBoxTop
);
1120 SCALE_METRIC(glyphBoxRight
);
1121 SCALE_METRIC(glyphBoxBottom
);
1122 SCALE_METRIC(subscriptPositionX
);
1123 SCALE_METRIC(subscriptPositionY
);
1124 SCALE_METRIC(subscriptSizeX
);
1125 SCALE_METRIC(subscriptSizeY
);
1126 SCALE_METRIC(superscriptPositionX
);
1127 SCALE_METRIC(superscriptPositionY
);
1128 SCALE_METRIC(superscriptSizeX
);
1129 SCALE_METRIC(superscriptSizeY
);
1131 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
1137 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1139 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1141 TRACE("%p, %p.\n", iface
, metrics
);
1143 *metrics
= fontface
->caret
;
1146 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1147 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1149 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1151 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1154 if (max_count
&& !ranges
)
1155 return E_INVALIDARG
;
1157 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1158 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1161 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1163 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1165 TRACE("%p.\n", iface
);
1167 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1170 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1171 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1173 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1178 FIXME("Sideways mode is not supported.\n");
1180 switch (measuring_mode
)
1182 case DWRITE_MEASURING_MODE_NATURAL
:
1183 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
1184 glyph
, measuring_mode
, &has_contours
);
1186 advance
+= adjustment
;
1189 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1190 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1195 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1196 FIXME("Transform is not supported.\n");
1198 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1201 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1203 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1207 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1212 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1213 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1215 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1218 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1221 FIXME("sideways mode not supported\n");
1223 for (i
= 0; i
< glyph_count
; ++i
)
1225 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1226 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1232 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1233 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1234 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1236 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1237 DWRITE_MEASURING_MODE measuring_mode
;
1240 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1241 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1243 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1244 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1245 return E_INVALIDARG
;
1248 if (em_size
== 0.0f
) {
1249 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1253 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1254 for (i
= 0; i
< glyph_count
; ++i
)
1256 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1257 glyphs
[i
], is_sideways
);
1263 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1264 const UINT16
*glyphs
, INT32
*values
)
1266 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1268 TRACE("%p, %u, %p, %p.\n", iface
, count
, glyphs
, values
);
1270 if (!(glyphs
|| values
) || !count
)
1271 return E_INVALIDARG
;
1273 if (!glyphs
|| count
== 1)
1275 memset(values
, 0, count
* sizeof(*values
));
1276 return E_INVALIDARG
;
1279 return opentype_get_kerning_pairs(fontface
, count
, glyphs
, values
);
1282 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1284 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1286 TRACE("%p.\n", iface
);
1288 return opentype_has_kerning_pairs(fontface
);
1291 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1292 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1293 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1295 DWRITE_GRID_FIT_MODE gridfitmode
;
1296 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1297 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1300 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1301 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1303 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1305 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1307 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1310 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1312 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1314 TRACE("%p.\n", iface
);
1316 return opentype_has_vertical_variants(fontface
);
1319 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1321 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1323 TRACE("%p.\n", iface
);
1325 return !!(fontface
->flags
& FONT_IS_COLORED
);
1328 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1330 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1332 TRACE("%p.\n", iface
);
1334 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1337 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1339 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1341 TRACE("%p.\n", iface
);
1343 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1346 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1347 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1349 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1351 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1353 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1356 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1357 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1358 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1359 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1361 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1365 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1366 measuringmode
, params
, renderingmode
, gridfitmode
);
1368 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1369 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1372 FIXME("sideways mode not supported\n");
1374 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1376 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1377 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1379 IDWriteRenderingParams2
*params2
;
1382 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1384 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1385 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1386 IDWriteRenderingParams2_Release(params2
);
1389 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1392 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1394 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1396 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1397 if (emSize
>= emthreshold
)
1398 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1400 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1403 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1404 if (emSize
>= emthreshold
)
1405 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1406 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1407 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1409 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1410 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1416 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1417 IDWriteFontFaceReference
**reference
)
1419 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1421 TRACE("%p, %p.\n", iface
, reference
);
1423 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1424 IDWriteFontFaceReference_AddRef(*reference
);
1429 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1431 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1433 TRACE("%p, %p.\n", iface
, panose
);
1435 *panose
= fontface
->panose
;
1438 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1440 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1442 TRACE("%p.\n", iface
);
1444 return fontface
->weight
;
1447 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1449 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1451 TRACE("%p.\n", iface
);
1453 return fontface
->stretch
;
1456 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1458 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1460 TRACE("%p.\n", iface
);
1462 return fontface
->style
;
1465 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1467 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1469 TRACE("%p, %p.\n", iface
, names
);
1471 return clone_localizedstrings(fontface
->family_names
, names
);
1474 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1476 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1478 TRACE("%p, %p.\n", iface
, names
);
1480 return clone_localizedstrings(fontface
->names
, names
);
1483 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1484 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1485 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1492 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1493 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1498 if (!strings_cache
[stringid
])
1500 struct file_stream_desc desc
= *stream_desc
;
1503 hr
= get_filestream_from_file(file
, &desc
.stream
);
1505 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1507 if (!stream_desc
->stream
&& desc
.stream
)
1508 IDWriteFontFileStream_Release(desc
.stream
);
1511 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1513 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1521 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1522 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1524 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1525 struct file_stream_desc stream_desc
;
1527 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1529 stream_desc
.stream
= fontface
->stream
;
1530 stream_desc
.face_index
= fontface
->index
;
1531 stream_desc
.face_type
= fontface
->type
;
1532 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1535 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1537 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1539 TRACE("%p, %#x.\n", iface
, ch
);
1541 return !!dwritefontface_get_glyph(fontface
, ch
);
1544 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1545 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1546 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1548 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1552 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1553 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1555 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1556 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1559 FIXME("sideways mode not supported\n");
1561 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1563 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1564 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1566 IDWriteRenderingParams3
*params3
;
1569 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1571 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1572 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1573 IDWriteRenderingParams3_Release(params3
);
1576 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1579 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1581 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1583 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1584 if (emSize
>= emthreshold
)
1585 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1587 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1590 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1591 if (emSize
>= emthreshold
)
1592 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1593 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1594 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1596 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1597 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1603 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1605 FIXME("%p, %#x: stub\n", iface
, ch
);
1610 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1612 FIXME("%p, %u: stub\n", iface
, glyph
);
1617 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1618 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1620 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1625 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1626 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1628 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1633 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1634 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1636 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1641 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1643 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1645 TRACE("%p.\n", iface
);
1647 return fontface
->glyph_image_formats
;
1650 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1651 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1653 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1658 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1660 FIXME("%p, %p: stub\n", iface
, context
);
1663 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1665 FIXME("%p: stub\n", iface
);
1670 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1673 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1678 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1683 FIXME("%p: stub\n", iface
);
1688 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1690 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1692 TRACE("%p, %p.\n", iface
, resource
);
1694 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->file
, fontface
->index
, resource
);
1697 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1699 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1701 TRACE("%p, %p.\n", iface
, other
);
1703 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1706 /* TODO: add variations support */
1708 return fontface
->index
== other_face
->index
&&
1709 fontface
->simulations
== other_face
->simulations
&&
1710 is_same_fontfile(fontface
->file
, other_face
->file
);
1713 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1715 dwritefontface_QueryInterface
,
1716 dwritefontface_AddRef
,
1717 dwritefontface_Release
,
1718 dwritefontface_GetType
,
1719 dwritefontface_GetFiles
,
1720 dwritefontface_GetIndex
,
1721 dwritefontface_GetSimulations
,
1722 dwritefontface_IsSymbolFont
,
1723 dwritefontface_GetMetrics
,
1724 dwritefontface_GetGlyphCount
,
1725 dwritefontface_GetDesignGlyphMetrics
,
1726 dwritefontface_GetGlyphIndices
,
1727 dwritefontface_TryGetFontTable
,
1728 dwritefontface_ReleaseFontTable
,
1729 dwritefontface_GetGlyphRunOutline
,
1730 dwritefontface_GetRecommendedRenderingMode
,
1731 dwritefontface_GetGdiCompatibleMetrics
,
1732 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1733 dwritefontface1_GetMetrics
,
1734 dwritefontface1_GetGdiCompatibleMetrics
,
1735 dwritefontface1_GetCaretMetrics
,
1736 dwritefontface1_GetUnicodeRanges
,
1737 dwritefontface1_IsMonospacedFont
,
1738 dwritefontface1_GetDesignGlyphAdvances
,
1739 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1740 dwritefontface1_GetKerningPairAdjustments
,
1741 dwritefontface1_HasKerningPairs
,
1742 dwritefontface1_GetRecommendedRenderingMode
,
1743 dwritefontface1_GetVerticalGlyphVariants
,
1744 dwritefontface1_HasVerticalGlyphVariants
,
1745 dwritefontface2_IsColorFont
,
1746 dwritefontface2_GetColorPaletteCount
,
1747 dwritefontface2_GetPaletteEntryCount
,
1748 dwritefontface2_GetPaletteEntries
,
1749 dwritefontface2_GetRecommendedRenderingMode
,
1750 dwritefontface3_GetFontFaceReference
,
1751 dwritefontface3_GetPanose
,
1752 dwritefontface3_GetWeight
,
1753 dwritefontface3_GetStretch
,
1754 dwritefontface3_GetStyle
,
1755 dwritefontface3_GetFamilyNames
,
1756 dwritefontface3_GetFaceNames
,
1757 dwritefontface3_GetInformationalStrings
,
1758 dwritefontface3_HasCharacter
,
1759 dwritefontface3_GetRecommendedRenderingMode
,
1760 dwritefontface3_IsCharacterLocal
,
1761 dwritefontface3_IsGlyphLocal
,
1762 dwritefontface3_AreCharactersLocal
,
1763 dwritefontface3_AreGlyphsLocal
,
1764 dwritefontface4_GetGlyphImageFormats_
,
1765 dwritefontface4_GetGlyphImageFormats
,
1766 dwritefontface4_GetGlyphImageData
,
1767 dwritefontface4_ReleaseGlyphImageData
,
1768 dwritefontface5_GetFontAxisValueCount
,
1769 dwritefontface5_GetFontAxisValues
,
1770 dwritefontface5_HasVariations
,
1771 dwritefontface5_GetFontResource
,
1772 dwritefontface5_Equals
,
1775 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
1777 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1778 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
1781 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
1783 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1784 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
1787 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
1789 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1790 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
1793 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
1794 IDWriteFontFace3
**ret
)
1796 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1798 TRACE("%p, %p.\n", iface
, ret
);
1800 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
1801 IDWriteFontFace3_AddRef(*ret
);
1806 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
1807 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
1809 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1810 DWRITE_FONT_FILE_TYPE file_type
;
1811 DWRITE_FONT_FACE_TYPE face_type
;
1812 IDWriteFontFace
*face
;
1817 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
1819 hr
= IDWriteFontFile_Analyze(fontface
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
1823 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, &fontface
->file
, fontface
->index
,
1824 simulations
, &face
);
1827 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
1828 IDWriteFontFace_Release(face
);
1834 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
1836 FIXME("%p, %p.\n", iface
, ref
);
1841 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
1843 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1845 TRACE("%p.\n", iface
);
1847 return fontface
->index
;
1850 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
1852 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1854 TRACE("%p.\n", iface
);
1856 return fontface
->simulations
;
1859 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
1861 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
1863 TRACE("%p, %p.\n", iface
, file
);
1865 *file
= fontface
->file
;
1866 IDWriteFontFile_AddRef(*file
);
1871 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
1873 FIXME("%p.\n", iface
);
1878 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
1880 FIXME("%p.\n", iface
);
1885 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
1887 FIXME("%p, %p.\n", iface
, writetime
);
1892 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
1894 FIXME("%p.\n", iface
);
1896 return DWRITE_LOCALITY_LOCAL
;
1899 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
1901 FIXME("%p.\n", iface
);
1906 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
1907 WCHAR
const *chars
, UINT32 count
)
1909 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
1914 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
1915 UINT16
const *glyphs
, UINT32 count
)
1917 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
1922 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
1923 UINT64 offset
, UINT64 size
)
1925 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
1930 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
1932 dwritefontface_reference_QueryInterface
,
1933 dwritefontface_reference_AddRef
,
1934 dwritefontface_reference_Release
,
1935 dwritefontface_reference_CreateFontFace
,
1936 dwritefontface_reference_CreateFontFaceWithSimulations
,
1937 dwritefontface_reference_Equals
,
1938 dwritefontface_reference_GetFontFaceIndex
,
1939 dwritefontface_reference_GetSimulations
,
1940 dwritefontface_reference_GetFontFile
,
1941 dwritefontface_reference_GetLocalFileSize
,
1942 dwritefontface_reference_GetFileSize
,
1943 dwritefontface_reference_GetFileTime
,
1944 dwritefontface_reference_GetLocality
,
1945 dwritefontface_reference_EnqueueFontDownloadRequest
,
1946 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
1947 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
1948 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
1951 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1953 struct dwrite_font_data
*data
= font
->data
;
1954 struct fontface_desc desc
;
1955 struct list
*cached_list
;
1960 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1961 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1965 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1968 desc
.factory
= font
->family
->collection
->factory
;
1969 desc
.face_type
= data
->face_type
;
1970 desc
.file
= data
->file
;
1971 desc
.index
= data
->face_index
;
1972 desc
.simulations
= data
->simulations
;
1973 desc
.font_data
= data
;
1974 hr
= create_fontface(&desc
, cached_list
, fontface
);
1976 IDWriteFontFileStream_Release(desc
.stream
);
1980 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1982 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1984 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1985 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1986 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1987 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1988 IsEqualIID(riid
, &IID_IUnknown
))
1991 IDWriteFont3_AddRef(iface
);
1995 WARN("%s not implemented.\n", debugstr_guid(riid
));
1998 return E_NOINTERFACE
;
2001 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
2003 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2004 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
2006 TRACE("%p, refcount %d.\n", iface
, refcount
);
2011 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
2013 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2014 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
2016 TRACE("%p, refcount %d.\n", iface
, refcount
);
2020 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
2021 release_font_data(font
->data
);
2028 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
2030 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2032 TRACE("%p, %p.\n", iface
, family
);
2034 *family
= (IDWriteFontFamily
*)font
->family
;
2035 IDWriteFontFamily_AddRef(*family
);
2039 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
2041 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2043 TRACE("%p.\n", iface
);
2045 return font
->data
->weight
;
2048 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
2050 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2052 TRACE("%p.\n", iface
);
2054 return font
->data
->stretch
;
2057 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
2059 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2061 TRACE("%p.\n", iface
);
2066 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
2068 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2070 TRACE("%p.\n", iface
);
2072 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
2075 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
2077 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2079 TRACE("%p, %p.\n", iface
, names
);
2081 return clone_localizedstrings(font
->data
->names
, names
);
2084 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
2085 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
2087 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2088 struct dwrite_font_data
*data
= font
->data
;
2089 struct file_stream_desc stream_desc
;
2091 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
2093 /* Stream will be created if necessary. */
2094 stream_desc
.stream
= NULL
;
2095 stream_desc
.face_index
= data
->face_index
;
2096 stream_desc
.face_type
= data
->face_type
;
2097 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
2100 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
2102 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2104 TRACE("%p.\n", iface
);
2106 return font
->data
->simulations
;
2109 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
2111 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2113 TRACE("%p, %p.\n", iface
, metrics
);
2115 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
2118 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
2121 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2122 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
2126 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2128 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2130 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2132 *exists
= dwritefont_has_character(font
, ch
);
2137 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2139 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2141 TRACE("%p, %p.\n", iface
, fontface
);
2143 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2146 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2148 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2150 TRACE("%p, %p.\n", iface
, metrics
);
2152 *metrics
= font
->data
->metrics
;
2155 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2157 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2159 TRACE("%p, %p.\n", iface
, panose
);
2161 *panose
= font
->data
->panose
;
2164 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2167 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2169 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2172 if (max_count
&& !ranges
)
2173 return E_INVALIDARG
;
2175 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2176 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2179 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2181 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2183 TRACE("%p.\n", iface
);
2185 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2188 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2190 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2192 TRACE("%p.\n", iface
);
2194 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2197 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2199 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2201 TRACE("%p, %p.\n", iface
, fontface
);
2203 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2206 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2208 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2210 TRACE("%p, %p.\n", iface
, other
);
2212 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2215 return font
->data
->face_index
== other_font
->data
->face_index
2216 && font
->data
->simulations
== other_font
->data
->simulations
2217 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2220 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2222 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2224 TRACE("%p, %p.\n", iface
, reference
);
2226 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2227 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2228 (IDWriteFontFaceReference1
**)reference
);
2231 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2233 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2235 TRACE("%p, %#x.\n", iface
, ch
);
2237 return dwritefont_has_character(font
, ch
);
2240 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2242 FIXME("%p: stub.\n", iface
);
2244 return DWRITE_LOCALITY_LOCAL
;
2247 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2248 dwritefont_QueryInterface
,
2251 dwritefont_GetFontFamily
,
2252 dwritefont_GetWeight
,
2253 dwritefont_GetStretch
,
2254 dwritefont_GetStyle
,
2255 dwritefont_IsSymbolFont
,
2256 dwritefont_GetFaceNames
,
2257 dwritefont_GetInformationalStrings
,
2258 dwritefont_GetSimulations
,
2259 dwritefont_GetMetrics
,
2260 dwritefont_HasCharacter
,
2261 dwritefont_CreateFontFace
,
2262 dwritefont1_GetMetrics
,
2263 dwritefont1_GetPanose
,
2264 dwritefont1_GetUnicodeRanges
,
2265 dwritefont1_IsMonospacedFont
,
2266 dwritefont2_IsColorFont
,
2267 dwritefont3_CreateFontFace
,
2269 dwritefont3_GetFontFaceReference
,
2270 dwritefont3_HasCharacter
,
2271 dwritefont3_GetLocality
2274 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2278 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2279 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2282 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2286 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2287 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2290 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2294 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2296 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2297 IDWriteFontFaceReference1_iface
);
2300 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2302 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2303 *lf
= font
->data
->lf
;
2306 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2308 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2312 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2314 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2315 *fontsig
= font
->data
->fontsig
;
2319 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2321 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2322 *fontsig
= fontface
->fontsig
;
2326 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2328 struct dwrite_font
*object
;
2332 if (!(object
= heap_alloc(sizeof(*object
))))
2333 return E_OUTOFMEMORY
;
2335 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2336 object
->refcount
= 1;
2337 object
->family
= family
;
2338 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2339 object
->data
= family
->data
->fonts
[index
];
2340 object
->style
= object
->data
->style
;
2341 addref_font_data(object
->data
);
2343 *font
= &object
->IDWriteFont3_iface
;
2348 /* IDWriteFontList2 */
2349 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2351 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2353 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2354 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2355 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2356 IsEqualIID(riid
, &IID_IUnknown
))
2359 IDWriteFontList2_AddRef(iface
);
2363 WARN("%s not implemented.\n", debugstr_guid(riid
));
2366 return E_NOINTERFACE
;
2369 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2371 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2372 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2374 TRACE("%p, refcount %u.\n", iface
, refcount
);
2379 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2381 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2382 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2384 TRACE("%p, refcount %u.\n", iface
, refcount
);
2390 for (i
= 0; i
< fontlist
->font_count
; i
++)
2391 release_font_data(fontlist
->fonts
[i
]);
2392 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2393 heap_free(fontlist
->fonts
);
2394 heap_free(fontlist
);
2400 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2402 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2403 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2406 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2408 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2410 TRACE("%p.\n", iface
);
2412 return fontlist
->font_count
;
2415 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2417 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2419 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2423 if (fontlist
->font_count
== 0)
2426 if (index
>= fontlist
->font_count
)
2427 return E_INVALIDARG
;
2429 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2432 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2434 FIXME("%p, %u.\n", iface
, index
);
2436 return DWRITE_LOCALITY_LOCAL
;
2439 static HRESULT
fontlist_get_font(const struct dwrite_fontlist
*fontlist
, unsigned int index
,
2440 IDWriteFont3
**font
)
2444 if (fontlist
->font_count
== 0)
2447 if (index
>= fontlist
->font_count
)
2450 return create_font(fontlist
->family
, index
, font
);
2453 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2455 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2457 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2459 return fontlist_get_font(fontlist
, index
, font
);
2462 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2463 IDWriteFontFaceReference
**reference
)
2465 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2469 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2473 if (SUCCEEDED(hr
= fontlist_get_font(fontlist
, index
, &font
)))
2475 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2476 IDWriteFont3_Release(font
);
2482 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2484 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2486 TRACE("%p, %p.\n", iface
, fontset
);
2488 return fontset_create_from_font_data(fontlist
->family
->collection
->factory
, fontlist
->fonts
,
2489 fontlist
->font_count
, fontset
);
2492 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2494 dwritefontlist_QueryInterface
,
2495 dwritefontlist_AddRef
,
2496 dwritefontlist_Release
,
2497 dwritefontlist_GetFontCollection
,
2498 dwritefontlist_GetFontCount
,
2499 dwritefontlist_GetFont
,
2500 dwritefontlist1_GetFontLocality
,
2501 dwritefontlist1_GetFont
,
2502 dwritefontlist1_GetFontFaceReference
,
2503 dwritefontlist2_GetFontSet
,
2506 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2508 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2510 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2512 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2513 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2514 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2515 IsEqualIID(riid
, &IID_IUnknown
))
2519 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2520 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2521 IsEqualIID(riid
, &IID_IDWriteFontList
))
2523 *obj
= &family
->IDWriteFontList2_iface
;
2527 WARN("%s not implemented.\n", debugstr_guid(riid
));
2529 return E_NOINTERFACE
;
2532 IUnknown_AddRef((IUnknown
*)*obj
);
2536 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2538 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2539 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2541 TRACE("%p, %u.\n", iface
, refcount
);
2546 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2548 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2549 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2551 TRACE("%p, %u.\n", iface
, refcount
);
2555 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2556 release_fontfamily_data(family
->data
);
2563 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2565 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2567 TRACE("%p, %p.\n", iface
, collection
);
2569 *collection
= (IDWriteFontCollection
*)family
->collection
;
2570 IDWriteFontCollection_AddRef(*collection
);
2574 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2576 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2578 TRACE("%p.\n", iface
);
2580 return family
->data
->count
;
2583 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2585 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2587 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2591 if (!family
->data
->count
)
2594 if (index
>= family
->data
->count
)
2595 return E_INVALIDARG
;
2597 return create_font(family
, index
, (IDWriteFont3
**)font
);
2600 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2602 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2604 TRACE("%p, %p.\n", iface
, names
);
2606 return clone_localizedstrings(family
->data
->familyname
, names
);
2609 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2610 const struct dwrite_font_propvec
*req
)
2612 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2613 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2614 FLOAT cur_req_prod
, next_req_prod
;
2616 if (next_to_req
< cur_to_req
)
2619 if (next_to_req
> cur_to_req
)
2622 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2623 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2625 if (next_req_prod
> cur_req_prod
)
2628 if (next_req_prod
< cur_req_prod
)
2631 if (next
->stretch
> cur
->stretch
)
2633 if (next
->stretch
< cur
->stretch
)
2636 if (next
->style
> cur
->style
)
2638 if (next
->style
< cur
->style
)
2641 if (next
->weight
> cur
->weight
)
2643 if (next
->weight
< cur
->weight
)
2646 /* full match, no reason to prefer new variant */
2650 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2651 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2653 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2654 struct dwrite_font_propvec req
;
2657 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2659 if (!family
->data
->count
)
2662 return DWRITE_E_NOFONT
;
2665 init_font_prop_vec(weight
, stretch
, style
, &req
);
2668 for (i
= 1; i
< family
->data
->count
; ++i
)
2670 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2674 return create_font(family
, match
, (IDWriteFont3
**)font
);
2677 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2679 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2681 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2684 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2686 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2689 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2691 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2696 for (j
= 0; j
< b
; j
++) {
2697 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2698 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2699 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2700 fonts
->fonts
[j
+1] = s
;
2711 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2712 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2714 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2715 matching_filter_func func
= NULL
;
2716 struct dwrite_font_propvec req
;
2717 struct dwrite_fontlist
*fonts
;
2720 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2724 fonts
= heap_alloc(sizeof(*fonts
));
2726 return E_OUTOFMEMORY
;
2728 /* Allocate as many as family has, not all of them will be necessary used. */
2729 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2730 if (!fonts
->fonts
) {
2732 return E_OUTOFMEMORY
;
2735 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2736 fonts
->refcount
= 1;
2737 fonts
->family
= family
;
2738 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2739 fonts
->font_count
= 0;
2741 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2742 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2743 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2744 func
= is_font_acceptable_for_normal
;
2746 else /* requested oblique or italic */ {
2747 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2748 func
= is_font_acceptable_for_oblique_italic
;
2751 for (i
= 0; i
< family
->data
->count
; ++i
)
2753 if (!func
|| func(family
->data
->fonts
[i
]))
2755 fonts
->fonts
[fonts
->font_count
++] = addref_font_data(family
->data
->fonts
[i
]);
2759 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2760 init_font_prop_vec(weight
, stretch
, style
, &req
);
2761 matchingfonts_sort(fonts
, &req
);
2763 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2767 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2769 FIXME("%p, %u.\n", iface
, index
);
2771 return DWRITE_LOCALITY_LOCAL
;
2774 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2776 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2778 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2782 if (!family
->data
->count
)
2785 if (index
>= family
->data
->count
)
2788 return create_font(family
, index
, font
);
2791 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2792 IDWriteFontFaceReference
**reference
)
2794 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2795 const struct dwrite_font_data
*font
;
2797 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2801 if (index
>= family
->data
->count
)
2804 font
= family
->data
->fonts
[index
];
2805 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
2806 font
->file
, font
->face_index
, font
->simulations
, reference
);
2809 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2810 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2812 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2817 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2819 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2821 TRACE("%p, %p.\n", iface
, fontset
);
2823 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
2824 family
->data
->count
, fontset
);
2827 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2829 dwritefontfamily_QueryInterface
,
2830 dwritefontfamily_AddRef
,
2831 dwritefontfamily_Release
,
2832 dwritefontfamily_GetFontCollection
,
2833 dwritefontfamily_GetFontCount
,
2834 dwritefontfamily_GetFont
,
2835 dwritefontfamily_GetFamilyNames
,
2836 dwritefontfamily_GetFirstMatchingFont
,
2837 dwritefontfamily_GetMatchingFonts
,
2838 dwritefontfamily1_GetFontLocality
,
2839 dwritefontfamily1_GetFont
,
2840 dwritefontfamily1_GetFontFaceReference
,
2841 dwritefontfamily2_GetMatchingFonts
,
2842 dwritefontfamily2_GetFontSet
,
2845 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2847 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2848 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2851 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2853 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2854 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2857 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2859 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2860 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2863 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2864 IDWriteFontCollection
**collection
)
2866 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2867 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2870 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2872 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2873 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2876 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2878 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2879 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2882 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2884 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2885 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2888 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2890 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2891 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2894 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2895 IDWriteFontFaceReference
**reference
)
2897 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2898 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2901 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2903 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2905 TRACE("%p, %p.\n", iface
, fontset
);
2907 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
2908 family
->data
->count
, fontset
);
2911 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2913 dwritefontfamilylist_QueryInterface
,
2914 dwritefontfamilylist_AddRef
,
2915 dwritefontfamilylist_Release
,
2916 dwritefontfamilylist_GetFontCollection
,
2917 dwritefontfamilylist_GetFontCount
,
2918 dwritefontfamilylist_GetFont
,
2919 dwritefontfamilylist1_GetFontLocality
,
2920 dwritefontfamilylist1_GetFont
,
2921 dwritefontfamilylist1_GetFontFaceReference
,
2922 dwritefontfamilylist2_GetFontSet
,
2925 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2926 struct dwrite_fontfamily
**family
)
2928 struct dwrite_fontfamily
*object
;
2932 object
= heap_alloc(sizeof(*object
));
2934 return E_OUTOFMEMORY
;
2936 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2937 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2938 object
->refcount
= 1;
2939 object
->collection
= collection
;
2940 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2941 object
->data
= collection
->family_data
[index
];
2942 InterlockedIncrement(&object
->data
->refcount
);
2949 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2952 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2955 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2957 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2959 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2961 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2962 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2963 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2964 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2965 IsEqualIID(riid
, &IID_IUnknown
))
2968 IDWriteFontCollection3_AddRef(iface
);
2974 if (IsEqualIID(riid
, &IID_issystemcollection
))
2977 WARN("%s not implemented.\n", debugstr_guid(riid
));
2979 return E_NOINTERFACE
;
2982 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2984 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2986 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2987 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2988 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2989 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2990 IsEqualIID(riid
, &IID_IUnknown
))
2993 IDWriteFontCollection3_AddRef(iface
);
2997 WARN("%s not implemented.\n", debugstr_guid(riid
));
3001 return E_NOINTERFACE
;
3004 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
3006 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3007 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
3009 TRACE("%p, refcount %d.\n", collection
, refcount
);
3014 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
3016 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3017 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
3020 TRACE("%p, refcount %d.\n", iface
, refcount
);
3024 factory_detach_fontcollection(collection
->factory
, iface
);
3025 for (i
= 0; i
< collection
->count
; ++i
)
3026 release_fontfamily_data(collection
->family_data
[i
]);
3027 heap_free(collection
->family_data
);
3028 heap_free(collection
);
3034 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
3036 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3038 TRACE("%p.\n", iface
);
3040 return collection
->count
;
3043 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3044 IDWriteFontFamily
**ret
)
3046 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3047 struct dwrite_fontfamily
*family
;
3050 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3054 if (index
>= collection
->count
)
3057 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3058 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
3063 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
3067 for (i
= 0; i
< collection
->count
; ++i
)
3069 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
3070 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
3073 for (j
= 0; j
< count
; j
++) {
3075 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
3076 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
3084 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
3085 UINT32
*index
, BOOL
*exists
)
3087 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3089 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
3091 *index
= collection_find_family(collection
, name
);
3092 *exists
= *index
!= ~0u;
3096 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
3099 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3100 struct dwrite_fontfamily
*family
;
3101 BOOL found_font
= FALSE
;
3102 IDWriteFontFile
*file
;
3103 UINT32 face_index
, count
;
3107 TRACE("%p, %p, %p.\n", iface
, face
, font
);
3112 return E_INVALIDARG
;
3115 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
3118 face_index
= IDWriteFontFace_GetIndex(face
);
3121 for (i
= 0; i
< collection
->count
; ++i
)
3123 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
3125 for (j
= 0; j
< family_data
->count
; ++j
)
3127 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
3129 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
3138 IDWriteFontFile_Release(file
);
3141 return DWRITE_E_NOFONT
;
3143 hr
= create_fontfamily(collection
, i
, &family
);
3147 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3148 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3152 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3154 FIXME("%p, %p.\n", iface
, fontset
);
3159 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3160 IDWriteFontFamily1
**ret
)
3162 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3163 struct dwrite_fontfamily
*family
;
3166 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3170 if (index
>= collection
->count
)
3173 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3174 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3179 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3180 UINT32 index
, IDWriteFontFamily2
**ret
)
3182 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3183 struct dwrite_fontfamily
*family
;
3186 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3190 if (index
>= collection
->count
)
3193 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3194 *ret
= &family
->IDWriteFontFamily2_iface
;
3199 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3200 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3201 IDWriteFontList2
**fontlist
)
3203 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3208 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3210 FIXME("%p.\n", iface
);
3212 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3215 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3217 FIXME("%p, %p.\n", iface
, fontset
);
3222 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3224 FIXME("%p.\n", iface
);
3229 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3231 dwritefontcollection_QueryInterface
,
3232 dwritefontcollection_AddRef
,
3233 dwritefontcollection_Release
,
3234 dwritefontcollection_GetFontFamilyCount
,
3235 dwritefontcollection_GetFontFamily
,
3236 dwritefontcollection_FindFamilyName
,
3237 dwritefontcollection_GetFontFromFontFace
,
3238 dwritefontcollection1_GetFontSet
,
3239 dwritefontcollection1_GetFontFamily
,
3240 dwritefontcollection2_GetFontFamily
,
3241 dwritefontcollection2_GetMatchingFonts
,
3242 dwritefontcollection2_GetFontFamilyModel
,
3243 dwritefontcollection2_GetFontSet
,
3244 dwritefontcollection3_GetExpirationEvent
,
3247 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3249 dwritesystemfontcollection_QueryInterface
,
3250 dwritefontcollection_AddRef
,
3251 dwritefontcollection_Release
,
3252 dwritefontcollection_GetFontFamilyCount
,
3253 dwritefontcollection_GetFontFamily
,
3254 dwritefontcollection_FindFamilyName
,
3255 dwritefontcollection_GetFontFromFontFace
,
3256 dwritefontcollection1_GetFontSet
,
3257 dwritefontcollection1_GetFontFamily
,
3258 dwritefontcollection2_GetFontFamily
,
3259 dwritefontcollection2_GetMatchingFonts
,
3260 dwritefontcollection2_GetFontFamilyModel
,
3261 dwritefontcollection2_GetFontSet
,
3262 dwritefontcollection3_GetExpirationEvent
,
3265 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3267 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3268 sizeof(*family_data
->fonts
)))
3270 return E_OUTOFMEMORY
;
3273 family_data
->fonts
[family_data
->count
++] = font_data
;
3274 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3275 family_data
->has_normal_face
= 1;
3276 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3277 family_data
->has_oblique_face
= 1;
3279 family_data
->has_italic_face
= 1;
3283 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3284 struct dwrite_fontfamily_data
*family
)
3286 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3287 sizeof(*collection
->family_data
)))
3289 return E_OUTOFMEMORY
;
3292 collection
->family_data
[collection
->count
++] = family
;
3296 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3298 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3299 collection
->refcount
= 1;
3300 collection
->count
= 0;
3301 collection
->size
= 0;
3302 collection
->family_data
= NULL
;
3307 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3309 IDWriteFontFileLoader
*loader
;
3316 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3320 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3324 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3325 IDWriteFontFileLoader_Release(loader
);
3332 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3334 BOOL exists
= FALSE
;
3339 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
3340 if (FAILED(hr
) || !exists
)
3343 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3346 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3350 while (isspaceW(*in
))
3354 if (!(len
= strlenW(in
)))
3357 while (isspaceW(in
[len
-1]))
3360 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3369 INT len
; /* token length */
3370 INT fulllen
; /* full length including following separators */
3373 static inline BOOL
is_name_separator_char(WCHAR ch
)
3375 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3378 struct name_pattern
{
3379 const WCHAR
*part1
; /* NULL indicates end of list */
3380 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3383 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3385 const struct name_pattern
*pattern
;
3386 struct name_token
*token
;
3389 while ((pattern
= &patterns
[i
++])->part1
) {
3390 int len_part1
= strlenW(pattern
->part1
);
3391 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
3393 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
3394 if (len_part2
== 0) {
3395 /* simple case with single part pattern */
3396 if (token
->len
!= len_part1
)
3399 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3400 if (match
) *match
= *token
;
3401 list_remove(&token
->entry
);
3407 struct name_token
*next_token
;
3408 struct list
*next_entry
;
3410 /* pattern parts are stored in reading order, tokens list is reversed */
3411 if (token
->len
< len_part2
)
3414 /* it's possible to have combined string as a token, like ExtraCondensed */
3415 if (token
->len
== len_part1
+ len_part2
) {
3416 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3419 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3422 /* combined string match */
3423 if (match
) *match
= *token
;
3424 list_remove(&token
->entry
);
3429 /* now it's only possible to have two tokens matched to respective pattern parts */
3430 if (token
->len
!= len_part2
)
3433 next_entry
= list_next(tokens
, &token
->entry
);
3435 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3436 if (next_token
->len
!= len_part1
)
3439 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3442 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3445 /* both parts matched, remove tokens */
3447 match
->ptr
= next_token
->ptr
;
3448 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3450 list_remove(&token
->entry
);
3451 list_remove(&next_token
->entry
);
3452 heap_free(next_token
);
3467 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3469 static const WCHAR itaW
[] = {'i','t','a',0};
3470 static const WCHAR italW
[] = {'i','t','a','l',0};
3471 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3472 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3474 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3475 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3476 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3477 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3479 static const struct name_pattern italic_patterns
[] = {
3488 static const struct name_pattern oblique_patterns
[] = {
3497 /* italic patterns first */
3498 if (match_pattern_list(tokens
, italic_patterns
, match
))
3499 return DWRITE_FONT_STYLE_ITALIC
;
3501 /* oblique patterns */
3502 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3503 return DWRITE_FONT_STYLE_OBLIQUE
;
3508 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3509 struct name_token
*match
)
3511 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3512 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3513 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3514 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3515 static const WCHAR wideW
[] = {'w','i','d','e',0};
3516 static const WCHAR condW
[] = {'c','o','n','d',0};
3518 static const struct name_pattern ultracondensed_patterns
[] = {
3519 { extraW
, compressedW
},
3520 { extW
, compressedW
},
3521 { ultraW
, compressedW
},
3522 { ultraW
, condensedW
},
3527 static const struct name_pattern extracondensed_patterns
[] = {
3529 { extraW
, condensedW
},
3530 { extW
, condensedW
},
3536 static const struct name_pattern semicondensed_patterns
[] = {
3539 { semiW
, condensedW
},
3544 static const struct name_pattern semiexpanded_patterns
[] = {
3546 { semiW
, expandedW
},
3547 { semiW
, extendedW
},
3551 static const struct name_pattern extraexpanded_patterns
[] = {
3552 { extraW
, expandedW
},
3553 { extW
, expandedW
},
3554 { extraW
, extendedW
},
3555 { extW
, extendedW
},
3559 static const struct name_pattern ultraexpanded_patterns
[] = {
3560 { ultraW
, expandedW
},
3561 { ultraW
, extendedW
},
3565 static const struct name_pattern condensed_patterns
[] = {
3571 static const struct name_pattern expanded_patterns
[] = {
3577 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3578 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3580 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3581 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3583 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3584 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3586 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3587 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3589 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3590 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3592 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3593 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3595 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3596 return DWRITE_FONT_STRETCH_CONDENSED
;
3598 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3599 return DWRITE_FONT_STRETCH_EXPANDED
;
3604 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3605 struct name_token
*match
)
3607 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3608 static const WCHAR nordW
[] = {'n','o','r','d',0};
3610 static const struct name_pattern thin_patterns
[] = {
3617 static const struct name_pattern extralight_patterns
[] = {
3624 static const struct name_pattern semilight_patterns
[] = {
3629 static const struct name_pattern demibold_patterns
[] = {
3635 static const struct name_pattern extrabold_patterns
[] = {
3642 static const struct name_pattern extrablack_patterns
[] = {
3649 static const struct name_pattern bold_patterns
[] = {
3654 static const struct name_pattern thin2_patterns
[] = {
3659 static const struct name_pattern light_patterns
[] = {
3664 static const struct name_pattern medium_patterns
[] = {
3669 static const struct name_pattern black_patterns
[] = {
3676 static const struct name_pattern demibold2_patterns
[] = {
3681 static const struct name_pattern extrabold2_patterns
[] = {
3686 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3687 matching pattern. */
3689 if (match_pattern_list(tokens
, thin_patterns
, match
))
3690 return DWRITE_FONT_WEIGHT_THIN
;
3692 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3693 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3695 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3696 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3698 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3699 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3701 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3702 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3704 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3705 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3707 if (match_pattern_list(tokens
, bold_patterns
, match
))
3708 return DWRITE_FONT_WEIGHT_BOLD
;
3710 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3711 return DWRITE_FONT_WEIGHT_THIN
;
3713 if (match_pattern_list(tokens
, light_patterns
, match
))
3714 return DWRITE_FONT_WEIGHT_LIGHT
;
3716 if (match_pattern_list(tokens
, medium_patterns
, match
))
3717 return DWRITE_FONT_WEIGHT_MEDIUM
;
3719 if (match_pattern_list(tokens
, black_patterns
, match
))
3720 return DWRITE_FONT_WEIGHT_BLACK
;
3722 if (match_pattern_list(tokens
, black_patterns
, match
))
3723 return DWRITE_FONT_WEIGHT_BLACK
;
3725 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3726 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3728 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3729 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3731 /* FIXME: use abbreviated names to extract weight */
3736 struct knownweight_entry
{
3738 DWRITE_FONT_WEIGHT weight
;
3741 static int compare_knownweights(const void *a
, const void* b
)
3743 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3744 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3747 if (target
> entry
->weight
)
3749 else if (target
< entry
->weight
)
3755 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3757 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3758 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3759 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3760 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3761 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3762 static const WCHAR thinW
[] = {'T','h','i','n',0};
3763 static const WCHAR lightW
[] = {'L','i','g','h','t',0};
3764 static const WCHAR mediumW
[] = {'M','e','d','i','u','m',0};
3765 static const WCHAR blackW
[] = {'B','l','a','c','k',0};
3766 const struct knownweight_entry
*ptr
;
3768 static const struct knownweight_entry knownweights
[] = {
3769 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3770 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3771 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3772 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3773 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3774 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3775 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3776 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3777 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3778 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3781 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3782 compare_knownweights
);
3788 strcpyW(nameW
, ptr
->nameW
);
3792 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3794 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3795 strW
[name
->len
] = 0;
3798 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3799 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3801 static const WCHAR bookW
[] = {'B','o','o','k',0};
3802 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3803 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3804 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3805 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3807 static const WCHAR
*regular_patterns
[] = {
3816 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3820 len
= strlenW(facenameW
);
3822 /* remove rightmost regular variant from face name */
3823 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3824 int pattern_len
= strlenW(ptr
);
3827 if (pattern_len
> len
)
3830 src
= facenameW
+ len
- pattern_len
;
3831 while (src
>= facenameW
) {
3832 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3833 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3834 len
= strlenW(facenameW
);
3846 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3854 struct name_token
*token
= heap_alloc(sizeof(*token
));
3859 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3865 /* skip separators */
3866 while (is_name_separator_char(*ptr
)) {
3871 list_add_head(tokens
, &token
->entry
);
3875 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3877 struct name_token
*token
, *token2
;
3878 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3881 list_remove(&token
->entry
);
3883 /* don't include last separator */
3884 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3885 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3893 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3895 struct name_token stretch_name
, weight_name
, style_name
;
3896 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3897 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3898 const WCHAR
*regular_ptr
= NULL
;
3899 DWRITE_FONT_STRETCH stretch
;
3900 DWRITE_FONT_WEIGHT weight
;
3904 /* remove leading and trailing spaces from family and face name */
3905 trim_spaces(familyW
, familynameW
);
3906 len
= trim_spaces(faceW
, facenameW
);
3908 /* remove rightmost regular variant from face name */
3909 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3911 /* append face name to family name, FIXME check if face name is a substring of family name */
3913 strcatW(familynameW
, spaceW
);
3914 strcatW(familynameW
, facenameW
);
3917 /* tokenize with " .-_" */
3918 fontname_tokenize(&tokens
, familynameW
);
3920 /* extract and resolve style */
3921 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3923 /* extract stretch */
3924 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3926 /* extract weight */
3927 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3929 /* resolve weight */
3930 if (weight
!= font
->weight
) {
3931 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3932 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3933 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3934 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3935 !(abs(weight
- font
->weight
) <= 150 &&
3936 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3937 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3938 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3940 font
->weight
= weight
;
3944 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3945 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3946 stretch itself is normal (extracted stretch is never normal). */
3947 if (stretch
!= font
->stretch
) {
3948 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3949 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3950 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3952 font
->stretch
= stretch
;
3956 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3958 /* get final combined string from what's left in token list, list is released */
3959 fontname_tokens_to_str(&tokens
, finalW
);
3961 if (!strcmpW(familyW
, finalW
))
3964 /* construct face name */
3965 strcpyW(familyW
, finalW
);
3967 /* resolved weight name */
3968 if (weight_name
.ptr
)
3969 font_name_token_to_str(&weight_name
, weightW
);
3970 /* ignore normal weight */
3971 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3973 /* for known weight values use appropriate names */
3974 else if (is_known_weight_value(font
->weight
, weightW
)) {
3976 /* use Wnnn format as a fallback in case weight is not one of known values */
3978 static const WCHAR fmtW
[] = {'W','%','d',0};
3979 sprintfW(weightW
, fmtW
, font
->weight
);
3982 /* resolved stretch name */
3983 if (stretch_name
.ptr
)
3984 font_name_token_to_str(&stretch_name
, stretchW
);
3985 /* ignore normal stretch */
3986 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3988 /* use predefined stretch names */
3990 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3991 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3992 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3993 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3994 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3995 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3997 static const WCHAR
*stretchnamesW
[] = {
3998 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4003 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
4009 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
4012 /* resolved style name */
4014 font_name_token_to_str(&style_name
, styleW
);
4015 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
4017 /* use predefined names */
4019 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
4020 strcpyW(styleW
, italicW
);
4022 strcpyW(styleW
, obliqueW
);
4025 /* use Regular match if it was found initially */
4026 if (!*weightW
&& !*stretchW
&& !*styleW
)
4027 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
4031 strcpyW(faceW
, stretchW
);
4034 strcatW(faceW
, spaceW
);
4035 strcatW(faceW
, weightW
);
4039 strcatW(faceW
, spaceW
);
4040 strcatW(faceW
, styleW
);
4044 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
4048 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
4050 static const float width_axis_values
[] =
4052 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4053 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
4054 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
4055 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
4056 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
4057 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
4058 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
4059 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
4060 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
4061 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
4064 struct file_stream_desc stream_desc
;
4065 struct dwrite_font_props props
;
4066 struct dwrite_font_data
*data
;
4067 WCHAR familyW
[255], faceW
[255];
4072 data
= heap_alloc_zero(sizeof(*data
));
4074 return E_OUTOFMEMORY
;
4077 data
->file
= desc
->file
;
4078 data
->face_index
= desc
->index
;
4079 data
->face_type
= desc
->face_type
;
4080 IDWriteFontFile_AddRef(data
->file
);
4082 stream_desc
.stream
= desc
->stream
;
4083 stream_desc
.face_type
= desc
->face_type
;
4084 stream_desc
.face_index
= desc
->index
;
4085 opentype_get_font_properties(&stream_desc
, &props
);
4086 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
4087 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
4089 /* get family name from font file */
4090 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
4092 WARN("unable to get family name from font\n");
4093 release_font_data(data
);
4097 data
->style
= props
.style
;
4098 data
->stretch
= props
.stretch
;
4099 data
->weight
= props
.weight
;
4100 data
->panose
= props
.panose
;
4101 data
->fontsig
= props
.fontsig
;
4102 data
->lf
= props
.lf
;
4103 data
->flags
= props
.flags
;
4105 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4106 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
4107 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
4108 set_en_localizedstring(data
->family_names
, familyW
);
4109 set_en_localizedstring(data
->names
, faceW
);
4112 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4114 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
4115 data
->axis
[0].value
= props
.weight
;
4116 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
4117 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
4118 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
4119 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
4125 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS simulations
,
4126 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
4128 struct dwrite_font_data
*data
;
4132 data
= heap_alloc_zero(sizeof(*data
));
4134 return E_OUTOFMEMORY
;
4138 data
->simulations
|= simulations
;
4139 if (simulations
& DWRITE_FONT_SIMULATIONS_BOLD
)
4140 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
4141 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4142 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4143 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4145 IDWriteFontFile_AddRef(data
->file
);
4146 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4148 create_localizedstrings(&data
->names
);
4149 add_localizedstring(data
->names
, enusW
, facenameW
);
4151 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4157 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4159 struct dwrite_fontfamily_data
*data
;
4161 data
= heap_alloc_zero(sizeof(*data
));
4163 return E_OUTOFMEMORY
;
4166 data
->familyname
= familyname
;
4167 IDWriteLocalizedStrings_AddRef(familyname
);
4174 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4176 size_t i
, j
, heaviest
;
4178 for (i
= 0; i
< family
->count
; ++i
)
4180 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4183 if (family
->fonts
[i
]->bold_sim_tested
)
4186 family
->fonts
[i
]->bold_sim_tested
= 1;
4187 for (j
= i
; j
< family
->count
; ++j
)
4189 if (family
->fonts
[j
]->bold_sim_tested
)
4192 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4193 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4194 if (family
->fonts
[j
]->weight
> weight
) {
4195 weight
= family
->fonts
[j
]->weight
;
4198 family
->fonts
[j
]->bold_sim_tested
= 1;
4202 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
4203 static const struct name_pattern weightsim_patterns
[] = {
4218 WCHAR facenameW
[255], initialW
[255];
4219 struct dwrite_font_data
*boldface
;
4222 /* add Bold simulation based on heaviest face data */
4224 /* Simulated face name should only contain Bold as weight term,
4225 so remove existing regular and weight terms. */
4226 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4227 facename_remove_regular_term(initialW
, -1);
4229 /* remove current weight pattern */
4230 fontname_tokenize(&tokens
, initialW
);
4231 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4232 fontname_tokens_to_str(&tokens
, facenameW
);
4234 /* Bold suffix for new name */
4236 strcatW(facenameW
, spaceW
);
4237 strcatW(facenameW
, boldW
);
4239 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4240 boldface
->bold_sim_tested
= 1;
4241 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4242 fontfamily_add_font(family
, boldface
);
4248 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4252 for (i
= 0; i
< family
->count
; ++i
)
4254 UINT32 regular
= ~0u, oblique
= ~0u;
4255 struct dwrite_font_data
*obliqueface
;
4256 WCHAR facenameW
[255];
4258 if (family
->fonts
[i
]->oblique_sim_tested
)
4261 family
->fonts
[i
]->oblique_sim_tested
= 1;
4262 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4264 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4267 /* find regular style with same weight/stretch values */
4268 for (j
= i
; j
< family
->count
; ++j
)
4270 if (family
->fonts
[j
]->oblique_sim_tested
)
4273 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4274 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4276 family
->fonts
[j
]->oblique_sim_tested
= 1;
4277 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4280 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4284 if (regular
!= ~0u && oblique
!= ~0u)
4288 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4292 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4296 /* add oblique simulation based on this regular face */
4298 /* remove regular term if any, append 'Oblique' */
4299 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4300 facename_remove_regular_term(facenameW
, -1);
4303 strcatW(facenameW
, spaceW
);
4304 strcatW(facenameW
, obliqueW
);
4306 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4307 obliqueface
->oblique_sim_tested
= 1;
4308 obliqueface
->lf
.lfItalic
= 1;
4309 fontfamily_add_font(family
, obliqueface
);
4314 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4315 const WCHAR
*replacement_name
)
4317 UINT32 i
= collection_find_family(collection
, replacement_name
);
4318 struct dwrite_fontfamily_data
*target
;
4319 IDWriteLocalizedStrings
*strings
;
4322 /* replacement does not exist */
4326 hr
= create_localizedstrings(&strings
);
4330 /* add a new family with target name, reuse font data from replacement */
4331 add_localizedstring(strings
, enusW
, target_name
);
4332 hr
= init_fontfamily_data(strings
, &target
);
4334 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4337 for (i
= 0; i
< replacement
->count
; ++i
)
4339 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4340 addref_font_data(replacement
->fonts
[i
]);
4343 fontcollection_add_family(collection
, target
);
4344 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4345 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4347 IDWriteLocalizedStrings_Release(strings
);
4351 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4352 system font collections. */
4353 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4355 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4360 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4363 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4368 max_namelen
++; /* returned value doesn't include room for '\0' */
4369 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
4370 data
= heap_alloc(max_datalen
);
4372 datalen
= max_datalen
;
4373 namelen
= max_namelen
;
4374 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4375 if (collection_find_family(collection
, name
) == ~0u) {
4376 if (type
== REG_MULTI_SZ
) {
4377 WCHAR
*replacement
= data
;
4378 while (*replacement
) {
4379 if (fontcollection_add_replacement(collection
, name
, replacement
))
4381 replacement
+= strlenW(replacement
) + 1;
4384 else if (type
== REG_SZ
)
4385 fontcollection_add_replacement(collection
, name
, data
);
4388 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4390 datalen
= max_datalen
;
4391 namelen
= max_namelen
;
4399 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4400 IDWriteFontCollection3
**ret
)
4402 struct fontfile_enum
{
4404 IDWriteFontFile
*file
;
4406 struct fontfile_enum
*fileenum
, *fileenum2
;
4407 struct dwrite_fontcollection
*collection
;
4408 struct list scannedfiles
;
4409 BOOL current
= FALSE
;
4415 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4416 if (!collection
) return E_OUTOFMEMORY
;
4418 hr
= init_font_collection(collection
, is_system
);
4420 heap_free(collection
);
4424 *ret
= &collection
->IDWriteFontCollection3_iface
;
4426 TRACE("building font collection:\n");
4428 list_init(&scannedfiles
);
4429 while (hr
== S_OK
) {
4430 DWRITE_FONT_FACE_TYPE face_type
;
4431 DWRITE_FONT_FILE_TYPE file_type
;
4432 BOOL supported
, same
= FALSE
;
4433 IDWriteFontFileStream
*stream
;
4434 IDWriteFontFile
*file
;
4438 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4439 if (FAILED(hr
) || !current
)
4442 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4446 /* check if we've scanned this file already */
4447 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4448 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4453 IDWriteFontFile_Release(file
);
4457 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4458 IDWriteFontFile_Release(file
);
4462 /* Unsupported formats are skipped. */
4463 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4464 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4465 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4466 IDWriteFontFileStream_Release(stream
);
4467 IDWriteFontFile_Release(file
);
4472 /* add to scanned list */
4473 fileenum
= heap_alloc(sizeof(*fileenum
));
4474 fileenum
->file
= file
;
4475 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4477 for (i
= 0; i
< face_count
; ++i
)
4479 struct dwrite_font_data
*font_data
;
4480 struct fontface_desc desc
;
4484 desc
.factory
= factory
;
4485 desc
.face_type
= face_type
;
4487 desc
.stream
= stream
;
4489 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4490 desc
.font_data
= NULL
;
4492 /* Allocate an initialize new font data structure. */
4493 hr
= init_font_data(&desc
, &font_data
);
4496 /* move to next one */
4501 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4503 /* ignore dot named faces */
4504 if (familyW
[0] == '.')
4506 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4507 release_font_data(font_data
);
4511 index
= collection_find_family(collection
, familyW
);
4513 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4515 struct dwrite_fontfamily_data
*family_data
;
4517 /* create and init new family */
4518 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4520 /* add font to family, family - to collection */
4521 hr
= fontfamily_add_font(family_data
, font_data
);
4523 hr
= fontcollection_add_family(collection
, family_data
);
4526 release_fontfamily_data(family_data
);
4534 IDWriteFontFileStream_Release(stream
);
4537 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4538 IDWriteFontFile_Release(fileenum
->file
);
4539 list_remove(&fileenum
->entry
);
4540 heap_free(fileenum
);
4543 for (i
= 0; i
< collection
->count
; ++i
)
4545 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4546 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4550 fontcollection_add_replacements(collection
);
4552 collection
->factory
= factory
;
4553 IDWriteFactory7_AddRef(factory
);
4558 struct system_fontfile_enumerator
4560 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4563 IDWriteFactory7
*factory
;
4568 DWORD filename_size
;
4571 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4573 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4576 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4578 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4579 IDWriteFontFileEnumerator_AddRef(iface
);
4584 WARN("%s not implemented.\n", debugstr_guid(riid
));
4588 return E_NOINTERFACE
;
4591 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4593 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4594 return InterlockedIncrement(&enumerator
->refcount
);
4597 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4599 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4600 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
4604 IDWriteFactory7_Release(enumerator
->factory
);
4605 RegCloseKey(enumerator
->hkey
);
4606 heap_free(enumerator
->filename
);
4607 heap_free(enumerator
);
4613 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4617 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4618 if (!strchrW(filename
, '\\')) {
4619 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4620 WCHAR fullpathW
[MAX_PATH
];
4622 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4623 strcatW(fullpathW
, fontsW
);
4624 strcatW(fullpathW
, filename
);
4626 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4629 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4634 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4636 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4640 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4643 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4646 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4648 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4649 WCHAR name_buf
[256], *name
= name_buf
;
4650 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4655 enumerator
->index
++;
4657 /* iterate until we find next string value */
4660 name_count
= max_name_count
;
4661 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4663 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4664 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4665 if (r
== ERROR_MORE_DATA
) {
4666 if (name_count
>= max_name_count
) {
4667 if (name
!= name_buf
) heap_free(name
);
4668 max_name_count
*= 2;
4669 name
= heap_alloc(max_name_count
* sizeof(*name
));
4670 if (!name
) return E_OUTOFMEMORY
;
4672 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4673 heap_free(enumerator
->filename
);
4674 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4675 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4676 if (!enumerator
->filename
) {
4682 } while (r
== ERROR_MORE_DATA
);
4684 if (r
!= ERROR_SUCCESS
) {
4685 enumerator
->filename
[0] = 0;
4688 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4689 if (type
== REG_SZ
&& *name
!= '@') {
4693 enumerator
->index
++;
4695 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4698 if (name
!= name_buf
) heap_free(name
);
4702 static const IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4704 systemfontfileenumerator_QueryInterface
,
4705 systemfontfileenumerator_AddRef
,
4706 systemfontfileenumerator_Release
,
4707 systemfontfileenumerator_MoveNext
,
4708 systemfontfileenumerator_GetCurrentFontFile
4711 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4713 struct system_fontfile_enumerator
*enumerator
;
4714 static const WCHAR fontslistW
[] = {
4715 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4716 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4717 'F','o','n','t','s',0
4722 enumerator
= heap_alloc(sizeof(*enumerator
));
4724 return E_OUTOFMEMORY
;
4726 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4727 enumerator
->refcount
= 1;
4728 enumerator
->factory
= factory
;
4729 enumerator
->index
= -1;
4730 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4731 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4732 if (!enumerator
->filename
) {
4733 heap_free(enumerator
);
4734 return E_OUTOFMEMORY
;
4737 IDWriteFactory7_AddRef(factory
);
4739 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4741 ERR("failed to open fonts list key\n");
4742 IDWriteFactory7_Release(factory
);
4743 heap_free(enumerator
->filename
);
4744 heap_free(enumerator
);
4748 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4753 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4755 IDWriteFontFileEnumerator
*enumerator
;
4760 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4764 TRACE("building system font collection for factory %p\n", factory
);
4765 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4766 IDWriteFontFileEnumerator_Release(enumerator
);
4770 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4771 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4773 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};
4774 static const WCHAR emptyW
[] = {0};
4775 struct dwrite_fontfamily_data
*family_data
;
4776 IDWriteLocalizedStrings
*names
;
4777 DWRITE_FONT_FACE_TYPE face_type
;
4778 DWRITE_FONT_FILE_TYPE file_type
;
4779 IDWriteFontFileStream
*stream
;
4780 IDWriteFontFile
*file
;
4781 UINT32 face_count
, i
;
4785 /* create font file from this path */
4786 hr
= create_local_file_reference(factory
, pathW
, &file
);
4790 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4791 IDWriteFontFile_Release(file
);
4795 /* Unsupported formats are skipped. */
4796 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4797 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4798 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4799 IDWriteFontFileStream_Release(stream
);
4800 IDWriteFontFile_Release(file
);
4804 /* create and init new family */
4806 /* Family names are added for non-specific locale, represented with empty string.
4807 Default family appears with empty family name. */
4808 create_localizedstrings(&names
);
4809 if (!strcmpiW(keynameW
, defaultfontW
))
4810 add_localizedstring(names
, emptyW
, emptyW
);
4812 add_localizedstring(names
, emptyW
, keynameW
);
4814 hr
= init_fontfamily_data(names
, &family_data
);
4815 IDWriteLocalizedStrings_Release(names
);
4817 IDWriteFontFile_Release(file
);
4821 /* fill with faces */
4822 for (i
= 0; i
< face_count
; i
++) {
4823 struct dwrite_font_data
*font_data
;
4824 struct fontface_desc desc
;
4826 /* Allocate new font data structure. */
4827 desc
.factory
= factory
;
4828 desc
.face_type
= face_type
;
4831 desc
.stream
= stream
;
4832 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4833 desc
.font_data
= NULL
;
4835 hr
= init_font_data(&desc
, &font_data
);
4839 /* add font to family */
4840 hr
= fontfamily_add_font(family_data
, font_data
);
4842 release_font_data(font_data
);
4845 /* add family to collection */
4846 hr
= fontcollection_add_family(collection
, family_data
);
4848 release_fontfamily_data(family_data
);
4849 IDWriteFontFileStream_Release(stream
);
4850 IDWriteFontFile_Release(file
);
4855 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4857 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4858 struct dwrite_fontcollection
*collection
;
4859 static const WCHAR emptyW
[] = {0};
4860 WCHAR eudckeypathW
[16];
4868 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4872 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4873 if (!collection
) return E_OUTOFMEMORY
;
4875 hr
= init_font_collection(collection
, FALSE
);
4877 heap_free(collection
);
4881 *ret
= &collection
->IDWriteFontCollection3_iface
;
4882 collection
->factory
= factory
;
4883 IDWriteFactory7_AddRef(factory
);
4885 /* return empty collection if EUDC fonts are not configured */
4886 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4887 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4890 retval
= ERROR_SUCCESS
;
4892 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4893 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4894 DWORD type
, path_len
, name_len
;
4896 path_len
= ARRAY_SIZE(pathW
);
4897 name_len
= ARRAY_SIZE(keynameW
);
4898 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4899 if (retval
|| type
!= REG_SZ
)
4902 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4904 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4906 RegCloseKey(eudckey
);
4908 /* try to add global default if not defined for specific codepage */
4910 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4912 if (FAILED(hr
) || !exists
) {
4913 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4914 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4916 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4919 /* EUDC collection offers simulated faces too */
4920 for (i
= 0; i
< collection
->count
; ++i
)
4922 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4923 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4929 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4931 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
4933 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4936 IDWriteFontFile_AddRef(iface
);
4940 WARN("%s not implemented.\n", debugstr_guid(riid
));
4943 return E_NOINTERFACE
;
4946 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4948 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4949 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
4951 TRACE("%p, refcount %d.\n", iface
, refcount
);
4956 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4958 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4959 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
4961 TRACE("%p, refcount %d.\n", iface
, refcount
);
4965 IDWriteFontFileLoader_Release(file
->loader
);
4967 IDWriteFontFileStream_Release(file
->stream
);
4968 heap_free(file
->reference_key
);
4975 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
4977 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4979 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
4981 *key
= file
->reference_key
;
4982 *key_size
= file
->key_size
;
4987 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
4989 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
4991 TRACE("%p, %p.\n", iface
, loader
);
4993 *loader
= file
->loader
;
4994 IDWriteFontFileLoader_AddRef(*loader
);
4999 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
5000 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
5002 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5003 IDWriteFontFileStream
*stream
;
5006 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
5008 *is_supported
= FALSE
;
5009 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
5011 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
5014 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
5018 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
5020 /* TODO: Further Analysis */
5021 IDWriteFontFileStream_Release(stream
);
5025 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
5027 dwritefontfile_QueryInterface
,
5028 dwritefontfile_AddRef
,
5029 dwritefontfile_Release
,
5030 dwritefontfile_GetReferenceKey
,
5031 dwritefontfile_GetLoader
,
5032 dwritefontfile_Analyze
,
5035 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
5036 IDWriteFontFile
**ret
)
5038 struct dwrite_fontfile
*file
;
5043 file
= heap_alloc(sizeof(*file
));
5044 key
= heap_alloc(key_size
);
5045 if (!file
|| !key
) {
5048 return E_OUTOFMEMORY
;
5051 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
5053 IDWriteFontFileLoader_AddRef(loader
);
5054 file
->loader
= loader
;
5055 file
->stream
= NULL
;
5056 file
->reference_key
= key
;
5057 memcpy(file
->reference_key
, reference_key
, key_size
);
5058 file
->key_size
= key_size
;
5060 *ret
= &file
->IDWriteFontFile_iface
;
5065 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
5067 struct file_stream_desc stream_desc
;
5068 struct dwrite_font_data
*font_data
;
5069 struct dwrite_fontface
*fontface
;
5075 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
5077 return E_OUTOFMEMORY
;
5079 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
5080 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
5081 fontface
->refcount
= 1;
5082 fontface
->type
= desc
->face_type
;
5083 fontface
->vdmx
.exists
= TRUE
;
5084 fontface
->gasp
.exists
= TRUE
;
5085 fontface
->cpal
.exists
= TRUE
;
5086 fontface
->colr
.exists
= TRUE
;
5087 fontface
->kern
.exists
= TRUE
;
5088 fontface
->index
= desc
->index
;
5089 fontface
->simulations
= desc
->simulations
;
5090 fontface
->factory
= desc
->factory
;
5091 IDWriteFactory7_AddRef(fontface
->factory
);
5092 fontface
->file
= desc
->file
;
5093 IDWriteFontFile_AddRef(fontface
->file
);
5094 fontface
->stream
= desc
->stream
;
5095 IDWriteFontFileStream_AddRef(fontface
->stream
);
5097 stream_desc
.stream
= fontface
->stream
;
5098 stream_desc
.face_type
= desc
->face_type
;
5099 stream_desc
.face_index
= desc
->index
;
5100 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
5101 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
5102 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
5103 /* TODO: test what happens if caret is already slanted */
5104 if (fontface
->caret
.slopeRise
== 1) {
5105 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
5106 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
5109 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
5111 /* Font properties are reused from font object when 'normal' face creation path is used:
5112 collection -> family -> matching font -> fontface.
5114 If face is created directly from factory we have to go through properties resolution.
5116 if (desc
->font_data
)
5118 font_data
= addref_font_data(desc
->font_data
);
5122 hr
= init_font_data(desc
, &font_data
);
5125 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5130 fontface
->weight
= font_data
->weight
;
5131 fontface
->style
= font_data
->style
;
5132 fontface
->stretch
= font_data
->stretch
;
5133 fontface
->panose
= font_data
->panose
;
5134 fontface
->fontsig
= font_data
->fontsig
;
5135 fontface
->lf
= font_data
->lf
;
5136 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5137 fontface
->names
= font_data
->names
;
5138 if (fontface
->names
)
5139 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5140 fontface
->family_names
= font_data
->family_names
;
5141 if (fontface
->family_names
)
5142 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5143 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5144 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5146 if (fontface
->info_strings
[i
])
5147 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5149 fontface
->cmap
.stream
= fontface
->stream
;
5150 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5151 release_font_data(font_data
);
5153 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5155 *ret
= &fontface
->IDWriteFontFace5_iface
;
5160 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5167 struct local_cached_stream
5170 IDWriteFontFileStream
*stream
;
5171 struct local_refkey
*key
;
5175 struct dwrite_localfontfilestream
5177 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5180 struct local_cached_stream
*entry
;
5181 const void *file_ptr
;
5185 struct dwrite_localfontfileloader
5187 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5190 struct list streams
;
5191 CRITICAL_SECTION cs
;
5194 static struct dwrite_localfontfileloader local_fontfile_loader
;
5196 struct dwrite_inmemory_stream_data
5204 struct dwrite_inmemory_filestream
5206 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5209 struct dwrite_inmemory_stream_data
*data
;
5212 struct dwrite_inmemory_fileloader
5214 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5217 struct dwrite_inmemory_stream_data
**streams
;
5222 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5224 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5227 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5229 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5232 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5234 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5237 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5239 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5242 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5244 if (InterlockedDecrement(&stream
->refcount
) == 0)
5247 IUnknown_Release(stream
->owner
);
5249 heap_free(stream
->data
);
5254 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5256 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5258 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5260 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5261 IsEqualIID(riid
, &IID_IUnknown
))
5264 if (InterlockedIncrement(&stream
->refcount
) == 1)
5266 InterlockedDecrement(&stream
->refcount
);
5273 WARN("%s not implemented.\n", debugstr_guid(riid
));
5276 return E_NOINTERFACE
;
5279 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5281 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5282 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5284 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5289 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5291 list_remove(&stream
->entry
);
5292 heap_free(stream
->key
);
5296 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5298 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5299 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5301 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5305 UnmapViewOfFile(stream
->file_ptr
);
5307 EnterCriticalSection(&local_fontfile_loader
.cs
);
5308 release_cached_stream(stream
->entry
);
5309 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5317 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5318 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5320 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5322 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5323 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5325 *fragment_context
= NULL
;
5327 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5329 *fragment_start
= NULL
;
5333 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5337 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5339 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5342 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5344 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5346 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5348 *size
= stream
->size
;
5352 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5354 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5357 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5359 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5360 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5361 *last_writetime
= li
.QuadPart
;
5366 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5368 localfontfilestream_QueryInterface
,
5369 localfontfilestream_AddRef
,
5370 localfontfilestream_Release
,
5371 localfontfilestream_ReadFileFragment
,
5372 localfontfilestream_ReleaseFileFragment
,
5373 localfontfilestream_GetFileSize
,
5374 localfontfilestream_GetLastWriteTime
5377 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5378 IDWriteFontFileStream
**ret
)
5380 struct dwrite_localfontfilestream
*object
;
5384 if (!(object
= heap_alloc(sizeof(*object
))))
5385 return E_OUTOFMEMORY
;
5387 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5388 object
->refcount
= 1;
5390 object
->file_ptr
= file_ptr
;
5391 object
->size
= size
;
5392 object
->entry
= entry
;
5394 *ret
= &object
->IDWriteFontFileStream_iface
;
5399 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5401 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5403 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5404 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5405 IsEqualIID(riid
, &IID_IUnknown
))
5408 IDWriteLocalFontFileLoader_AddRef(iface
);
5412 WARN("%s not implemented.\n", debugstr_guid(riid
));
5415 return E_NOINTERFACE
;
5418 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5420 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5421 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5423 TRACE("%p, refcount %d.\n", iface
, refcount
);
5428 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5430 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5431 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5433 TRACE("%p, refcount %d.\n", iface
, refcount
);
5438 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5440 const struct local_refkey
*refkey
= key
;
5441 struct local_cached_stream
*stream
;
5442 IDWriteFontFileStream
*filestream
;
5443 HANDLE file
, mapping
;
5450 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5451 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5452 if (file
== INVALID_HANDLE_VALUE
) {
5453 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5457 GetFileSizeEx(file
, &size
);
5458 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5463 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5464 CloseHandle(mapping
);
5466 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5470 stream
= heap_alloc(sizeof(*stream
));
5472 UnmapViewOfFile(file_ptr
);
5473 return E_OUTOFMEMORY
;
5476 stream
->key
= heap_alloc(key_size
);
5478 UnmapViewOfFile(file_ptr
);
5480 return E_OUTOFMEMORY
;
5483 stream
->key_size
= key_size
;
5484 memcpy(stream
->key
, key
, key_size
);
5486 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5488 UnmapViewOfFile(file_ptr
);
5489 heap_free(stream
->key
);
5494 stream
->stream
= filestream
;
5501 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5502 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5504 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5505 struct local_cached_stream
*stream
;
5508 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5510 EnterCriticalSection(&loader
->cs
);
5514 /* search cache first */
5515 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5517 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5518 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5523 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5525 list_add_head(&loader
->streams
, &stream
->entry
);
5526 *ret
= stream
->stream
;
5529 LeaveCriticalSection(&loader
->cs
);
5534 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5535 UINT32 key_size
, UINT32
*length
)
5537 const struct local_refkey
*refkey
= key
;
5539 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5541 *length
= strlenW(refkey
->name
);
5545 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5546 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5548 const struct local_refkey
*refkey
= key
;
5550 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5552 if (length
< strlenW(refkey
->name
))
5553 return E_INVALIDARG
;
5555 strcpyW(path
, refkey
->name
);
5559 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5560 UINT32 key_size
, FILETIME
*writetime
)
5562 const struct local_refkey
*refkey
= key
;
5564 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5566 *writetime
= refkey
->writetime
;
5570 static const IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5572 localfontfileloader_QueryInterface
,
5573 localfontfileloader_AddRef
,
5574 localfontfileloader_Release
,
5575 localfontfileloader_CreateStreamFromKey
,
5576 localfontfileloader_GetFilePathLengthFromKey
,
5577 localfontfileloader_GetFilePathFromKey
,
5578 localfontfileloader_GetLastWriteTimeFromKey
5581 void init_local_fontfile_loader(void)
5583 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5584 local_fontfile_loader
.refcount
= 1;
5585 list_init(&local_fontfile_loader
.streams
);
5586 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5587 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5590 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5592 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5595 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5597 struct local_refkey
*refkey
;
5600 return E_INVALIDARG
;
5602 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5605 refkey
= heap_alloc(*size
);
5607 return E_OUTOFMEMORY
;
5610 refkey
->writetime
= *writetime
;
5612 WIN32_FILE_ATTRIBUTE_DATA info
;
5614 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5615 refkey
->writetime
= info
.ftLastWriteTime
;
5617 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5619 strcpyW(refkey
->name
, path
);
5626 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5628 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5630 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5631 IsEqualIID(riid
, &IID_IUnknown
))
5634 IDWriteGlyphRunAnalysis_AddRef(iface
);
5638 WARN("%s not implemented.\n", debugstr_guid(riid
));
5641 return E_NOINTERFACE
;
5644 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5646 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5647 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
5649 TRACE("%p, refcount %d.\n", iface
, refcount
);
5654 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5656 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5657 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
5659 TRACE("%p, refcount %d.\n", iface
, refcount
);
5663 if (analysis
->run
.fontFace
)
5664 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5665 heap_free(analysis
->glyphs
);
5666 heap_free(analysis
->origins
);
5667 heap_free(analysis
->bitmap
);
5668 heap_free(analysis
);
5674 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5678 case DWRITE_RENDERING_MODE1_NATURAL
:
5679 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5680 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5687 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5689 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5692 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5694 struct dwrite_glyphbitmap glyph_bitmap
;
5695 IDWriteFontFace4
*fontface
;
5699 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5700 *bounds
= analysis
->bounds
;
5704 if (analysis
->run
.isSideways
)
5705 FIXME("sideways runs are not supported.\n");
5707 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5709 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5711 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5712 glyph_bitmap
.fontface
= fontface
;
5713 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5714 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5715 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5716 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5717 glyph_bitmap
.m
= &analysis
->m
;
5719 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5720 RECT
*bbox
= &glyph_bitmap
.bbox
;
5723 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5724 freetype_get_glyph_bbox(&glyph_bitmap
);
5726 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5727 (bbox
->bottom
- bbox
->top
);
5728 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5729 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5731 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5732 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5735 IDWriteFontFace4_Release(fontface
);
5737 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5738 *bounds
= analysis
->bounds
;
5741 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
5742 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5744 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5746 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
5748 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5749 SetRectEmpty(bounds
);
5750 return E_INVALIDARG
;
5753 if (type
!= analysis
->texture_type
)
5755 SetRectEmpty(bounds
);
5759 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
5763 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5765 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5766 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5767 (runbounds
->left
- bounds
->left
) * 3;
5769 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5770 runbounds
->left
- bounds
->left
;
5773 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5775 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5776 struct dwrite_glyphbitmap glyph_bitmap
;
5777 IDWriteFontFace4
*fontface
;
5778 D2D_POINT_2F origin
;
5783 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5785 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5789 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5790 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5792 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5793 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5794 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5795 IDWriteFontFace4_Release(fontface
);
5796 return E_OUTOFMEMORY
;
5799 origin
.x
= origin
.y
= 0.0f
;
5801 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5802 glyph_bitmap
.fontface
= fontface
;
5803 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5804 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5805 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5806 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5807 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5808 glyph_bitmap
.m
= &analysis
->m
;
5809 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5810 IDWriteFontFace4_Release(fontface
);
5811 return E_OUTOFMEMORY
;
5814 bbox
= &glyph_bitmap
.bbox
;
5816 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5817 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5818 int x
, y
, width
, height
;
5821 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5822 freetype_get_glyph_bbox(&glyph_bitmap
);
5824 if (IsRectEmpty(bbox
))
5827 width
= bbox
->right
- bbox
->left
;
5828 height
= bbox
->bottom
- bbox
->top
;
5830 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5831 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5832 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5834 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5836 /* blit to analysis bitmap */
5837 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5840 /* convert 1bpp to 8bpp/24bpp */
5841 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5842 for (y
= 0; y
< height
; y
++) {
5843 for (x
= 0; x
< width
; x
++)
5844 if (src
[x
/ 8] & masks
[x
% 8])
5845 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5846 src
+= glyph_bitmap
.pitch
;
5847 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5851 for (y
= 0; y
< height
; y
++) {
5852 for (x
= 0; x
< width
; x
++)
5853 if (src
[x
/ 8] & masks
[x
% 8])
5854 dst
[x
] = DWRITE_ALPHA_MAX
;
5855 src
+= glyph_bitmap
.pitch
;
5856 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5861 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5862 for (y
= 0; y
< height
; y
++) {
5863 for (x
= 0; x
< width
; x
++)
5864 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5865 src
+= glyph_bitmap
.pitch
;
5866 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5870 for (y
= 0; y
< height
; y
++) {
5871 for (x
= 0; x
< width
; x
++)
5873 src
+= glyph_bitmap
.pitch
;
5874 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5879 heap_free(glyph_bitmap
.buf
);
5881 IDWriteFontFace4_Release(fontface
);
5883 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5885 /* we don't need this anymore */
5886 heap_free(analysis
->glyphs
);
5887 heap_free(analysis
->origins
);
5888 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5890 analysis
->glyphs
= NULL
;
5891 analysis
->origins
= NULL
;
5892 analysis
->run
.glyphIndices
= NULL
;
5893 analysis
->run
.fontFace
= NULL
;
5898 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5899 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5901 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5905 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5907 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5908 return E_INVALIDARG
;
5910 /* make sure buffer is large enough for requested texture type */
5911 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5912 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5915 if (size
< required
)
5916 return E_NOT_SUFFICIENT_BUFFER
;
5918 /* validate requested texture type */
5919 if (analysis
->texture_type
!= type
)
5920 return DWRITE_E_UNSUPPORTEDOPERATION
;
5922 memset(bitmap
, 0, size
);
5923 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
5924 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
5926 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5927 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
5928 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5929 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5933 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
5937 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
5941 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
5942 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5944 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5945 memcpy(dst
, src
, draw_width
);
5954 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5955 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5957 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5959 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
5962 return E_INVALIDARG
;
5964 switch (analysis
->rendering_mode
)
5966 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5967 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5970 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5971 *gamma
= (FLOAT
)value
/ 1000.0f
;
5973 *cleartypelevel
= 1.0f
;
5976 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5977 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5979 case DWRITE_RENDERING_MODE1_ALIASED
:
5980 case DWRITE_RENDERING_MODE1_NATURAL
:
5981 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5982 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5983 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5984 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5993 static const IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
5995 glyphrunanalysis_QueryInterface
,
5996 glyphrunanalysis_AddRef
,
5997 glyphrunanalysis_Release
,
5998 glyphrunanalysis_GetAlphaTextureBounds
,
5999 glyphrunanalysis_CreateAlphaTexture
,
6000 glyphrunanalysis_GetAlphaBlendParams
6003 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
6006 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
6007 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
6011 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
6012 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
6014 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
6018 FIXME("Sideways mode is not supported.\n");
6020 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
6022 switch (measuring_mode
)
6024 case DWRITE_MEASURING_MODE_NATURAL
:
6025 return (float)advance
* emsize
/ (float)upem
;
6026 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
6027 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
6028 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
6030 WARN("Unknown measuring mode %u.\n", measuring_mode
);
6035 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
6037 struct dwrite_glyphrunanalysis
*analysis
;
6042 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
6043 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
6044 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
6045 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
6046 return E_INVALIDARG
;
6048 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6049 return E_INVALIDARG
;
6051 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
6052 return E_INVALIDARG
;
6054 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
6055 return E_INVALIDARG
;
6057 analysis
= heap_alloc_zero(sizeof(*analysis
));
6059 return E_OUTOFMEMORY
;
6061 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
6062 analysis
->refcount
= 1;
6063 analysis
->rendering_mode
= desc
->rendering_mode
;
6065 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
6066 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6067 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
6069 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
6071 analysis
->run
= *desc
->run
;
6072 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
6073 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
6074 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
6076 if (!analysis
->glyphs
|| !analysis
->origins
) {
6077 heap_free(analysis
->glyphs
);
6078 heap_free(analysis
->origins
);
6080 analysis
->glyphs
= NULL
;
6081 analysis
->origins
= NULL
;
6083 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
6084 return E_OUTOFMEMORY
;
6087 /* check if transform is usable */
6088 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
6089 analysis
->m
= *desc
->transform
;
6090 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
6093 analysis
->run
.glyphIndices
= analysis
->glyphs
;
6094 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
6096 compute_glyph_origins(desc
->run
, desc
->measuring_mode
, desc
->origin
, desc
->transform
, analysis
->origins
);
6097 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6099 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
6100 transform_point(&analysis
->origins
[i
], &analysis
->m
);
6103 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6107 /* IDWriteColorGlyphRunEnumerator1 */
6108 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6110 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6112 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6113 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6114 IsEqualIID(riid
, &IID_IUnknown
))
6117 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6121 WARN("%s not implemented.\n", debugstr_guid(riid
));
6124 return E_NOINTERFACE
;
6127 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6129 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6130 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6132 TRACE("%p, refcount %u.\n", iface
, refcount
);
6137 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6139 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6140 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6142 TRACE("%p, refcount %u.\n", iface
, refcount
);
6146 heap_free(glyphenum
->advances
);
6147 heap_free(glyphenum
->color_advances
);
6148 heap_free(glyphenum
->offsets
);
6149 heap_free(glyphenum
->color_offsets
);
6150 heap_free(glyphenum
->glyphindices
);
6151 heap_free(glyphenum
->glyphs
);
6152 if (glyphenum
->colr
.context
)
6153 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6154 IDWriteFontFace5_Release(glyphenum
->fontface
);
6155 heap_free(glyphenum
);
6161 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6163 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6164 FLOAT origin
= 0.0f
;
6170 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6174 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6176 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6177 FLOAT advance_adj
= 0.0f
;
6178 BOOL got_palette_index
;
6181 /* start with regular glyphs */
6182 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6183 UINT32 first_glyph
= 0;
6185 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6186 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6187 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6188 first_glyph
= min(first_glyph
, g
);
6191 glyphenum
->glyphindices
[g
] = 1;
6192 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6193 if (glyphenum
->color_offsets
)
6194 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6197 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6198 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6199 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6200 colorrun
->paletteIndex
= 0xffff;
6201 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6202 glyphenum
->has_regular_glyphs
= FALSE
;
6206 colorrun
->glyphRun
.glyphCount
= 0;
6207 got_palette_index
= FALSE
;
6211 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6213 glyphenum
->glyphindices
[g
] = 1;
6215 /* all glyph layers were returned */
6216 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6217 advance_adj
+= glyphenum
->advances
[g
];
6221 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6222 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6223 if (!got_palette_index
) {
6224 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6225 /* use foreground color or request one from the font */
6226 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6227 if (colorrun
->paletteIndex
!= 0xffff)
6229 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6230 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6232 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6233 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6235 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6236 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6237 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6238 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6239 got_palette_index
= TRUE
;
6242 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6243 /* offsets are relative to glyph origin, nothing to fix up */
6244 if (glyphenum
->color_offsets
)
6245 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6246 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6248 glyphenum
->color_advances
[index
-1] += advance_adj
;
6249 colorrun
->glyphRun
.glyphCount
++;
6253 advance_adj
+= glyphenum
->advances
[g
];
6256 /* reset last advance */
6257 if (colorrun
->glyphRun
.glyphCount
)
6258 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6260 return colorrun
->glyphRun
.glyphCount
> 0;
6263 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6265 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6267 TRACE("%p, %p.\n", iface
, has_run
);
6271 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6272 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6274 if (colorglyphenum_build_color_run(glyphenum
))
6277 glyphenum
->current_layer
++;
6280 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6285 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6286 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6288 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6291 return E_NOT_VALID_STATE
;
6294 *run
= &glyphenum
->colorrun
;
6298 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6299 DWRITE_COLOR_GLYPH_RUN
const **run
)
6301 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6303 TRACE("%p, %p.\n", iface
, run
);
6305 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6308 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6309 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6311 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6313 TRACE("%p, %p.\n", iface
, run
);
6315 return colorglyphenum_get_current_run(glyphenum
, run
);
6318 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6320 colorglyphenum_QueryInterface
,
6321 colorglyphenum_AddRef
,
6322 colorglyphenum_Release
,
6323 colorglyphenum_MoveNext
,
6324 colorglyphenum_GetCurrentRun
,
6325 colorglyphenum1_GetCurrentRun
,
6328 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6329 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6330 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6332 struct dwrite_colorglyphenum
*colorglyphenum
;
6333 BOOL colorfont
, has_colored_glyph
;
6334 struct dwrite_fontface
*fontface
;
6339 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6341 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6342 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6344 return DWRITE_E_NOCOLOR
;
6346 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
6347 if (!colorglyphenum
)
6348 return E_OUTOFMEMORY
;
6350 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6351 colorglyphenum
->refcount
= 1;
6352 colorglyphenum
->origin_x
= originX
;
6353 colorglyphenum
->origin_y
= originY
;
6354 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6355 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6356 colorglyphenum
->glyphs
= NULL
;
6357 colorglyphenum
->run
= *run
;
6358 colorglyphenum
->run
.glyphIndices
= NULL
;
6359 colorglyphenum
->run
.glyphAdvances
= NULL
;
6360 colorglyphenum
->run
.glyphOffsets
= NULL
;
6361 colorglyphenum
->palette
= palette
;
6362 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6363 colorglyphenum
->colr
.exists
= TRUE
;
6364 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6365 colorglyphenum
->current_layer
= 0;
6366 colorglyphenum
->max_layer_num
= 0;
6368 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6370 has_colored_glyph
= FALSE
;
6371 colorglyphenum
->has_regular_glyphs
= FALSE
;
6372 for (i
= 0; i
< run
->glyphCount
; i
++) {
6373 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6374 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6375 has_colored_glyph
= TRUE
;
6377 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6378 colorglyphenum
->has_regular_glyphs
= TRUE
;
6381 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6382 is supposed to proceed normally, like if font had no color info at all. */
6383 if (!has_colored_glyph
) {
6384 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6385 return DWRITE_E_NOCOLOR
;
6388 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6389 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6390 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6391 if (run
->glyphOffsets
) {
6392 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6393 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6394 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6397 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6398 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6399 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6400 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6401 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6402 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6403 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6404 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6406 if (run
->glyphAdvances
)
6407 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6410 for (i
= 0; i
< run
->glyphCount
; ++i
)
6411 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6412 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6415 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6420 /* IDWriteFontFaceReference */
6421 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6423 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6425 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6426 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6427 IsEqualIID(riid
, &IID_IUnknown
))
6430 IDWriteFontFaceReference1_AddRef(iface
);
6434 WARN("%s not implemented.\n", debugstr_guid(riid
));
6438 return E_NOINTERFACE
;
6441 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6443 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6444 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6446 TRACE("%p, refcount %u.\n", iface
, refcount
);
6451 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6453 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6454 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6456 TRACE("%p, refcount %u.\n", iface
, refcount
);
6460 IDWriteFontFile_Release(reference
->file
);
6461 IDWriteFactory7_Release(reference
->factory
);
6462 heap_free(reference
->axis_values
);
6463 heap_free(reference
);
6469 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6471 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6473 TRACE("%p, %p.\n", iface
, fontface
);
6475 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6478 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6479 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6481 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6482 DWRITE_FONT_FILE_TYPE file_type
;
6483 DWRITE_FONT_FACE_TYPE face_type
;
6484 IDWriteFontFace
*fontface
;
6489 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6491 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6495 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6496 simulations
, &fontface
);
6499 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6500 IDWriteFontFace_Release(fontface
);
6506 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6508 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6509 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6512 TRACE("%p, %p.\n", iface
, ref
);
6514 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6515 reference
->simulations
== other
->simulations
;
6516 if (reference
->axis_values_count
)
6518 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6519 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6525 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6527 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6529 TRACE("%p.\n", iface
);
6531 return reference
->index
;
6534 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6536 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6538 TRACE("%p.\n", iface
);
6540 return reference
->simulations
;
6543 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6545 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6546 IDWriteFontFileLoader
*loader
;
6551 TRACE("%p, %p.\n", iface
, file
);
6553 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6557 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6561 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6562 IDWriteFontFileLoader_Release(loader
);
6567 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6569 FIXME("%p.\n", iface
);
6574 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6576 FIXME("%p.\n", iface
);
6581 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6583 FIXME("%p, %p.\n", iface
, writetime
);
6588 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6590 FIXME("%p.\n", iface
);
6592 return DWRITE_LOCALITY_LOCAL
;
6595 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6597 FIXME("%p.\n", iface
);
6602 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6603 WCHAR
const *chars
, UINT32 count
)
6605 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6610 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6611 UINT16
const *glyphs
, UINT32 count
)
6613 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6618 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6619 UINT64 offset
, UINT64 size
)
6621 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6626 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6628 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6629 IDWriteFontFace3
*fontface3
;
6632 TRACE("%p, %p.\n", iface
, fontface
);
6634 /* FIXME: created instance should likely respect given axis. */
6635 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6638 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6639 IDWriteFontFace3_Release(fontface3
);
6645 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6647 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6649 TRACE("%p.\n", iface
);
6651 return reference
->axis_values_count
;
6654 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6655 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6657 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6659 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6661 if (value_count
< reference
->axis_values_count
)
6662 return E_NOT_SUFFICIENT_BUFFER
;
6664 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6669 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6671 fontfacereference_QueryInterface
,
6672 fontfacereference_AddRef
,
6673 fontfacereference_Release
,
6674 fontfacereference_CreateFontFace
,
6675 fontfacereference_CreateFontFaceWithSimulations
,
6676 fontfacereference_Equals
,
6677 fontfacereference_GetFontFaceIndex
,
6678 fontfacereference_GetSimulations
,
6679 fontfacereference_GetFontFile
,
6680 fontfacereference_GetLocalFileSize
,
6681 fontfacereference_GetFileSize
,
6682 fontfacereference_GetFileTime
,
6683 fontfacereference_GetLocality
,
6684 fontfacereference_EnqueueFontDownloadRequest
,
6685 fontfacereference_EnqueueCharacterDownloadRequest
,
6686 fontfacereference_EnqueueGlyphDownloadRequest
,
6687 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6688 fontfacereference1_CreateFontFace
,
6689 fontfacereference1_GetFontAxisValueCount
,
6690 fontfacereference1_GetFontAxisValues
,
6693 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6694 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6695 IDWriteFontFaceReference1
**ret
)
6697 struct dwrite_fontfacereference
*object
;
6701 if (!is_simulation_valid(simulations
))
6702 return E_INVALIDARG
;
6704 object
= heap_alloc_zero(sizeof(*object
));
6706 return E_OUTOFMEMORY
;
6708 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6709 object
->refcount
= 1;
6711 object
->factory
= factory
;
6712 IDWriteFactory7_AddRef(object
->factory
);
6713 object
->file
= file
;
6714 IDWriteFontFile_AddRef(object
->file
);
6715 object
->index
= index
;
6716 object
->simulations
= simulations
;
6717 if (axis_values_count
)
6719 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6721 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6722 return E_OUTOFMEMORY
;
6724 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6725 object
->axis_values_count
= axis_values_count
;
6728 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6733 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6735 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6737 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6739 IDWriteFontFileStream_AddRef(iface
);
6745 WARN("%s not implemented.\n", debugstr_guid(riid
));
6746 return E_NOINTERFACE
;
6749 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6751 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6752 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
6754 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6759 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6761 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6762 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
6764 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6768 release_inmemory_stream(stream
->data
);
6775 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6776 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6778 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6780 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
6781 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6783 *fragment_context
= NULL
;
6785 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6786 *fragment_start
= NULL
;
6790 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6794 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6796 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
6799 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6801 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6803 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
6805 *size
= stream
->data
->size
;
6810 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6812 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
6814 *last_writetime
= 0;
6819 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6820 inmemoryfilestream_QueryInterface
,
6821 inmemoryfilestream_AddRef
,
6822 inmemoryfilestream_Release
,
6823 inmemoryfilestream_ReadFileFragment
,
6824 inmemoryfilestream_ReleaseFileFragment
,
6825 inmemoryfilestream_GetFileSize
,
6826 inmemoryfilestream_GetLastWriteTime
,
6829 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6830 REFIID riid
, void **obj
)
6832 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6834 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6835 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6836 IsEqualIID(riid
, &IID_IUnknown
))
6839 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6843 WARN("%s not implemented.\n", debugstr_guid(riid
));
6847 return E_NOINTERFACE
;
6850 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6852 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6853 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
6855 TRACE("%p, refcount %u.\n", iface
, refcount
);
6860 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6862 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6863 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
6866 TRACE("%p, refcount %u.\n", iface
, refcount
);
6870 for (i
= 0; i
< loader
->count
; ++i
)
6871 release_inmemory_stream(loader
->streams
[i
]);
6872 heap_free(loader
->streams
);
6879 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6880 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6882 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6883 struct dwrite_inmemory_filestream
*stream
;
6886 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
6890 if (key_size
!= sizeof(DWORD
))
6891 return E_INVALIDARG
;
6893 index
= *(DWORD
*)key
;
6895 if (index
>= loader
->count
)
6896 return E_INVALIDARG
;
6898 if (!(stream
= heap_alloc(sizeof(*stream
))))
6899 return E_OUTOFMEMORY
;
6901 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6902 stream
->refcount
= 1;
6903 stream
->data
= loader
->streams
[index
];
6904 InterlockedIncrement(&stream
->data
->refcount
);
6906 *ret
= &stream
->IDWriteFontFileStream_iface
;
6911 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6912 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6914 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6915 struct dwrite_inmemory_stream_data
*stream
;
6918 TRACE("%p, %p, %p, %u, %p, %p.\n", iface
, factory
, data
, data_size
, owner
, fontfile
);
6922 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6923 return E_OUTOFMEMORY
;
6925 if (!(stream
= heap_alloc(sizeof(*stream
))))
6926 return E_OUTOFMEMORY
;
6928 stream
->refcount
= 1;
6929 stream
->size
= data_size
;
6930 stream
->owner
= owner
;
6931 if (stream
->owner
) {
6932 IUnknown_AddRef(stream
->owner
);
6933 stream
->data
= (void *)data
;
6936 if (!(stream
->data
= heap_alloc(data_size
))) {
6938 return E_OUTOFMEMORY
;
6940 memcpy(stream
->data
, data
, data_size
);
6943 key
= loader
->count
;
6944 loader
->streams
[loader
->count
++] = stream
;
6946 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6947 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6950 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6952 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6954 TRACE("%p.\n", iface
);
6956 return loader
->count
;
6959 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6961 inmemoryfontfileloader_QueryInterface
,
6962 inmemoryfontfileloader_AddRef
,
6963 inmemoryfontfileloader_Release
,
6964 inmemoryfontfileloader_CreateStreamFromKey
,
6965 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6966 inmemoryfontfileloader_GetFileCount
,
6969 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
6971 struct dwrite_inmemory_fileloader
*loader
;
6975 loader
= heap_alloc_zero(sizeof(*loader
));
6977 return E_OUTOFMEMORY
;
6979 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6980 loader
->refcount
= 1;
6982 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
6987 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6989 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6991 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6992 IsEqualIID(riid
, &IID_IUnknown
))
6995 IDWriteFontResource_AddRef(iface
);
6999 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7001 return E_NOINTERFACE
;
7004 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
7006 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7007 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
7009 TRACE("%p, refcount %u.\n", iface
, refcount
);
7014 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
7016 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7017 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
7019 TRACE("%p, refcount %u.\n", iface
, refcount
);
7023 IDWriteFactory7_Release(resource
->factory
);
7024 IDWriteFontFile_Release(resource
->file
);
7025 heap_free(resource
);
7031 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
7033 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7035 TRACE("%p, %p.\n", iface
, fontfile
);
7037 *fontfile
= resource
->file
;
7038 IDWriteFontFile_AddRef(*fontfile
);
7043 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
7045 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7047 TRACE("%p.\n", iface
);
7049 return resource
->face_index
;
7052 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
7054 FIXME("%p.\n", iface
);
7059 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
7060 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
7062 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
7067 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
7068 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
7070 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
7075 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7078 FIXME("%p, %u.\n", iface
, axis
);
7080 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
7083 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7084 IDWriteLocalizedStrings
**names
)
7086 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7091 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7093 FIXME("%p, %u.\n", iface
, axis
);
7098 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7099 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7101 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7106 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7108 FIXME("%p.\n", iface
);
7113 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7114 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7115 IDWriteFontFace5
**fontface
)
7117 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7118 IDWriteFontFaceReference1
*reference
;
7121 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7123 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7124 simulations
, axis_values
, num_values
, &reference
);
7127 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7128 IDWriteFontFaceReference1_Release(reference
);
7134 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7135 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7136 IDWriteFontFaceReference1
**reference
)
7138 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7140 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7142 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7143 simulations
, axis_values
, num_values
, reference
);
7146 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7148 dwritefontresource_QueryInterface
,
7149 dwritefontresource_AddRef
,
7150 dwritefontresource_Release
,
7151 dwritefontresource_GetFontFile
,
7152 dwritefontresource_GetFontFaceIndex
,
7153 dwritefontresource_GetFontAxisCount
,
7154 dwritefontresource_GetDefaultFontAxisValues
,
7155 dwritefontresource_GetFontAxisRanges
,
7156 dwritefontresource_GetFontAxisAttributes
,
7157 dwritefontresource_GetAxisNames
,
7158 dwritefontresource_GetAxisValueNameCount
,
7159 dwritefontresource_GetAxisValueNames
,
7160 dwritefontresource_HasVariations
,
7161 dwritefontresource_CreateFontFace
,
7162 dwritefontresource_CreateFontFaceReference
,
7165 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7166 IDWriteFontResource
**ret
)
7168 struct dwrite_fontresource
*resource
;
7172 resource
= heap_alloc_zero(sizeof(*resource
));
7174 return E_OUTOFMEMORY
;
7176 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7177 resource
->refcount
= 1;
7178 resource
->face_index
= face_index
;
7179 resource
->file
= file
;
7180 IDWriteFontFile_AddRef(resource
->file
);
7181 resource
->factory
= factory
;
7182 IDWriteFactory7_AddRef(resource
->factory
);
7184 *ret
= &resource
->IDWriteFontResource_iface
;
7189 static HRESULT WINAPI
dwritefontset_QueryInterface(IDWriteFontSet3
*iface
, REFIID riid
, void **obj
)
7191 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7193 if (IsEqualIID(riid
, &IID_IDWriteFontSet3
) ||
7194 IsEqualIID(riid
, &IID_IDWriteFontSet2
) ||
7195 IsEqualIID(riid
, &IID_IDWriteFontSet1
) ||
7196 IsEqualIID(riid
, &IID_IDWriteFontSet
))
7199 IDWriteFontSet3_AddRef(iface
);
7203 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7205 return E_NOINTERFACE
;
7208 static ULONG WINAPI
dwritefontset_AddRef(IDWriteFontSet3
*iface
)
7210 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7211 ULONG refcount
= InterlockedIncrement(&set
->refcount
);
7213 TRACE("%p, refcount %u.\n", iface
, refcount
);
7218 #define MISSING_SET_PROP ((void *)0x1)
7220 static void release_fontset_entry(struct dwrite_fontset_entry
*entry
)
7224 if (InterlockedDecrement(&entry
->refcount
) > 0)
7226 IDWriteFontFile_Release(entry
->file
);
7227 for (i
= 0; i
< ARRAY_SIZE(entry
->props
); ++i
)
7229 if (entry
->props
[i
] && entry
->props
[i
] != MISSING_SET_PROP
)
7230 IDWriteLocalizedStrings_Release(entry
->props
[i
]);
7235 static struct dwrite_fontset_entry
* addref_fontset_entry(struct dwrite_fontset_entry
*entry
)
7237 InterlockedIncrement(&entry
->refcount
);
7241 static IDWriteLocalizedStrings
* fontset_entry_get_property(struct dwrite_fontset_entry
*entry
,
7242 DWRITE_FONT_PROPERTY_ID property
)
7244 struct file_stream_desc stream_desc
= { 0 };
7245 IDWriteLocalizedStrings
*value
;
7247 assert(property
> DWRITE_FONT_PROPERTY_ID_NONE
&& property
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
);
7249 if (entry
->props
[property
] == MISSING_SET_PROP
)
7252 if ((value
= entry
->props
[property
]))
7254 IDWriteLocalizedStrings_AddRef(value
);
7258 get_filestream_from_file(entry
->file
, &stream_desc
.stream
);
7259 stream_desc
.face_type
= entry
->face_type
;
7260 stream_desc
.face_index
= entry
->face_index
;
7262 if (property
== DWRITE_FONT_PROPERTY_ID_FULL_NAME
)
7263 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_FULL_NAME
, &value
);
7264 else if (property
== DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
)
7265 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME
, &value
);
7266 else if (property
== DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
)
7267 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG
, &value
);
7268 else if (property
== DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
)
7269 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
, &value
);
7271 WARN("Unsupported property %u.\n", property
);
7273 if (stream_desc
.stream
)
7274 IDWriteFontFileStream_Release(stream_desc
.stream
);
7278 entry
->props
[property
] = value
;
7279 IDWriteLocalizedStrings_AddRef(value
);
7282 entry
->props
[property
] = MISSING_SET_PROP
;
7287 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7288 struct dwrite_fontset_entry
**entries
, unsigned int count
);
7290 static ULONG WINAPI
dwritefontset_Release(IDWriteFontSet3
*iface
)
7292 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7293 ULONG refcount
= InterlockedDecrement(&set
->refcount
);
7296 TRACE("%p, refcount %u.\n", iface
, refcount
);
7300 IDWriteFactory7_Release(set
->factory
);
7301 for (i
= 0; i
< set
->count
; ++i
)
7302 release_fontset_entry(set
->entries
[i
]);
7303 heap_free(set
->entries
);
7310 static UINT32 WINAPI
dwritefontset_GetFontCount(IDWriteFontSet3
*iface
)
7312 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7314 TRACE("%p.\n", iface
);
7319 static HRESULT WINAPI
dwritefontset_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7320 IDWriteFontFaceReference
**reference
)
7322 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7324 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
7328 if (index
>= set
->count
)
7329 return E_INVALIDARG
;
7331 return IDWriteFactory7_CreateFontFaceReference_(set
->factory
, set
->entries
[index
]->file
,
7332 set
->entries
[index
]->face_index
, set
->entries
[index
]->simulations
, reference
);
7335 static HRESULT WINAPI
dwritefontset_FindFontFaceReference(IDWriteFontSet3
*iface
,
7336 IDWriteFontFaceReference
*reference
, UINT32
*index
, BOOL
*exists
)
7338 FIXME("%p, %p, %p, %p.\n", iface
, reference
, index
, exists
);
7343 static HRESULT WINAPI
dwritefontset_FindFontFace(IDWriteFontSet3
*iface
, IDWriteFontFace
*fontface
,
7344 UINT32
*index
, BOOL
*exists
)
7346 FIXME("%p, %p, %p, %p.\n", iface
, fontface
, index
, exists
);
7351 static HRESULT WINAPI
dwritefontset_GetPropertyValues__(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7352 IDWriteStringList
**values
)
7354 FIXME("%p, %d, %p.\n", iface
, id
, values
);
7359 static HRESULT WINAPI
dwritefontset_GetPropertyValues_(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7360 WCHAR
const *preferred_locales
, IDWriteStringList
**values
)
7362 FIXME("%p, %d, %s, %p.\n", iface
, id
, debugstr_w(preferred_locales
), values
);
7367 static HRESULT WINAPI
dwritefontset_GetPropertyValues(IDWriteFontSet3
*iface
, UINT32 index
, DWRITE_FONT_PROPERTY_ID id
,
7368 BOOL
*exists
, IDWriteLocalizedStrings
**values
)
7370 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7372 TRACE("%p, %u, %d, %p, %p.\n", iface
, index
, id
, exists
, values
);
7374 if (!(id
> DWRITE_FONT_PROPERTY_ID_NONE
&& id
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
) ||
7375 index
>= set
->count
)
7379 return E_INVALIDARG
;
7382 *values
= fontset_entry_get_property(set
->entries
[index
], id
);
7383 *exists
= !!*values
;
7388 static HRESULT WINAPI
dwritefontset_GetPropertyOccurrenceCount(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7391 FIXME("%p, %p, %p.\n", iface
, property
, count
);
7396 static BOOL
fontset_entry_is_matching(struct dwrite_fontset_entry
*entry
, DWRITE_FONT_PROPERTY
const *props
,
7399 IDWriteLocalizedStrings
*value
;
7403 for (i
= 0; i
< count
; ++i
)
7405 switch (props
[i
].propertyId
)
7407 case DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
:
7408 case DWRITE_FONT_PROPERTY_ID_FULL_NAME
:
7409 case DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
:
7410 case DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
:
7411 if (!(value
= fontset_entry_get_property(entry
, props
[i
].propertyId
)))
7414 ret
= localizedstrings_contains(value
, props
[i
].propertyValue
);
7415 IDWriteLocalizedStrings_Release(value
);
7416 if (!ret
) return FALSE
;
7418 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
:
7419 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME
:
7420 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME
:
7421 case DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME
:
7422 case DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG
:
7423 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
7424 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
7425 case DWRITE_FONT_PROPERTY_ID_STYLE
:
7426 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
:
7427 FIXME("Unsupported property %d.\n", props
[i
].propertyId
);
7437 static HRESULT WINAPI
dwritefontset_GetMatchingFonts_(IDWriteFontSet3
*iface
, WCHAR
const *family
, DWRITE_FONT_WEIGHT weight
,
7438 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontSet
**fontset
)
7440 FIXME("%p, %s, %d, %d, %d, %p.\n", iface
, debugstr_w(family
), weight
, stretch
, style
, fontset
);
7445 static HRESULT WINAPI
dwritefontset_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
, UINT32 count
,
7446 IDWriteFontSet
**filtered_set
)
7448 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7449 struct dwrite_fontset_entry
**entries
;
7450 unsigned int i
, matched_count
= 0;
7451 struct dwrite_fontset
*object
;
7453 TRACE("%p, %p, %u, %p.\n", iface
, props
, count
, filtered_set
);
7455 if (!props
&& count
)
7456 return E_INVALIDARG
;
7458 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7459 return E_OUTOFMEMORY
;
7461 if (!(entries
= heap_calloc(set
->count
, sizeof(*entries
))))
7464 return E_OUTOFMEMORY
;
7467 for (i
= 0; i
< set
->count
; ++i
)
7469 if (fontset_entry_is_matching(set
->entries
[i
], props
, count
))
7471 entries
[matched_count
++] = addref_fontset_entry(set
->entries
[i
]);
7481 init_fontset(object
, set
->factory
, entries
, matched_count
);
7483 *filtered_set
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7488 static HRESULT WINAPI
dwritefontset1_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7489 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontSet1
**fontset
)
7491 FIXME("%p, %p, %p, %u, %p.\n", iface
, property
, axis_values
, num_values
, fontset
);
7496 static HRESULT WINAPI
dwritefontset1_GetFirstFontResources(IDWriteFontSet3
*iface
, IDWriteFontSet1
**fontset
)
7498 FIXME("%p, %p.\n", iface
, fontset
);
7503 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts__(IDWriteFontSet3
*iface
, UINT32
const *indices
,
7504 UINT32 num_indices
, IDWriteFontSet1
**fontset
)
7506 FIXME("%p, %p, %u, %p.\n", iface
, indices
, num_indices
, fontset
);
7511 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *axis_ranges
,
7512 UINT32 num_ranges
, BOOL select_any_range
, IDWriteFontSet1
**fontset
)
7514 FIXME("%p, %p, %u, %d, %p.\n", iface
, axis_ranges
, num_ranges
, select_any_range
, fontset
);
7519 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7520 UINT32 num_properties
, BOOL select_any_property
, IDWriteFontSet1
**fontset
)
7522 FIXME("%p, %p, %u, %d, %p.\n", iface
, props
, num_properties
, select_any_property
, fontset
);
7527 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *ranges
,
7528 UINT32 num_ranges
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7530 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, ranges
, num_ranges
, select_any_range
, indices
, num_indices
, actual_num_indices
);
7535 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7536 UINT32 num_properties
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7538 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, props
, num_properties
, select_any_range
, indices
,
7539 num_indices
, actual_num_indices
);
7544 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges_(IDWriteFontSet3
*iface
, UINT32 font_index
,
7545 DWRITE_FONT_AXIS_RANGE
*axis_ranges
, UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7547 FIXME("%p, %u, %p, %u, %p.\n", iface
, font_index
, axis_ranges
, num_ranges
, actual_num_ranges
);
7552 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
*axis_ranges
,
7553 UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7555 FIXME("%p, %p, %u, %p.\n", iface
, axis_ranges
, num_ranges
, actual_num_ranges
);
7560 static HRESULT WINAPI
dwritefontset1_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7561 IDWriteFontFaceReference1
**reference
)
7563 FIXME("%p, %u, %p.\n", iface
, index
, reference
);
7568 static HRESULT WINAPI
dwritefontset1_CreateFontResource(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontResource
**resource
)
7570 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7572 TRACE("%p, %u, %p.\n", iface
, index
, resource
);
7576 if (index
>= set
->count
)
7577 return E_INVALIDARG
;
7579 return IDWriteFactory7_CreateFontResource(set
->factory
, set
->entries
[index
]->file
,
7580 set
->entries
[index
]->face_index
, resource
);
7583 static HRESULT WINAPI
dwritefontset1_CreateFontFace(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontFace5
**fontface
)
7585 FIXME("%p, %u, %p.\n", iface
, index
, fontface
);
7590 static DWRITE_LOCALITY WINAPI
dwritefontset1_GetFontLocality(IDWriteFontSet3
*iface
, UINT32 index
)
7592 FIXME("%p, %u.\n", iface
, index
);
7594 return DWRITE_LOCALITY_LOCAL
;
7597 static HANDLE WINAPI
dwritefontset2_GetExpirationEvent(IDWriteFontSet3
*iface
)
7599 FIXME("%p.\n", iface
);
7604 static DWRITE_FONT_SOURCE_TYPE WINAPI
dwritefontset3_GetFontSourceType(IDWriteFontSet3
*iface
, UINT32 index
)
7606 FIXME("%p, %u.\n", iface
, index
);
7608 return DWRITE_FONT_SOURCE_TYPE_UNKNOWN
;
7611 static UINT32 WINAPI
dwritefontset3_GetFontSourceNameLength(IDWriteFontSet3
*iface
, UINT32 index
)
7613 FIXME("%p, %u.\n", iface
, index
);
7618 static HRESULT WINAPI
dwritefontset3_GetFontSourceName(IDWriteFontSet3
*iface
, UINT32 index
, WCHAR
*buffer
, UINT32 buffer_size
)
7620 FIXME("%p, %u, %p, %u.\n", iface
, index
, buffer
, buffer_size
);
7625 static const IDWriteFontSet3Vtbl fontsetvtbl
=
7627 dwritefontset_QueryInterface
,
7628 dwritefontset_AddRef
,
7629 dwritefontset_Release
,
7630 dwritefontset_GetFontCount
,
7631 dwritefontset_GetFontFaceReference
,
7632 dwritefontset_FindFontFaceReference
,
7633 dwritefontset_FindFontFace
,
7634 dwritefontset_GetPropertyValues__
,
7635 dwritefontset_GetPropertyValues_
,
7636 dwritefontset_GetPropertyValues
,
7637 dwritefontset_GetPropertyOccurrenceCount
,
7638 dwritefontset_GetMatchingFonts_
,
7639 dwritefontset_GetMatchingFonts
,
7640 dwritefontset1_GetMatchingFonts
,
7641 dwritefontset1_GetFirstFontResources
,
7642 dwritefontset1_GetFilteredFonts__
,
7643 dwritefontset1_GetFilteredFonts_
,
7644 dwritefontset1_GetFilteredFonts
,
7645 dwritefontset1_GetFilteredFontIndices_
,
7646 dwritefontset1_GetFilteredFontIndices
,
7647 dwritefontset1_GetFontAxisRanges_
,
7648 dwritefontset1_GetFontAxisRanges
,
7649 dwritefontset1_GetFontFaceReference
,
7650 dwritefontset1_CreateFontResource
,
7651 dwritefontset1_CreateFontFace
,
7652 dwritefontset1_GetFontLocality
,
7653 dwritefontset2_GetExpirationEvent
,
7654 dwritefontset3_GetFontSourceType
,
7655 dwritefontset3_GetFontSourceNameLength
,
7656 dwritefontset3_GetFontSourceName
,
7659 static HRESULT
fontset_create_entry(IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
,
7660 unsigned int face_index
, unsigned int simulations
, struct dwrite_fontset_entry
**ret
)
7662 struct dwrite_fontset_entry
*entry
;
7664 if (!(entry
= heap_alloc_zero(sizeof(*entry
))))
7665 return E_OUTOFMEMORY
;
7667 entry
->refcount
= 1;
7669 IDWriteFontFile_AddRef(entry
->file
);
7670 entry
->face_type
= face_type
;
7671 entry
->face_index
= face_index
;
7672 entry
->simulations
= simulations
;
7679 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7680 struct dwrite_fontset_entry
**entries
, unsigned int count
)
7682 object
->IDWriteFontSet3_iface
.lpVtbl
= &fontsetvtbl
;
7683 object
->refcount
= 1;
7684 object
->factory
= factory
;
7685 IDWriteFactory7_AddRef(object
->factory
);
7686 object
->entries
= entries
;
7687 object
->count
= count
;
7690 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
7691 unsigned int count
, IDWriteFontSet1
**ret
)
7693 struct dwrite_fontset_entry
**entries
= NULL
;
7694 struct dwrite_fontset
*object
;
7697 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7698 return E_OUTOFMEMORY
;
7702 entries
= heap_calloc(count
, sizeof(*entries
));
7704 /* FIXME: set available properties too */
7706 for (i
= 0; i
< count
; ++i
)
7708 fontset_create_entry(fonts
[i
]->file
, fonts
[i
]->face_type
, fonts
[i
]->face_index
,
7709 fonts
[i
]->simulations
, &entries
[i
]);
7712 init_fontset(object
, factory
, entries
, count
);
7714 *ret
= (IDWriteFontSet1
*)&object
->IDWriteFontSet3_iface
;
7719 static HRESULT
fontset_builder_create_fontset(IDWriteFactory7
*factory
, struct dwrite_fontset_entry
**src_entries
,
7720 unsigned int count
, IDWriteFontSet
**ret
)
7722 struct dwrite_fontset_entry
**entries
= NULL
;
7723 struct dwrite_fontset
*object
;
7726 if (!(object
= heap_alloc_zero(sizeof(*object
))))
7727 return E_OUTOFMEMORY
;
7731 entries
= heap_calloc(count
, sizeof(*entries
));
7733 for (i
= 0; i
< count
; ++i
)
7734 entries
[i
] = addref_fontset_entry(src_entries
[i
]);
7736 init_fontset(object
, factory
, entries
, count
);
7738 *ret
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7743 static HRESULT WINAPI
dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2
*iface
,
7744 REFIID riid
, void **obj
)
7746 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7748 if (IsEqualIID(riid
, &IID_IDWriteFontSetBuilder2
) ||
7749 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder1
) ||
7750 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder
) ||
7751 IsEqualIID(riid
, &IID_IUnknown
))
7754 IDWriteFontSetBuilder2_AddRef(iface
);
7758 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7760 return E_NOINTERFACE
;
7763 static ULONG WINAPI
dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2
*iface
)
7765 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7766 ULONG refcount
= InterlockedIncrement(&builder
->refcount
);
7768 TRACE("%p, refcount %u.\n", iface
, refcount
);
7773 static ULONG WINAPI
dwritefontsetbuilder_Release(IDWriteFontSetBuilder2
*iface
)
7775 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7776 ULONG refcount
= InterlockedDecrement(&builder
->refcount
);
7779 TRACE("%p, refcount %u.\n", iface
, refcount
);
7783 IDWriteFactory7_Release(builder
->factory
);
7784 for (i
= 0; i
< builder
->count
; ++i
)
7785 release_fontset_entry(builder
->entries
[i
]);
7786 heap_free(builder
->entries
);
7793 static HRESULT
fontset_builder_add_entry(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
,
7794 DWRITE_FONT_FACE_TYPE face_type
, unsigned int face_index
, unsigned int simulations
)
7796 struct dwrite_fontset_entry
*entry
;
7799 if (!dwrite_array_reserve((void **)&builder
->entries
, &builder
->capacity
, builder
->count
+ 1,
7800 sizeof(*builder
->entries
)))
7802 return E_OUTOFMEMORY
;
7805 if (FAILED(hr
= fontset_create_entry(file
, face_type
, face_index
, simulations
, &entry
)))
7808 builder
->entries
[builder
->count
++] = entry
;
7813 static HRESULT
fontset_builder_add_file(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
)
7815 DWRITE_FONT_FILE_TYPE filetype
;
7816 DWRITE_FONT_FACE_TYPE facetype
;
7817 unsigned int i
, face_count
;
7818 BOOL supported
= FALSE
;
7821 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &filetype
, &facetype
, &face_count
)))
7825 return DWRITE_E_FILEFORMAT
;
7827 for (i
= 0; i
< face_count
; ++i
)
7829 if (FAILED(hr
= fontset_builder_add_entry(builder
, file
, facetype
, i
, DWRITE_FONT_SIMULATIONS_NONE
)))
7836 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2
*iface
,
7837 IDWriteFontFaceReference
*ref
, DWRITE_FONT_PROPERTY
const *props
, UINT32 prop_count
)
7839 FIXME("%p, %p, %p, %u.\n", iface
, ref
, props
, prop_count
);
7844 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2
*iface
,
7845 IDWriteFontFaceReference
*ref
)
7847 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7848 unsigned int face_count
, face_index
, simulations
;
7849 DWRITE_FONT_FILE_TYPE file_type
;
7850 DWRITE_FONT_FACE_TYPE face_type
;
7851 IDWriteFontFile
*file
;
7855 TRACE("%p, %p.\n", iface
, ref
);
7857 if (FAILED(hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
))) return hr
;
7858 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
)))
7863 hr
= DWRITE_E_FILEFORMAT
;
7867 face_index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
7868 simulations
= IDWriteFontFaceReference_GetSimulations(ref
);
7869 hr
= fontset_builder_add_entry(builder
, file
, face_type
, face_index
, simulations
);
7872 IDWriteFontFile_Release(file
);
7877 static HRESULT WINAPI
dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
*fontset
)
7879 FIXME("%p, %p.\n", iface
, fontset
);
7884 static HRESULT WINAPI
dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
**fontset
)
7886 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7888 TRACE("%p, %p.\n", iface
, fontset
);
7890 return fontset_builder_create_fontset(builder
->factory
, builder
->entries
, builder
->count
, fontset
);
7893 static HRESULT WINAPI
dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
)
7895 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7897 TRACE("%p, %p.\n", iface
, file
);
7899 return fontset_builder_add_file(builder
, file
);
7902 static HRESULT WINAPI
dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
,
7903 unsigned int face_index
, DWRITE_FONT_SIMULATIONS simulations
, const DWRITE_FONT_AXIS_VALUE
*axis_values
,
7904 unsigned int num_values
, const DWRITE_FONT_AXIS_RANGE
*axis_ranges
, unsigned int num_ranges
,
7905 const DWRITE_FONT_PROPERTY
*props
, unsigned int num_properties
)
7907 FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface
, file
, face_index
, simulations
, axis_values
, num_values
,
7908 axis_ranges
, num_ranges
, props
, num_properties
);
7913 static HRESULT WINAPI
dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2
*iface
, const WCHAR
*filepath
)
7915 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
7916 IDWriteFontFile
*file
;
7919 TRACE("%p, %s.\n", iface
, debugstr_w(filepath
));
7921 if (FAILED(hr
= IDWriteFactory7_CreateFontFileReference(builder
->factory
, filepath
, NULL
, &file
)))
7924 hr
= fontset_builder_add_file(builder
, file
);
7925 IDWriteFontFile_Release(file
);
7929 static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl
=
7931 dwritefontsetbuilder_QueryInterface
,
7932 dwritefontsetbuilder_AddRef
,
7933 dwritefontsetbuilder_Release
,
7934 dwritefontsetbuilder_AddFontFaceReference_
,
7935 dwritefontsetbuilder_AddFontFaceReference
,
7936 dwritefontsetbuilder_AddFontSet
,
7937 dwritefontsetbuilder_CreateFontSet
,
7938 dwritefontsetbuilder1_AddFontFile
,
7939 dwritefontsetbuilder2_AddFont
,
7940 dwritefontsetbuilder2_AddFontFile
,
7943 HRESULT
create_fontset_builder(IDWriteFactory7
*factory
, IDWriteFontSetBuilder2
**ret
)
7945 struct dwrite_fontset_builder
*builder
;
7949 if (!(builder
= heap_alloc_zero(sizeof(*builder
))))
7950 return E_OUTOFMEMORY
;
7952 builder
->IDWriteFontSetBuilder2_iface
.lpVtbl
= &fontsetbuildervtbl
;
7953 builder
->refcount
= 1;
7954 builder
->factory
= factory
;
7955 IDWriteFactory7_AddRef(builder
->factory
);
7957 *ret
= &builder
->IDWriteFontSetBuilder2_iface
;