4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2022 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"
31 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
32 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
34 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
35 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
36 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
37 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
38 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
39 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
40 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
41 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
43 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
45 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
46 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
47 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
58 struct wine_rb_entry entry
;
64 unsigned int bitmap_size
;
65 unsigned int is_1bpp
: 1;
66 unsigned int has_contours
: 1;
67 unsigned int has_advance
: 1;
68 unsigned int has_bbox
: 1;
69 unsigned int has_bitmap
: 1;
72 static void fontface_release_cache_entry(struct cache_entry
*entry
)
78 static struct cache_entry
* fontface_get_cache_entry(struct dwrite_fontface
*fontface
, size_t size
,
79 const struct cache_key
*key
)
81 struct cache_entry
*entry
, *old_entry
;
82 struct wine_rb_entry
*e
;
84 if (!(e
= wine_rb_get(&fontface
->cache
.tree
, key
)))
86 if (!(entry
= calloc(1, sizeof(*entry
)))) return NULL
;
88 list_init(&entry
->mru
);
90 size
+= sizeof(*entry
);
92 if ((fontface
->cache
.size
+ size
> fontface
->cache
.max_size
) && !list_empty(&fontface
->cache
.mru
))
94 old_entry
= LIST_ENTRY(list_tail(&fontface
->cache
.mru
), struct cache_entry
, mru
);
95 fontface
->cache
.size
-= (old_entry
->bitmap_size
+ sizeof(*old_entry
));
96 wine_rb_remove(&fontface
->cache
.tree
, &old_entry
->entry
);
97 list_remove(&old_entry
->mru
);
98 fontface_release_cache_entry(old_entry
);
101 if (wine_rb_put(&fontface
->cache
.tree
, &key
, &entry
->entry
) == -1)
103 WARN("Failed to add cache entry.\n");
108 fontface
->cache
.size
+= size
;
111 entry
= WINE_RB_ENTRY_VALUE(e
, struct cache_entry
, entry
);
113 list_remove(&entry
->mru
);
114 list_add_head(&fontface
->cache
.mru
, &entry
->mru
);
119 static int fontface_get_glyph_advance(struct dwrite_fontface
*fontface
, float fontsize
, unsigned short glyph
,
120 unsigned short mode
, BOOL
*has_contours
)
122 struct cache_key key
= { .size
= fontsize
, .glyph
= glyph
, .mode
= mode
};
123 struct get_glyph_advance_params params
;
124 struct cache_entry
*entry
;
127 if (!(entry
= fontface_get_cache_entry(fontface
, 0, &key
)))
130 if (!entry
->has_advance
)
132 params
.object
= fontface
->get_font_object(fontface
);
133 params
.glyph
= glyph
;
135 params
.emsize
= fontsize
;
136 params
.advance
= &entry
->advance
;
137 params
.has_contours
= &value
;
139 UNIX_CALL(get_glyph_advance
, ¶ms
);
141 entry
->has_contours
= !!value
;
142 entry
->has_advance
= 1;
145 *has_contours
= entry
->has_contours
;
146 return entry
->advance
;
149 void dwrite_fontface_get_glyph_bbox(IDWriteFontFace
*iface
, struct dwrite_glyphbitmap
*bitmap
)
151 struct cache_key key
= { .size
= bitmap
->emsize
, .glyph
= bitmap
->glyph
, .mode
= DWRITE_MEASURING_MODE_NATURAL
};
152 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
153 struct get_glyph_bbox_params params
;
154 struct cache_entry
*entry
;
156 params
.object
= fontface
->get_font_object(fontface
);
157 params
.simulations
= bitmap
->simulations
;
158 params
.glyph
= bitmap
->glyph
;
159 params
.emsize
= bitmap
->emsize
;
160 params
.m
= bitmap
->m
? *bitmap
->m
: identity
;
162 EnterCriticalSection(&fontface
->cs
);
163 /* For now bypass cache for transformed cases. */
164 if (bitmap
->m
&& memcmp(bitmap
->m
, &identity
, sizeof(*bitmap
->m
)))
166 params
.bbox
= &bitmap
->bbox
;
167 UNIX_CALL(get_glyph_bbox
, ¶ms
);
169 else if ((entry
= fontface_get_cache_entry(fontface
, 0, &key
)))
171 if (!entry
->has_bbox
)
173 params
.bbox
= &entry
->bbox
;
174 UNIX_CALL(get_glyph_bbox
, ¶ms
);
177 bitmap
->bbox
= entry
->bbox
;
179 LeaveCriticalSection(&fontface
->cs
);
182 static unsigned int get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
184 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
187 static HRESULT
dwrite_fontface_get_glyph_bitmap(struct dwrite_fontface
*fontface
, DWRITE_RENDERING_MODE rendering_mode
,
188 unsigned int *is_1bpp
, struct dwrite_glyphbitmap
*bitmap
)
190 struct cache_key key
= { .size
= bitmap
->emsize
, .glyph
= bitmap
->glyph
, .mode
= DWRITE_MEASURING_MODE_NATURAL
};
191 struct get_glyph_bitmap_params params
;
192 const RECT
*bbox
= &bitmap
->bbox
;
193 unsigned int bitmap_size
, _1bpp
;
194 struct cache_entry
*entry
;
197 bitmap_size
= get_glyph_bitmap_pitch(rendering_mode
, bbox
->right
- bbox
->left
) *
198 (bbox
->bottom
- bbox
->top
);
200 params
.object
= fontface
->get_font_object(fontface
);
201 params
.simulations
= fontface
->simulations
;
202 params
.glyph
= bitmap
->glyph
;
203 params
.mode
= rendering_mode
;
204 params
.emsize
= bitmap
->emsize
;
205 params
.m
= bitmap
->m
? *bitmap
->m
: identity
;
206 params
.bbox
= bitmap
->bbox
;
207 params
.pitch
= bitmap
->pitch
;
208 params
.bitmap
= bitmap
->buf
;
209 params
.is_1bpp
= is_1bpp
;
211 EnterCriticalSection(&fontface
->cs
);
212 /* For now bypass cache for transformed cases. */
213 if (memcmp(¶ms
.m
, &identity
, sizeof(params
.m
)))
215 UNIX_CALL(get_glyph_bitmap
, ¶ms
);
217 else if ((entry
= fontface_get_cache_entry(fontface
, bitmap_size
, &key
)))
219 if (entry
->has_bitmap
)
221 memcpy(bitmap
->buf
, entry
->bitmap
, entry
->bitmap_size
);
225 params
.is_1bpp
= &_1bpp
;
226 UNIX_CALL(get_glyph_bitmap
, ¶ms
);
228 entry
->bitmap_size
= bitmap_size
;
229 if ((entry
->bitmap
= malloc(entry
->bitmap_size
)))
230 memcpy(entry
->bitmap
, bitmap
->buf
, entry
->bitmap_size
);
231 entry
->is_1bpp
= !!_1bpp
;
232 entry
->has_bitmap
= 1;
234 *is_1bpp
= entry
->is_1bpp
;
238 LeaveCriticalSection(&fontface
->cs
);
243 static int fontface_cache_compare(const void *k
, const struct wine_rb_entry
*e
)
245 const struct cache_entry
*entry
= WINE_RB_ENTRY_VALUE(e
, const struct cache_entry
, entry
);
246 const struct cache_key
*key
= k
, *key2
= &entry
->key
;
248 if (key
->size
!= key2
->size
) return key
->size
< key2
->size
? -1 : 1;
249 if (key
->glyph
!= key2
->glyph
) return (int)key
->glyph
- (int)key2
->glyph
;
250 if (key
->mode
!= key2
->mode
) return (int)key
->mode
- (int)key2
->mode
;
254 static void fontface_cache_init(struct dwrite_fontface
*fontface
)
256 wine_rb_init(&fontface
->cache
.tree
, fontface_cache_compare
);
257 list_init(&fontface
->cache
.mru
);
258 fontface
->cache
.max_size
= 0x8000;
261 static void fontface_cache_clear(struct dwrite_fontface
*fontface
)
263 struct cache_entry
*entry
, *entry2
;
265 LIST_FOR_EACH_ENTRY_SAFE(entry
, entry2
, &fontface
->cache
.mru
, struct cache_entry
, mru
)
267 list_remove(&entry
->mru
);
268 fontface_release_cache_entry(entry
);
270 memset(&fontface
->cache
, 0, sizeof(fontface
->cache
));
273 struct dwrite_font_propvec
{
279 struct dwrite_font_data
283 DWRITE_FONT_STYLE style
;
284 DWRITE_FONT_STRETCH stretch
;
285 DWRITE_FONT_WEIGHT weight
;
286 DWRITE_PANOSE panose
;
287 FONTSIGNATURE fontsig
;
288 UINT32 flags
; /* enum font_flags */
289 struct dwrite_font_propvec propvec
;
290 struct dwrite_cmap cmap
;
291 /* Static axis for weight/width/italic. */
292 DWRITE_FONT_AXIS_VALUE axis
[3];
294 DWRITE_FONT_METRICS1 metrics
;
295 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
296 IDWriteLocalizedStrings
*family_names
;
297 IDWriteLocalizedStrings
*names
;
299 /* data needed to create fontface instance */
300 DWRITE_FONT_FACE_TYPE face_type
;
301 IDWriteFontFile
*file
;
310 /* used to mark font as tested when scanning for simulation candidate */
311 unsigned int bold_sim_tested
: 1;
312 unsigned int oblique_sim_tested
: 1;
315 struct dwrite_fontfamily_data
319 IDWriteLocalizedStrings
*familyname
;
321 struct dwrite_font_data
**fonts
;
325 unsigned int has_normal_face
: 1;
326 unsigned int has_oblique_face
: 1;
327 unsigned int has_italic_face
: 1;
330 struct dwrite_fontcollection
332 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
335 IDWriteFactory7
*factory
;
336 DWRITE_FONT_FAMILY_MODEL family_model
;
337 struct dwrite_fontfamily_data
**family_data
;
342 struct dwrite_fontfamily
344 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
345 IDWriteFontList2 IDWriteFontList2_iface
;
348 struct dwrite_fontfamily_data
*data
;
349 struct dwrite_fontcollection
*collection
;
352 struct dwrite_fontlist
354 IDWriteFontList2 IDWriteFontList2_iface
;
357 struct dwrite_font_data
**fonts
;
359 struct dwrite_fontfamily
*family
;
364 IDWriteFont3 IDWriteFont3_iface
;
367 DWRITE_FONT_STYLE style
;
368 struct dwrite_font_data
*data
;
369 struct dwrite_fontfamily
*family
;
372 enum runanalysis_flags
{
373 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
374 RUNANALYSIS_BITMAP_READY
= 1 << 1,
375 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
378 struct dwrite_glyphrunanalysis
380 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
383 DWRITE_RENDERING_MODE1 rendering_mode
;
384 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
385 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
388 D2D_POINT_2F
*origins
;
393 UINT32 max_glyph_bitmap_size
;
396 struct dwrite_colorglyphenum
398 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
401 D2D1_POINT_2F origin
; /* original run origin */
403 IDWriteFontFace5
*fontface
; /* for convenience */
404 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
405 DWRITE_GLYPH_RUN run
; /* base run */
406 UINT32 palette
; /* palette index to get layer color from */
407 FLOAT
*advances
; /* original or measured advances for base glyphs */
408 FLOAT
*color_advances
; /* returned color run points to this */
409 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
410 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
411 UINT16
*glyphindices
; /* returned color run points to this */
412 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
413 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
414 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
415 UINT16 max_layer_num
; /* max number of layers for this run */
416 struct dwrite_fonttable colr
; /* used to access layers */
419 struct dwrite_fontfile
421 IDWriteFontFile IDWriteFontFile_iface
;
424 IDWriteFontFileLoader
*loader
;
427 IDWriteFontFileStream
*stream
;
430 struct dwrite_fontfacereference
432 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
435 IDWriteFontFile
*file
;
438 DWRITE_FONT_AXIS_VALUE
*axis_values
;
439 UINT32 axis_values_count
;
440 IDWriteFactory7
*factory
;
443 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
445 struct dwrite_fontresource
447 IDWriteFontResource IDWriteFontResource_iface
;
450 IDWriteFontFile
*file
;
452 IDWriteFactory7
*factory
;
454 struct dwrite_var_axis
*axis
;
455 unsigned int axis_count
;
458 struct dwrite_fontset_entry_desc
460 IDWriteFontFile
*file
;
461 DWRITE_FONT_FACE_TYPE face_type
;
462 unsigned int face_index
;
463 unsigned int simulations
;
466 struct dwrite_fontset_entry
469 struct dwrite_fontset_entry_desc desc
;
470 IDWriteLocalizedStrings
*props
[DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
+ 1];
473 struct dwrite_fontset
475 IDWriteFontSet3 IDWriteFontSet3_iface
;
477 IDWriteFactory7
*factory
;
479 struct dwrite_fontset_entry
**entries
;
483 struct dwrite_fontset_builder
485 IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface
;
487 IDWriteFactory7
*factory
;
489 struct dwrite_fontset_entry
**entries
;
494 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
495 unsigned int count
, IDWriteFontSet1
**ret
);
497 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
499 struct dwrite_fontface
*fontface
= context
;
502 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
503 size
, data_context
, &exists
)) || !exists
)
507 *data_context
= NULL
;
511 static void dwrite_release_font_table(void *context
, void *data_context
)
513 struct dwrite_fontface
*fontface
= context
;
514 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
517 static UINT16
dwrite_get_font_upem(void *context
)
519 struct dwrite_fontface
*fontface
= context
;
520 return fontface
->metrics
.designUnitsPerEm
;
523 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
525 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
526 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
529 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
531 struct dwrite_fontface
*fontface
= context
;
532 return !!dwritefontface_get_glyph(fontface
, codepoint
);
535 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
537 struct dwrite_fontface
*fontface
= context
;
538 return dwritefontface_get_glyph(fontface
, codepoint
);
541 static const struct shaping_font_ops dwrite_font_ops
=
543 dwrite_grab_font_table
,
544 dwrite_release_font_table
,
545 dwrite_get_font_upem
,
550 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
552 if (fontface
->shaping_cache
)
553 return fontface
->shaping_cache
;
555 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
558 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
560 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
563 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
565 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
568 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
570 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
573 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
575 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
577 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
580 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
582 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
585 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
587 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
590 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
592 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
595 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
597 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
600 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
602 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
605 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
607 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
610 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
612 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
615 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
617 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
620 static struct dwrite_fontset_builder
*impl_from_IDWriteFontSetBuilder2(IDWriteFontSetBuilder2
*iface
)
622 return CONTAINING_RECORD(iface
, struct dwrite_fontset_builder
, IDWriteFontSetBuilder2_iface
);
625 static struct dwrite_fontset
*impl_from_IDWriteFontSet3(IDWriteFontSet3
*iface
)
627 return CONTAINING_RECORD(iface
, struct dwrite_fontset
, IDWriteFontSet3_iface
);
630 static struct dwrite_fontset
*unsafe_impl_from_IDWriteFontSet(IDWriteFontSet
*iface
);
632 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
634 static const DWRITE_GLYPH_METRICS nil
;
635 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
637 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
638 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
642 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
644 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
648 /* start new block */
649 if (!(*block
= calloc(GLYPH_BLOCK_SIZE
, sizeof(*metrics
))))
650 return E_OUTOFMEMORY
;
653 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
657 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
661 if (table
->data
|| !table
->exists
)
664 table
->exists
= FALSE
;
665 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
667 if (FAILED(hr
) || !table
->exists
) {
668 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
675 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
676 struct dwrite_font_propvec
*vec
)
678 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
679 vec
->style
= style
* 7.0f
;
680 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
683 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
685 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
688 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
690 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
693 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
695 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
696 return &fontface
->vdmx
;
699 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
701 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
702 return &fontface
->gasp
;
705 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
707 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
708 return &fontface
->cpal
;
711 static struct dwrite_font_data
* addref_font_data(struct dwrite_font_data
*data
)
713 InterlockedIncrement(&data
->refcount
);
717 static void release_font_data(struct dwrite_font_data
*data
)
721 if (InterlockedDecrement(&data
->refcount
) > 0)
724 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
726 if (data
->info_strings
[i
])
727 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
730 IDWriteLocalizedStrings_Release(data
->names
);
732 if (data
->family_names
)
733 IDWriteLocalizedStrings_Release(data
->family_names
);
735 dwrite_cmap_release(&data
->cmap
);
736 IDWriteFontFile_Release(data
->file
);
737 free(data
->facename
);
741 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
745 if (InterlockedDecrement(&data
->refcount
) > 0)
748 for (i
= 0; i
< data
->count
; ++i
)
749 release_font_data(data
->fonts
[i
]);
751 IDWriteLocalizedStrings_Release(data
->familyname
);
755 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
757 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
758 fontface
->cached
= NULL
;
761 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
763 UINT32 left_key_size
, right_key_size
;
764 const void *left_key
, *right_key
;
770 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
774 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
778 if (left_key_size
!= right_key_size
)
781 return !memcmp(left_key
, right_key
, left_key_size
);
784 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
786 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
788 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
790 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
791 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
792 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
793 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
794 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
795 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
796 IsEqualIID(riid
, &IID_IUnknown
))
800 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
801 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
807 if (InterlockedIncrement(&fontface
->refcount
) == 1)
809 InterlockedDecrement(&fontface
->refcount
);
816 WARN("%s not implemented.\n", debugstr_guid(riid
));
818 return E_NOINTERFACE
;
821 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
823 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
824 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
826 TRACE("%p, refcount %lu.\n", iface
, refcount
);
831 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
833 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
834 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
835 struct release_font_object_params params
= { fontface
->font_object
};
837 TRACE("%p, refcount %lu.\n", iface
, refcount
);
843 if (fontface
->cached
)
845 factory_lock(fontface
->factory
);
846 list_remove(&fontface
->cached
->entry
);
847 factory_unlock(fontface
->factory
);
848 free(fontface
->cached
);
850 release_scriptshaping_cache(fontface
->shaping_cache
);
851 if (fontface
->vdmx
.context
)
852 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
853 if (fontface
->gasp
.context
)
854 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
855 if (fontface
->cpal
.context
)
856 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
857 if (fontface
->colr
.context
)
858 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
859 if (fontface
->kern
.context
)
860 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->kern
.context
);
862 IDWriteFontFile_Release(fontface
->file
);
864 IDWriteLocalizedStrings_Release(fontface
->names
);
865 if (fontface
->family_names
)
866 IDWriteLocalizedStrings_Release(fontface
->family_names
);
867 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
869 if (fontface
->info_strings
[i
])
870 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
873 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
874 free(fontface
->glyphs
[i
]);
876 UNIX_CALL(release_font_object
, ¶ms
);
877 if (fontface
->stream
)
879 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, fontface
->data_context
);
880 IDWriteFontFileStream_Release(fontface
->stream
);
882 fontface_cache_clear(fontface
);
884 dwrite_cmap_release(&fontface
->cmap
);
885 IDWriteFactory7_Release(fontface
->factory
);
886 DeleteCriticalSection(&fontface
->cs
);
893 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
895 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
897 TRACE("%p.\n", iface
);
899 return fontface
->type
;
902 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
903 IDWriteFontFile
**fontfiles
)
905 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
907 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
911 *number_of_files
= 1;
915 if (!*number_of_files
)
918 IDWriteFontFile_AddRef(fontface
->file
);
919 *fontfiles
= fontface
->file
;
924 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
926 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
928 TRACE("%p.\n", iface
);
930 return fontface
->index
;
933 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
935 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
937 TRACE("%p.\n", iface
);
939 return fontface
->simulations
;
942 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
944 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
946 TRACE("%p.\n", iface
);
948 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
951 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
953 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
955 TRACE("%p, %p.\n", iface
, metrics
);
957 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
960 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
962 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
963 struct get_glyph_count_params params
;
966 TRACE("%p.\n", iface
);
968 params
.object
= fontface
->get_font_object(fontface
);
969 params
.count
= &count
;
970 UNIX_CALL(get_glyph_count
, ¶ms
);
975 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
976 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
978 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
979 struct get_design_glyph_metrics_params params
;
980 DWRITE_GLYPH_METRICS metrics
;
984 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
990 FIXME("sideways metrics are not supported.\n");
992 params
.object
= fontface
->get_font_object(fontface
);
993 params
.simulations
= fontface
->simulations
;
994 params
.upem
= fontface
->metrics
.designUnitsPerEm
;
995 params
.ascent
= fontface
->typo_metrics
.ascent
;
996 params
.metrics
= &metrics
;
998 EnterCriticalSection(&fontface
->cs
);
999 for (i
= 0; i
< glyph_count
; ++i
)
1002 if (get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
) != S_OK
)
1004 params
.glyph
= glyphs
[i
];
1005 UNIX_CALL(get_design_glyph_metrics
, ¶ms
);
1006 if (FAILED(hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
))) break;
1010 LeaveCriticalSection(&fontface
->cs
);
1015 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
1016 UINT32 count
, UINT16
*glyphs
)
1018 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1021 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
1024 return E_INVALIDARG
;
1028 memset(glyphs
, 0, count
* sizeof(*glyphs
));
1029 return E_INVALIDARG
;
1032 for (i
= 0; i
< count
; ++i
)
1033 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
1038 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
1039 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
1041 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1042 struct file_stream_desc stream_desc
;
1044 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
1046 stream_desc
.stream
= fontface
->stream
;
1047 stream_desc
.face_type
= fontface
->type
;
1048 stream_desc
.face_index
= fontface
->index
;
1049 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
1052 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
1054 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1056 TRACE("%p, %p.\n", iface
, table_context
);
1058 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
1061 static void apply_outline_point_offset(const D2D1_POINT_2F
*src
, const D2D1_POINT_2F
*offset
,
1064 dst
->x
= src
->x
+ offset
->x
;
1065 dst
->y
= src
->y
+ offset
->y
;
1068 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
1069 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
1070 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
1072 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1073 D2D1_POINT_2F
*origins
, baseline_origin
= { 0 };
1074 struct dwrite_outline outline
, outline_size
;
1075 struct get_glyph_outline_params params
;
1076 D2D1_BEZIER_SEGMENT segment
;
1077 D2D1_POINT_2F point
;
1078 DWRITE_GLYPH_RUN run
;
1079 unsigned int i
, j
, p
;
1083 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
1084 count
, is_sideways
, is_rtl
, sink
);
1086 if (!glyphs
|| !sink
)
1087 return E_INVALIDARG
;
1092 run
.fontFace
= (IDWriteFontFace
*)iface
;
1093 run
.fontEmSize
= emSize
;
1094 run
.glyphCount
= count
;
1095 run
.glyphIndices
= glyphs
;
1096 run
.glyphAdvances
= advances
;
1097 run
.glyphOffsets
= offsets
;
1098 run
.isSideways
= is_sideways
;
1099 run
.bidiLevel
= is_rtl
? 1 : 0;
1101 if (!(origins
= malloc(sizeof(*origins
) * count
)))
1102 return E_OUTOFMEMORY
;
1104 if (FAILED(hr
= compute_glyph_origins(&run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
, NULL
, origins
)))
1110 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
1112 memset(&outline_size
, 0, sizeof(outline_size
));
1113 memset(&outline
, 0, sizeof(outline
));
1115 params
.object
= fontface
->get_font_object(fontface
);
1116 params
.simulations
= fontface
->simulations
;
1117 params
.emsize
= emSize
;
1119 for (i
= 0; i
< count
; ++i
)
1121 outline
.tags
.count
= outline
.points
.count
= 0;
1123 EnterCriticalSection(&fontface
->cs
);
1125 params
.glyph
= glyphs
[i
];
1126 params
.outline
= &outline_size
;
1128 if (!(status
= UNIX_CALL(get_glyph_outline
, ¶ms
)))
1130 dwrite_array_reserve((void **)&outline
.tags
.values
, &outline
.tags
.size
, outline_size
.tags
.count
,
1131 sizeof(*outline
.tags
.values
));
1132 dwrite_array_reserve((void **)&outline
.points
.values
, &outline
.points
.size
, outline_size
.points
.count
,
1133 sizeof(*outline
.points
.values
));
1135 params
.outline
= &outline
;
1136 if ((status
= UNIX_CALL(get_glyph_outline
, ¶ms
)))
1138 WARN("Failed to get glyph outline for glyph %u.\n", glyphs
[i
]);
1141 LeaveCriticalSection(&fontface
->cs
);
1146 for (j
= 0, p
= 0; j
< outline
.tags
.count
; ++j
)
1148 switch (outline
.tags
.values
[j
])
1150 case OUTLINE_BEGIN_FIGURE
:
1151 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
1152 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, point
, D2D1_FIGURE_BEGIN_FILLED
);
1154 case OUTLINE_END_FIGURE
:
1155 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
1158 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
1159 ID2D1SimplifiedGeometrySink_AddLines(sink
, &point
, 1);
1161 case OUTLINE_BEZIER
:
1162 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point1
);
1163 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point2
);
1164 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point3
);
1165 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, &segment
, 1);
1171 free(outline
.tags
.values
);
1172 free(outline
.points
.values
);
1178 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
1179 float ppem
, unsigned int gasp
)
1181 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
1185 case DWRITE_MEASURING_MODE_NATURAL
:
1187 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
1188 mode
= DWRITE_RENDERING_MODE_NATURAL
;
1190 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
1193 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1194 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
1196 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1197 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
1206 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1207 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
1209 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1213 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
1216 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
1217 return E_INVALIDARG
;
1220 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1221 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
1224 ppem
= emSize
* ppdip
;
1226 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
1227 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
1231 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
1232 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
1236 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
1237 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
1239 DWRITE_FONT_METRICS1 metrics1
;
1240 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
1241 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
1245 static inline int round_metric(FLOAT metric
)
1247 return (int)floorf(metric
+ 0.5f
);
1250 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
1252 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
1255 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
1258 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
1259 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
1260 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
1262 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1263 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1264 DWRITE_MEASURING_MODE mode
;
1269 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
1270 glyph_count
, metrics
, is_sideways
);
1272 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1273 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
1275 size
= emSize
* ppdip
;
1276 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
1277 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1279 EnterCriticalSection(&fontface
->cs
);
1280 for (i
= 0; i
< glyph_count
; ++i
)
1282 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
1283 DWRITE_GLYPH_METRICS design
;
1286 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
1290 ret
->advanceWidth
= fontface_get_glyph_advance(fontface
, size
, glyphs
[i
], mode
, &has_contours
);
1292 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
1294 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
1296 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
1297 SCALE_METRIC(leftSideBearing
);
1298 SCALE_METRIC(rightSideBearing
);
1299 SCALE_METRIC(topSideBearing
);
1300 SCALE_METRIC(advanceHeight
);
1301 SCALE_METRIC(bottomSideBearing
);
1302 SCALE_METRIC(verticalOriginY
);
1305 LeaveCriticalSection(&fontface
->cs
);
1310 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1312 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1314 TRACE("%p, %p.\n", iface
, metrics
);
1316 *metrics
= fontface
->metrics
;
1319 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
1320 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
1322 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1323 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
1324 UINT16 ascent
, descent
;
1327 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
1329 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
1330 memset(metrics
, 0, sizeof(*metrics
));
1331 return E_INVALIDARG
;
1334 em_size
*= pixels_per_dip
;
1335 if (m
&& m
->m22
!= 0.0f
)
1336 em_size
*= fabs(m
->m22
);
1338 scale
= em_size
/ design
->designUnitsPerEm
;
1339 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
1341 ascent
= round_metric(design
->ascent
* scale
);
1342 descent
= round_metric(design
->descent
* scale
);
1345 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
1346 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
1347 metrics
->ascent
= round_metric(ascent
/ scale
);
1348 metrics
->descent
= round_metric(descent
/ scale
);
1350 SCALE_METRIC(lineGap
);
1351 SCALE_METRIC(capHeight
);
1352 SCALE_METRIC(xHeight
);
1353 SCALE_METRIC(underlinePosition
);
1354 SCALE_METRIC(underlineThickness
);
1355 SCALE_METRIC(strikethroughPosition
);
1356 SCALE_METRIC(strikethroughThickness
);
1357 SCALE_METRIC(glyphBoxLeft
);
1358 SCALE_METRIC(glyphBoxTop
);
1359 SCALE_METRIC(glyphBoxRight
);
1360 SCALE_METRIC(glyphBoxBottom
);
1361 SCALE_METRIC(subscriptPositionX
);
1362 SCALE_METRIC(subscriptPositionY
);
1363 SCALE_METRIC(subscriptSizeX
);
1364 SCALE_METRIC(subscriptSizeY
);
1365 SCALE_METRIC(superscriptPositionX
);
1366 SCALE_METRIC(superscriptPositionY
);
1367 SCALE_METRIC(superscriptSizeX
);
1368 SCALE_METRIC(superscriptSizeY
);
1370 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
1376 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1378 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1380 TRACE("%p, %p.\n", iface
, metrics
);
1382 *metrics
= fontface
->caret
;
1385 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1386 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1388 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1390 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1393 if (max_count
&& !ranges
)
1394 return E_INVALIDARG
;
1396 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1397 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1400 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1402 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1404 TRACE("%p.\n", iface
);
1406 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1409 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1410 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1412 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1417 FIXME("Sideways mode is not supported.\n");
1419 switch (measuring_mode
)
1421 case DWRITE_MEASURING_MODE_NATURAL
:
1422 advance
= fontface_get_glyph_advance(fontface
, fontface
->metrics
.designUnitsPerEm
, glyph
,
1423 measuring_mode
, &has_contours
);
1425 advance
+= adjustment
;
1428 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1429 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1434 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1435 FIXME("Transform is not supported.\n");
1437 advance
= fontface_get_glyph_advance(fontface
, emsize
, glyph
, measuring_mode
, &has_contours
);
1439 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1441 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1445 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1450 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1451 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1453 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1456 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1459 FIXME("sideways mode not supported\n");
1461 EnterCriticalSection(&fontface
->cs
);
1462 for (i
= 0; i
< glyph_count
; ++i
)
1464 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1465 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1467 LeaveCriticalSection(&fontface
->cs
);
1472 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1473 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1474 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1476 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1477 DWRITE_MEASURING_MODE measuring_mode
;
1480 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1481 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1483 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1484 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1485 return E_INVALIDARG
;
1488 if (em_size
== 0.0f
) {
1489 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1493 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1495 EnterCriticalSection(&fontface
->cs
);
1496 for (i
= 0; i
< glyph_count
; ++i
)
1498 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1499 glyphs
[i
], is_sideways
);
1501 LeaveCriticalSection(&fontface
->cs
);
1506 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1507 const UINT16
*glyphs
, INT32
*values
)
1509 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1511 TRACE("%p, %u, %p, %p.\n", iface
, count
, glyphs
, values
);
1513 if (!(glyphs
|| values
) || !count
)
1514 return E_INVALIDARG
;
1516 if (!glyphs
|| count
== 1)
1518 memset(values
, 0, count
* sizeof(*values
));
1519 return E_INVALIDARG
;
1522 return opentype_get_kerning_pairs(fontface
, count
, glyphs
, values
);
1525 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1527 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1529 TRACE("%p.\n", iface
);
1531 return opentype_has_kerning_pairs(fontface
);
1534 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1535 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1536 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1538 DWRITE_GRID_FIT_MODE gridfitmode
;
1539 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1540 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1543 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1544 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1546 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1548 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1550 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1553 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1555 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1557 TRACE("%p.\n", iface
);
1559 return opentype_has_vertical_variants(fontface
);
1562 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1564 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1566 TRACE("%p.\n", iface
);
1568 return !!(fontface
->flags
& FONT_IS_COLORED
);
1571 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1573 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1575 TRACE("%p.\n", iface
);
1577 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1580 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1582 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1584 TRACE("%p.\n", iface
);
1586 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1589 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1590 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1592 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1594 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1596 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1599 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1600 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1601 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1602 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1604 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1608 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1609 measuringmode
, params
, renderingmode
, gridfitmode
);
1611 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1612 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1615 FIXME("sideways mode not supported\n");
1617 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1619 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1620 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1622 IDWriteRenderingParams2
*params2
;
1625 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1627 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1628 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1629 IDWriteRenderingParams2_Release(params2
);
1632 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1635 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1637 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1639 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1640 if (emSize
>= emthreshold
)
1641 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1643 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1646 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1647 if (emSize
>= emthreshold
)
1648 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1649 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1650 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1652 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1653 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1659 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1660 IDWriteFontFaceReference
**reference
)
1662 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1664 TRACE("%p, %p.\n", iface
, reference
);
1666 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1667 IDWriteFontFaceReference_AddRef(*reference
);
1672 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1674 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1676 TRACE("%p, %p.\n", iface
, panose
);
1678 *panose
= fontface
->panose
;
1681 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1683 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1685 TRACE("%p.\n", iface
);
1687 return fontface
->weight
;
1690 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1692 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1694 TRACE("%p.\n", iface
);
1696 return fontface
->stretch
;
1699 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1701 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1703 TRACE("%p.\n", iface
);
1705 return fontface
->style
;
1708 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1710 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1712 TRACE("%p, %p.\n", iface
, names
);
1714 return clone_localizedstrings(fontface
->family_names
, names
);
1717 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1719 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1721 TRACE("%p, %p.\n", iface
, names
);
1723 return clone_localizedstrings(fontface
->names
, names
);
1726 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1727 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1728 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1735 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1736 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1741 if (!strings_cache
[stringid
])
1743 struct file_stream_desc desc
= *stream_desc
;
1746 hr
= get_filestream_from_file(file
, &desc
.stream
);
1748 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1750 if (!stream_desc
->stream
&& desc
.stream
)
1751 IDWriteFontFileStream_Release(desc
.stream
);
1754 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1756 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1764 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1765 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1767 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1768 struct file_stream_desc stream_desc
;
1770 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1772 stream_desc
.stream
= fontface
->stream
;
1773 stream_desc
.face_index
= fontface
->index
;
1774 stream_desc
.face_type
= fontface
->type
;
1775 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1778 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1780 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1782 TRACE("%p, %#x.\n", iface
, ch
);
1784 return !!dwritefontface_get_glyph(fontface
, ch
);
1787 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1788 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1789 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1791 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1795 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1796 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1798 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1799 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1802 FIXME("sideways mode not supported\n");
1804 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1806 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1807 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1809 IDWriteRenderingParams3
*params3
;
1812 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1814 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1815 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1816 IDWriteRenderingParams3_Release(params3
);
1819 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1822 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1824 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1826 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1827 if (emSize
>= emthreshold
)
1828 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1830 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1833 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1834 if (emSize
>= emthreshold
)
1835 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1836 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1837 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1839 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1840 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1846 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1848 FIXME("%p, %#x: stub\n", iface
, ch
);
1853 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1855 FIXME("%p, %u: stub\n", iface
, glyph
);
1860 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1861 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1863 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1868 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1869 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1871 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1876 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1877 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1879 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1884 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1886 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1888 TRACE("%p.\n", iface
);
1890 return fontface
->glyph_image_formats
;
1893 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1894 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1896 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1901 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1903 FIXME("%p, %p: stub\n", iface
, context
);
1906 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1908 FIXME("%p: stub\n", iface
);
1913 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1916 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1921 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1926 FIXME("%p: stub\n", iface
);
1931 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1933 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1935 TRACE("%p, %p.\n", iface
, resource
);
1937 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->file
, fontface
->index
, resource
);
1940 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1942 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1944 TRACE("%p, %p.\n", iface
, other
);
1946 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1949 /* TODO: add variations support */
1951 return fontface
->index
== other_face
->index
&&
1952 fontface
->simulations
== other_face
->simulations
&&
1953 is_same_fontfile(fontface
->file
, other_face
->file
);
1956 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1958 dwritefontface_QueryInterface
,
1959 dwritefontface_AddRef
,
1960 dwritefontface_Release
,
1961 dwritefontface_GetType
,
1962 dwritefontface_GetFiles
,
1963 dwritefontface_GetIndex
,
1964 dwritefontface_GetSimulations
,
1965 dwritefontface_IsSymbolFont
,
1966 dwritefontface_GetMetrics
,
1967 dwritefontface_GetGlyphCount
,
1968 dwritefontface_GetDesignGlyphMetrics
,
1969 dwritefontface_GetGlyphIndices
,
1970 dwritefontface_TryGetFontTable
,
1971 dwritefontface_ReleaseFontTable
,
1972 dwritefontface_GetGlyphRunOutline
,
1973 dwritefontface_GetRecommendedRenderingMode
,
1974 dwritefontface_GetGdiCompatibleMetrics
,
1975 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1976 dwritefontface1_GetMetrics
,
1977 dwritefontface1_GetGdiCompatibleMetrics
,
1978 dwritefontface1_GetCaretMetrics
,
1979 dwritefontface1_GetUnicodeRanges
,
1980 dwritefontface1_IsMonospacedFont
,
1981 dwritefontface1_GetDesignGlyphAdvances
,
1982 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1983 dwritefontface1_GetKerningPairAdjustments
,
1984 dwritefontface1_HasKerningPairs
,
1985 dwritefontface1_GetRecommendedRenderingMode
,
1986 dwritefontface1_GetVerticalGlyphVariants
,
1987 dwritefontface1_HasVerticalGlyphVariants
,
1988 dwritefontface2_IsColorFont
,
1989 dwritefontface2_GetColorPaletteCount
,
1990 dwritefontface2_GetPaletteEntryCount
,
1991 dwritefontface2_GetPaletteEntries
,
1992 dwritefontface2_GetRecommendedRenderingMode
,
1993 dwritefontface3_GetFontFaceReference
,
1994 dwritefontface3_GetPanose
,
1995 dwritefontface3_GetWeight
,
1996 dwritefontface3_GetStretch
,
1997 dwritefontface3_GetStyle
,
1998 dwritefontface3_GetFamilyNames
,
1999 dwritefontface3_GetFaceNames
,
2000 dwritefontface3_GetInformationalStrings
,
2001 dwritefontface3_HasCharacter
,
2002 dwritefontface3_GetRecommendedRenderingMode
,
2003 dwritefontface3_IsCharacterLocal
,
2004 dwritefontface3_IsGlyphLocal
,
2005 dwritefontface3_AreCharactersLocal
,
2006 dwritefontface3_AreGlyphsLocal
,
2007 dwritefontface4_GetGlyphImageFormats_
,
2008 dwritefontface4_GetGlyphImageFormats
,
2009 dwritefontface4_GetGlyphImageData
,
2010 dwritefontface4_ReleaseGlyphImageData
,
2011 dwritefontface5_GetFontAxisValueCount
,
2012 dwritefontface5_GetFontAxisValues
,
2013 dwritefontface5_HasVariations
,
2014 dwritefontface5_GetFontResource
,
2015 dwritefontface5_Equals
,
2018 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
2020 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2021 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
2024 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
2026 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2027 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
2030 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
2032 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2033 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
2036 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
2037 IDWriteFontFace3
**ret
)
2039 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2041 TRACE("%p, %p.\n", iface
, ret
);
2043 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
2044 IDWriteFontFace3_AddRef(*ret
);
2049 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
2050 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
2052 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2053 DWRITE_FONT_FILE_TYPE file_type
;
2054 DWRITE_FONT_FACE_TYPE face_type
;
2055 IDWriteFontFace
*face
;
2060 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
2062 hr
= IDWriteFontFile_Analyze(fontface
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
2066 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, &fontface
->file
, fontface
->index
,
2067 simulations
, &face
);
2070 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
2071 IDWriteFontFace_Release(face
);
2077 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
2079 FIXME("%p, %p.\n", iface
, ref
);
2084 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
2086 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2088 TRACE("%p.\n", iface
);
2090 return fontface
->index
;
2093 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
2095 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2097 TRACE("%p.\n", iface
);
2099 return fontface
->simulations
;
2102 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
2104 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2106 TRACE("%p, %p.\n", iface
, file
);
2108 *file
= fontface
->file
;
2109 IDWriteFontFile_AddRef(*file
);
2114 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
2116 FIXME("%p.\n", iface
);
2121 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
2123 FIXME("%p.\n", iface
);
2128 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
2130 FIXME("%p, %p.\n", iface
, writetime
);
2135 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
2137 FIXME("%p.\n", iface
);
2139 return DWRITE_LOCALITY_LOCAL
;
2142 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
2144 FIXME("%p.\n", iface
);
2149 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
2150 WCHAR
const *chars
, UINT32 count
)
2152 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
2157 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
2158 UINT16
const *glyphs
, UINT32 count
)
2160 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
2165 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
2166 UINT64 offset
, UINT64 size
)
2168 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
2173 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
2175 dwritefontface_reference_QueryInterface
,
2176 dwritefontface_reference_AddRef
,
2177 dwritefontface_reference_Release
,
2178 dwritefontface_reference_CreateFontFace
,
2179 dwritefontface_reference_CreateFontFaceWithSimulations
,
2180 dwritefontface_reference_Equals
,
2181 dwritefontface_reference_GetFontFaceIndex
,
2182 dwritefontface_reference_GetSimulations
,
2183 dwritefontface_reference_GetFontFile
,
2184 dwritefontface_reference_GetLocalFileSize
,
2185 dwritefontface_reference_GetFileSize
,
2186 dwritefontface_reference_GetFileTime
,
2187 dwritefontface_reference_GetLocality
,
2188 dwritefontface_reference_EnqueueFontDownloadRequest
,
2189 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
2190 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
2191 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
2194 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
2196 struct dwrite_font_data
*data
= font
->data
;
2197 struct fontface_desc desc
;
2198 struct list
*cached_list
;
2203 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
2204 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
2208 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
2211 desc
.factory
= font
->family
->collection
->factory
;
2212 desc
.face_type
= data
->face_type
;
2213 desc
.file
= data
->file
;
2214 desc
.index
= data
->face_index
;
2215 desc
.simulations
= data
->simulations
;
2216 desc
.font_data
= data
;
2217 hr
= create_fontface(&desc
, cached_list
, fontface
);
2219 IDWriteFontFileStream_Release(desc
.stream
);
2223 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
2225 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2227 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
2228 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
2229 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
2230 IsEqualIID(riid
, &IID_IDWriteFont
) ||
2231 IsEqualIID(riid
, &IID_IUnknown
))
2234 IDWriteFont3_AddRef(iface
);
2238 WARN("%s not implemented.\n", debugstr_guid(riid
));
2241 return E_NOINTERFACE
;
2244 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
2246 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2247 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
2249 TRACE("%p, refcount %ld.\n", iface
, refcount
);
2254 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
2256 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2257 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
2259 TRACE("%p, refcount %ld.\n", iface
, refcount
);
2263 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
2264 release_font_data(font
->data
);
2271 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
2273 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2275 TRACE("%p, %p.\n", iface
, family
);
2277 *family
= (IDWriteFontFamily
*)&font
->family
->IDWriteFontFamily2_iface
;
2278 IDWriteFontFamily_AddRef(*family
);
2282 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
2284 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2286 TRACE("%p.\n", iface
);
2288 return font
->data
->weight
;
2291 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
2293 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2295 TRACE("%p.\n", iface
);
2297 return font
->data
->stretch
;
2300 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
2302 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2304 TRACE("%p.\n", iface
);
2309 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
2311 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2313 TRACE("%p.\n", iface
);
2315 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
2318 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
2320 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2322 TRACE("%p, %p.\n", iface
, names
);
2324 return clone_localizedstrings(font
->data
->names
, names
);
2327 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
2328 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
2330 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2331 struct dwrite_font_data
*data
= font
->data
;
2332 struct file_stream_desc stream_desc
;
2334 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
2336 /* Stream will be created if necessary. */
2337 stream_desc
.stream
= NULL
;
2338 stream_desc
.face_index
= data
->face_index
;
2339 stream_desc
.face_type
= data
->face_type
;
2340 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
2343 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
2345 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2347 TRACE("%p.\n", iface
);
2349 return font
->data
->simulations
;
2352 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
2354 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2356 TRACE("%p, %p.\n", iface
, metrics
);
2358 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
2361 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
2364 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2365 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
2369 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2371 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2373 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2375 *exists
= dwritefont_has_character(font
, ch
);
2380 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2382 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2384 TRACE("%p, %p.\n", iface
, fontface
);
2386 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2389 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2391 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2393 TRACE("%p, %p.\n", iface
, metrics
);
2395 *metrics
= font
->data
->metrics
;
2398 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2400 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2402 TRACE("%p, %p.\n", iface
, panose
);
2404 *panose
= font
->data
->panose
;
2407 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2410 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2412 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2415 if (max_count
&& !ranges
)
2416 return E_INVALIDARG
;
2418 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2419 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2422 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2424 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2426 TRACE("%p.\n", iface
);
2428 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2431 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2433 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2435 TRACE("%p.\n", iface
);
2437 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2440 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2442 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2444 TRACE("%p, %p.\n", iface
, fontface
);
2446 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2449 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2451 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2453 TRACE("%p, %p.\n", iface
, other
);
2455 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2458 return font
->data
->face_index
== other_font
->data
->face_index
2459 && font
->data
->simulations
== other_font
->data
->simulations
2460 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2463 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2465 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2467 TRACE("%p, %p.\n", iface
, reference
);
2469 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2470 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2471 (IDWriteFontFaceReference1
**)reference
);
2474 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2476 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2478 TRACE("%p, %#x.\n", iface
, ch
);
2480 return dwritefont_has_character(font
, ch
);
2483 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2485 FIXME("%p: stub.\n", iface
);
2487 return DWRITE_LOCALITY_LOCAL
;
2490 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2491 dwritefont_QueryInterface
,
2494 dwritefont_GetFontFamily
,
2495 dwritefont_GetWeight
,
2496 dwritefont_GetStretch
,
2497 dwritefont_GetStyle
,
2498 dwritefont_IsSymbolFont
,
2499 dwritefont_GetFaceNames
,
2500 dwritefont_GetInformationalStrings
,
2501 dwritefont_GetSimulations
,
2502 dwritefont_GetMetrics
,
2503 dwritefont_HasCharacter
,
2504 dwritefont_CreateFontFace
,
2505 dwritefont1_GetMetrics
,
2506 dwritefont1_GetPanose
,
2507 dwritefont1_GetUnicodeRanges
,
2508 dwritefont1_IsMonospacedFont
,
2509 dwritefont2_IsColorFont
,
2510 dwritefont3_CreateFontFace
,
2512 dwritefont3_GetFontFaceReference
,
2513 dwritefont3_HasCharacter
,
2514 dwritefont3_GetLocality
2517 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2521 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2522 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2525 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2529 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2530 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2533 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2537 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2539 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2540 IDWriteFontFaceReference1_iface
);
2543 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2545 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2546 *lf
= font
->data
->lf
;
2549 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2551 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2555 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2557 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2558 *fontsig
= font
->data
->fontsig
;
2562 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2564 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2565 *fontsig
= fontface
->fontsig
;
2569 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2571 struct dwrite_font
*object
;
2575 if (!(object
= calloc(1, sizeof(*object
))))
2576 return E_OUTOFMEMORY
;
2578 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2579 object
->refcount
= 1;
2580 object
->family
= family
;
2581 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2582 object
->data
= family
->data
->fonts
[index
];
2583 object
->style
= object
->data
->style
;
2584 addref_font_data(object
->data
);
2586 *font
= &object
->IDWriteFont3_iface
;
2591 /* IDWriteFontList2 */
2592 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2594 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2596 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2597 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2598 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2599 IsEqualIID(riid
, &IID_IUnknown
))
2602 IDWriteFontList2_AddRef(iface
);
2606 WARN("%s not implemented.\n", debugstr_guid(riid
));
2609 return E_NOINTERFACE
;
2612 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2614 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2615 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2617 TRACE("%p, refcount %lu.\n", iface
, refcount
);
2622 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2624 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2625 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2627 TRACE("%p, refcount %lu.\n", iface
, refcount
);
2633 for (i
= 0; i
< fontlist
->font_count
; i
++)
2634 release_font_data(fontlist
->fonts
[i
]);
2635 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2636 free(fontlist
->fonts
);
2643 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2645 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2646 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2649 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2651 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2653 TRACE("%p.\n", iface
);
2655 return fontlist
->font_count
;
2658 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2660 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2662 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2666 if (fontlist
->font_count
== 0)
2669 if (index
>= fontlist
->font_count
)
2670 return E_INVALIDARG
;
2672 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2675 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2677 FIXME("%p, %u.\n", iface
, index
);
2679 return DWRITE_LOCALITY_LOCAL
;
2682 static HRESULT
fontlist_get_font(const struct dwrite_fontlist
*fontlist
, unsigned int index
,
2683 IDWriteFont3
**font
)
2687 if (fontlist
->font_count
== 0)
2690 if (index
>= fontlist
->font_count
)
2693 return create_font(fontlist
->family
, index
, font
);
2696 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2698 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2700 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2702 return fontlist_get_font(fontlist
, index
, font
);
2705 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2706 IDWriteFontFaceReference
**reference
)
2708 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2712 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2716 if (SUCCEEDED(hr
= fontlist_get_font(fontlist
, index
, &font
)))
2718 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2719 IDWriteFont3_Release(font
);
2725 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2727 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2729 TRACE("%p, %p.\n", iface
, fontset
);
2731 return fontset_create_from_font_data(fontlist
->family
->collection
->factory
, fontlist
->fonts
,
2732 fontlist
->font_count
, fontset
);
2735 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2737 dwritefontlist_QueryInterface
,
2738 dwritefontlist_AddRef
,
2739 dwritefontlist_Release
,
2740 dwritefontlist_GetFontCollection
,
2741 dwritefontlist_GetFontCount
,
2742 dwritefontlist_GetFont
,
2743 dwritefontlist1_GetFontLocality
,
2744 dwritefontlist1_GetFont
,
2745 dwritefontlist1_GetFontFaceReference
,
2746 dwritefontlist2_GetFontSet
,
2749 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2751 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2753 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2755 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2756 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2757 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2758 IsEqualIID(riid
, &IID_IUnknown
))
2762 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2763 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2764 IsEqualIID(riid
, &IID_IDWriteFontList
))
2766 *obj
= &family
->IDWriteFontList2_iface
;
2770 WARN("%s not implemented.\n", debugstr_guid(riid
));
2772 return E_NOINTERFACE
;
2775 IUnknown_AddRef((IUnknown
*)*obj
);
2779 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2781 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2782 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2784 TRACE("%p, %lu.\n", iface
, refcount
);
2789 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2791 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2792 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2794 TRACE("%p, %lu.\n", iface
, refcount
);
2798 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2799 release_fontfamily_data(family
->data
);
2806 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2808 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2810 TRACE("%p, %p.\n", iface
, collection
);
2812 *collection
= (IDWriteFontCollection
*)&family
->collection
->IDWriteFontCollection3_iface
;
2813 IDWriteFontCollection_AddRef(*collection
);
2817 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2819 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2821 TRACE("%p.\n", iface
);
2823 return family
->data
->count
;
2826 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2828 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2830 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2834 if (!family
->data
->count
)
2837 if (index
>= family
->data
->count
)
2838 return E_INVALIDARG
;
2840 return create_font(family
, index
, (IDWriteFont3
**)font
);
2843 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2845 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2847 TRACE("%p, %p.\n", iface
, names
);
2849 return clone_localizedstrings(family
->data
->familyname
, names
);
2852 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2853 const struct dwrite_font_propvec
*req
)
2855 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2856 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2857 FLOAT cur_req_prod
, next_req_prod
;
2859 if (next_to_req
< cur_to_req
)
2862 if (next_to_req
> cur_to_req
)
2865 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2866 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2868 if (next_req_prod
> cur_req_prod
)
2871 if (next_req_prod
< cur_req_prod
)
2874 if (next
->stretch
> cur
->stretch
)
2876 if (next
->stretch
< cur
->stretch
)
2879 if (next
->style
> cur
->style
)
2881 if (next
->style
< cur
->style
)
2884 if (next
->weight
> cur
->weight
)
2886 if (next
->weight
< cur
->weight
)
2889 /* full match, no reason to prefer new variant */
2893 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2894 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2896 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2897 struct dwrite_font_propvec req
;
2900 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2902 if (!family
->data
->count
)
2905 return DWRITE_E_NOFONT
;
2908 init_font_prop_vec(weight
, stretch
, style
, &req
);
2911 for (i
= 1; i
< family
->data
->count
; ++i
)
2913 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2917 return create_font(family
, match
, (IDWriteFont3
**)font
);
2920 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2922 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2924 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2927 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2929 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2932 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2934 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2939 for (j
= 0; j
< b
; j
++) {
2940 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2941 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2942 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2943 fonts
->fonts
[j
+1] = s
;
2954 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2955 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2957 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2958 matching_filter_func func
= NULL
;
2959 struct dwrite_font_propvec req
;
2960 struct dwrite_fontlist
*fonts
;
2963 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2967 if (!(fonts
= malloc(sizeof(*fonts
))))
2968 return E_OUTOFMEMORY
;
2970 /* Allocate as many as family has, not all of them will be necessary used. */
2971 if (!(fonts
->fonts
= calloc(family
->data
->count
, sizeof(*fonts
->fonts
))))
2974 return E_OUTOFMEMORY
;
2977 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2978 fonts
->refcount
= 1;
2979 fonts
->family
= family
;
2980 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2981 fonts
->font_count
= 0;
2983 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2984 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2985 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2986 func
= is_font_acceptable_for_normal
;
2988 else /* requested oblique or italic */ {
2989 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2990 func
= is_font_acceptable_for_oblique_italic
;
2993 for (i
= 0; i
< family
->data
->count
; ++i
)
2995 if (!func
|| func(family
->data
->fonts
[i
]))
2997 fonts
->fonts
[fonts
->font_count
++] = addref_font_data(family
->data
->fonts
[i
]);
3001 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
3002 init_font_prop_vec(weight
, stretch
, style
, &req
);
3003 matchingfonts_sort(fonts
, &req
);
3005 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
3009 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
3011 FIXME("%p, %u.\n", iface
, index
);
3013 return DWRITE_LOCALITY_LOCAL
;
3016 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
3018 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
3020 TRACE("%p, %u, %p.\n", iface
, index
, font
);
3024 if (!family
->data
->count
)
3027 if (index
>= family
->data
->count
)
3030 return create_font(family
, index
, font
);
3033 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
3034 IDWriteFontFaceReference
**reference
)
3036 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
3037 const struct dwrite_font_data
*font
;
3039 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
3043 if (index
>= family
->data
->count
)
3046 font
= family
->data
->fonts
[index
];
3047 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
3048 font
->file
, font
->face_index
, font
->simulations
, reference
);
3051 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
3052 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
3054 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
3059 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
3061 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
3063 TRACE("%p, %p.\n", iface
, fontset
);
3065 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
3066 family
->data
->count
, fontset
);
3069 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
3071 dwritefontfamily_QueryInterface
,
3072 dwritefontfamily_AddRef
,
3073 dwritefontfamily_Release
,
3074 dwritefontfamily_GetFontCollection
,
3075 dwritefontfamily_GetFontCount
,
3076 dwritefontfamily_GetFont
,
3077 dwritefontfamily_GetFamilyNames
,
3078 dwritefontfamily_GetFirstMatchingFont
,
3079 dwritefontfamily_GetMatchingFonts
,
3080 dwritefontfamily1_GetFontLocality
,
3081 dwritefontfamily1_GetFont
,
3082 dwritefontfamily1_GetFontFaceReference
,
3083 dwritefontfamily2_GetMatchingFonts
,
3084 dwritefontfamily2_GetFontSet
,
3087 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
3089 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3090 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
3093 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
3095 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3096 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
3099 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
3101 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3102 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
3105 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
3106 IDWriteFontCollection
**collection
)
3108 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3109 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
3112 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
3114 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3115 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
3118 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
3120 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3121 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
3124 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
3126 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3127 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
3130 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
3132 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3133 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
3136 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
3137 IDWriteFontFaceReference
**reference
)
3139 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3140 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
3143 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
3145 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3147 TRACE("%p, %p.\n", iface
, fontset
);
3149 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
3150 family
->data
->count
, fontset
);
3153 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
3155 dwritefontfamilylist_QueryInterface
,
3156 dwritefontfamilylist_AddRef
,
3157 dwritefontfamilylist_Release
,
3158 dwritefontfamilylist_GetFontCollection
,
3159 dwritefontfamilylist_GetFontCount
,
3160 dwritefontfamilylist_GetFont
,
3161 dwritefontfamilylist1_GetFontLocality
,
3162 dwritefontfamilylist1_GetFont
,
3163 dwritefontfamilylist1_GetFontFaceReference
,
3164 dwritefontfamilylist2_GetFontSet
,
3167 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
3168 struct dwrite_fontfamily
**family
)
3170 struct dwrite_fontfamily
*object
;
3174 if (!(object
= calloc(1, sizeof(*object
))))
3175 return E_OUTOFMEMORY
;
3177 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
3178 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
3179 object
->refcount
= 1;
3180 object
->collection
= collection
;
3181 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
3182 object
->data
= collection
->family_data
[index
];
3183 InterlockedIncrement(&object
->data
->refcount
);
3190 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
3193 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
3196 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
3198 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3200 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
3202 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
3203 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
3204 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
3205 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
3206 IsEqualIID(riid
, &IID_IUnknown
))
3209 IDWriteFontCollection3_AddRef(iface
);
3215 if (IsEqualIID(riid
, &IID_issystemcollection
))
3218 WARN("%s not implemented.\n", debugstr_guid(riid
));
3220 return E_NOINTERFACE
;
3223 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
3225 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
3227 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
3228 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
3229 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
3230 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
3231 IsEqualIID(riid
, &IID_IUnknown
))
3234 IDWriteFontCollection3_AddRef(iface
);
3238 WARN("%s not implemented.\n", debugstr_guid(riid
));
3242 return E_NOINTERFACE
;
3245 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
3247 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3248 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
3250 TRACE("%p, refcount %ld.\n", collection
, refcount
);
3255 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
3257 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3258 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
3261 TRACE("%p, refcount %ld.\n", iface
, refcount
);
3265 factory_detach_fontcollection(collection
->factory
, iface
);
3266 for (i
= 0; i
< collection
->count
; ++i
)
3267 release_fontfamily_data(collection
->family_data
[i
]);
3268 free(collection
->family_data
);
3275 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
3277 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3279 TRACE("%p.\n", iface
);
3281 return collection
->count
;
3284 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3285 IDWriteFontFamily
**ret
)
3287 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3288 struct dwrite_fontfamily
*family
;
3291 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3295 if (index
>= collection
->count
)
3298 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3299 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
3304 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
3308 for (i
= 0; i
< collection
->count
; ++i
)
3310 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
3311 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
3314 for (j
= 0; j
< count
; j
++)
3317 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
3318 if (SUCCEEDED(hr
) && !wcsicmp(buffer
, name
))
3326 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
3327 UINT32
*index
, BOOL
*exists
)
3329 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3331 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
3333 *index
= collection_find_family(collection
, name
);
3334 *exists
= *index
!= ~0u;
3338 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
3341 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3342 struct dwrite_fontfamily
*family
;
3343 BOOL found_font
= FALSE
;
3344 IDWriteFontFile
*file
;
3345 UINT32 face_index
, count
;
3349 TRACE("%p, %p, %p.\n", iface
, face
, font
);
3354 return E_INVALIDARG
;
3357 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
3360 face_index
= IDWriteFontFace_GetIndex(face
);
3363 for (i
= 0; i
< collection
->count
; ++i
)
3365 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
3367 for (j
= 0; j
< family_data
->count
; ++j
)
3369 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
3371 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
3380 IDWriteFontFile_Release(file
);
3383 return DWRITE_E_NOFONT
;
3385 hr
= create_fontfamily(collection
, i
, &family
);
3389 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3390 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3394 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3396 FIXME("%p, %p.\n", iface
, fontset
);
3401 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3402 IDWriteFontFamily1
**ret
)
3404 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3405 struct dwrite_fontfamily
*family
;
3408 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3412 if (index
>= collection
->count
)
3415 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3416 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3421 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3422 UINT32 index
, IDWriteFontFamily2
**ret
)
3424 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3425 struct dwrite_fontfamily
*family
;
3428 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3432 if (index
>= collection
->count
)
3435 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3436 *ret
= &family
->IDWriteFontFamily2_iface
;
3441 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3442 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3443 IDWriteFontList2
**fontlist
)
3445 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3450 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3452 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3454 TRACE("%p.\n", iface
);
3456 return collection
->family_model
;
3459 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3461 FIXME("%p, %p.\n", iface
, fontset
);
3466 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3468 FIXME("%p.\n", iface
);
3473 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3475 dwritefontcollection_QueryInterface
,
3476 dwritefontcollection_AddRef
,
3477 dwritefontcollection_Release
,
3478 dwritefontcollection_GetFontFamilyCount
,
3479 dwritefontcollection_GetFontFamily
,
3480 dwritefontcollection_FindFamilyName
,
3481 dwritefontcollection_GetFontFromFontFace
,
3482 dwritefontcollection1_GetFontSet
,
3483 dwritefontcollection1_GetFontFamily
,
3484 dwritefontcollection2_GetFontFamily
,
3485 dwritefontcollection2_GetMatchingFonts
,
3486 dwritefontcollection2_GetFontFamilyModel
,
3487 dwritefontcollection2_GetFontSet
,
3488 dwritefontcollection3_GetExpirationEvent
,
3491 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3493 dwritesystemfontcollection_QueryInterface
,
3494 dwritefontcollection_AddRef
,
3495 dwritefontcollection_Release
,
3496 dwritefontcollection_GetFontFamilyCount
,
3497 dwritefontcollection_GetFontFamily
,
3498 dwritefontcollection_FindFamilyName
,
3499 dwritefontcollection_GetFontFromFontFace
,
3500 dwritefontcollection1_GetFontSet
,
3501 dwritefontcollection1_GetFontFamily
,
3502 dwritefontcollection2_GetFontFamily
,
3503 dwritefontcollection2_GetMatchingFonts
,
3504 dwritefontcollection2_GetFontFamilyModel
,
3505 dwritefontcollection2_GetFontSet
,
3506 dwritefontcollection3_GetExpirationEvent
,
3509 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3511 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3512 sizeof(*family_data
->fonts
)))
3514 return E_OUTOFMEMORY
;
3517 family_data
->fonts
[family_data
->count
++] = font_data
;
3518 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3519 family_data
->has_normal_face
= 1;
3520 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3521 family_data
->has_oblique_face
= 1;
3523 family_data
->has_italic_face
= 1;
3527 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3528 struct dwrite_fontfamily_data
*family
)
3530 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3531 sizeof(*collection
->family_data
)))
3533 return E_OUTOFMEMORY
;
3536 collection
->family_data
[collection
->count
++] = family
;
3540 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, IDWriteFactory7
*factory
,
3541 DWRITE_FONT_FAMILY_MODEL family_model
, BOOL is_system
)
3543 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3544 collection
->refcount
= 1;
3545 collection
->factory
= factory
;
3546 IDWriteFactory7_AddRef(collection
->factory
);
3547 collection
->family_model
= family_model
;
3552 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3554 IDWriteFontFileLoader
*loader
;
3561 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3565 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3569 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3570 IDWriteFontFileLoader_Release(loader
);
3577 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3579 BOOL exists
= FALSE
;
3584 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-us", &index
, &exists
);
3585 if (FAILED(hr
) || !exists
)
3588 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3591 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3595 while (iswspace(*in
))
3599 if (!(len
= wcslen(in
)))
3602 while (iswspace(in
[len
-1]))
3605 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3614 INT len
; /* token length */
3615 INT fulllen
; /* full length including following separators */
3618 static inline BOOL
is_name_separator_char(WCHAR ch
)
3620 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3623 struct name_pattern
{
3624 const WCHAR
*part1
; /* NULL indicates end of list */
3625 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3628 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3630 const struct name_pattern
*pattern
;
3631 struct name_token
*token
;
3634 while ((pattern
= &patterns
[i
++])->part1
)
3636 int len_part1
= wcslen(pattern
->part1
);
3637 int len_part2
= pattern
->part2
? wcslen(pattern
->part2
) : 0;
3639 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
)
3643 /* simple case with single part pattern */
3644 if (token
->len
!= len_part1
)
3647 if (!wcsnicmp(token
->ptr
, pattern
->part1
, len_part1
))
3649 if (match
) *match
= *token
;
3650 list_remove(&token
->entry
);
3657 struct name_token
*next_token
;
3658 struct list
*next_entry
;
3660 /* pattern parts are stored in reading order, tokens list is reversed */
3661 if (token
->len
< len_part2
)
3664 /* it's possible to have combined string as a token, like ExtraCondensed */
3665 if (token
->len
== len_part1
+ len_part2
)
3667 if (wcsnicmp(token
->ptr
, pattern
->part1
, len_part1
))
3670 if (wcsnicmp(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3673 /* combined string match */
3674 if (match
) *match
= *token
;
3675 list_remove(&token
->entry
);
3680 /* now it's only possible to have two tokens matched to respective pattern parts */
3681 if (token
->len
!= len_part2
)
3684 next_entry
= list_next(tokens
, &token
->entry
);
3686 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3687 if (next_token
->len
!= len_part1
)
3690 if (wcsnicmp(token
->ptr
, pattern
->part2
, len_part2
))
3693 if (wcsnicmp(next_token
->ptr
, pattern
->part1
, len_part1
))
3696 /* both parts matched, remove tokens */
3698 match
->ptr
= next_token
->ptr
;
3699 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3701 list_remove(&token
->entry
);
3702 list_remove(&next_token
->entry
);
3718 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3720 static const struct name_pattern italic_patterns
[] =
3730 static const struct name_pattern oblique_patterns
[] =
3740 /* italic patterns first */
3741 if (match_pattern_list(tokens
, italic_patterns
, match
))
3742 return DWRITE_FONT_STYLE_ITALIC
;
3744 /* oblique patterns */
3745 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3746 return DWRITE_FONT_STYLE_OBLIQUE
;
3751 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3752 struct name_token
*match
)
3754 static const struct name_pattern ultracondensed_patterns
[] =
3756 { L
"extra", L
"compressed" },
3757 { L
"ext", L
"compressed" },
3758 { L
"ultra", L
"compressed" },
3759 { L
"ultra", L
"condensed" },
3760 { L
"ultra", L
"cond" },
3764 static const struct name_pattern extracondensed_patterns
[] =
3767 { L
"extra", L
"condensed" },
3768 { L
"ext", L
"condensed" },
3769 { L
"extra", L
"cond" },
3770 { L
"ext", L
"cond" },
3774 static const struct name_pattern semicondensed_patterns
[] =
3778 { L
"semi", L
"condensed" },
3779 { L
"semi", L
"cond" },
3783 static const struct name_pattern semiexpanded_patterns
[] =
3786 { L
"semi", L
"expanded" },
3787 { L
"semi", L
"extended" },
3791 static const struct name_pattern extraexpanded_patterns
[] =
3793 { L
"extra", L
"expanded" },
3794 { L
"ext", L
"expanded" },
3795 { L
"extra", L
"extended" },
3796 { L
"ext", L
"extended" },
3800 static const struct name_pattern ultraexpanded_patterns
[] =
3802 { L
"ultra", L
"expanded" },
3803 { L
"ultra", L
"extended" },
3807 static const struct name_pattern condensed_patterns
[] =
3814 static const struct name_pattern expanded_patterns
[] =
3821 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3822 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3824 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3825 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3827 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3828 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3830 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3831 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3833 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3834 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3836 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3837 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3839 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3840 return DWRITE_FONT_STRETCH_CONDENSED
;
3842 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3843 return DWRITE_FONT_STRETCH_EXPANDED
;
3848 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3849 struct name_token
*match
)
3851 static const struct name_pattern thin_patterns
[] =
3853 { L
"extra", L
"thin" },
3854 { L
"ext", L
"thin" },
3855 { L
"ultra", L
"thin" },
3859 static const struct name_pattern extralight_patterns
[] =
3861 { L
"extra", L
"light" },
3862 { L
"ext", L
"light" },
3863 { L
"ultra", L
"light" },
3867 static const struct name_pattern semilight_patterns
[] =
3869 { L
"semi", L
"light" },
3873 static const struct name_pattern demibold_patterns
[] =
3875 { L
"semi", L
"bold" },
3876 { L
"demi", L
"bold" },
3880 static const struct name_pattern extrabold_patterns
[] =
3882 { L
"extra", L
"bold" },
3883 { L
"ext", L
"bold" },
3884 { L
"ultra", L
"bold" },
3888 static const struct name_pattern extrablack_patterns
[] =
3890 { L
"extra", L
"black" },
3891 { L
"ext", L
"black" },
3892 { L
"ultra", L
"black" },
3896 static const struct name_pattern bold_patterns
[] =
3902 static const struct name_pattern thin2_patterns
[] =
3908 static const struct name_pattern light_patterns
[] =
3914 static const struct name_pattern medium_patterns
[] =
3920 static const struct name_pattern black_patterns
[] =
3928 static const struct name_pattern demibold2_patterns
[] =
3934 static const struct name_pattern extrabold2_patterns
[] =
3940 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3941 matching pattern. */
3943 if (match_pattern_list(tokens
, thin_patterns
, match
))
3944 return DWRITE_FONT_WEIGHT_THIN
;
3946 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3947 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3949 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3950 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3952 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3953 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3955 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3956 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3958 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3959 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3961 if (match_pattern_list(tokens
, bold_patterns
, match
))
3962 return DWRITE_FONT_WEIGHT_BOLD
;
3964 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3965 return DWRITE_FONT_WEIGHT_THIN
;
3967 if (match_pattern_list(tokens
, light_patterns
, match
))
3968 return DWRITE_FONT_WEIGHT_LIGHT
;
3970 if (match_pattern_list(tokens
, medium_patterns
, match
))
3971 return DWRITE_FONT_WEIGHT_MEDIUM
;
3973 if (match_pattern_list(tokens
, black_patterns
, match
))
3974 return DWRITE_FONT_WEIGHT_BLACK
;
3976 if (match_pattern_list(tokens
, black_patterns
, match
))
3977 return DWRITE_FONT_WEIGHT_BLACK
;
3979 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3980 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3982 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3983 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3985 /* FIXME: use abbreviated names to extract weight */
3990 struct knownweight_entry
3993 DWRITE_FONT_WEIGHT weight
;
3996 static int __cdecl
compare_knownweights(const void *a
, const void* b
)
3998 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3999 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
4002 if (target
> entry
->weight
)
4004 else if (target
< entry
->weight
)
4010 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
4012 static const struct knownweight_entry knownweights
[] =
4014 { L
"Thin", DWRITE_FONT_WEIGHT_THIN
},
4015 { L
"Extra Light", DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
4016 { L
"Light", DWRITE_FONT_WEIGHT_LIGHT
},
4017 { L
"Semi Light", DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
4018 { L
"Medium", DWRITE_FONT_WEIGHT_MEDIUM
},
4019 { L
"Demi Bold", DWRITE_FONT_WEIGHT_DEMI_BOLD
},
4020 { L
"Bold", DWRITE_FONT_WEIGHT_BOLD
},
4021 { L
"Extra Bold", DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
4022 { L
"Black", DWRITE_FONT_WEIGHT_BLACK
},
4023 { L
"Extra Black", DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
4025 const struct knownweight_entry
*ptr
;
4027 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(*knownweights
),
4028 compare_knownweights
);
4034 wcscpy(nameW
, ptr
->nameW
);
4038 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
4040 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
4041 strW
[name
->len
] = 0;
4044 /* Modifies facenameW string, and returns pointer to regular term that was removed */
4045 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
4047 static const WCHAR
*regular_patterns
[] =
4057 const WCHAR
*regular_ptr
= NULL
, *ptr
;
4061 len
= wcslen(facenameW
);
4063 /* remove rightmost regular variant from face name */
4064 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++]))
4066 int pattern_len
= wcslen(ptr
);
4069 if (pattern_len
> len
)
4072 src
= facenameW
+ len
- pattern_len
;
4073 while (src
>= facenameW
)
4075 if (!wcsnicmp(src
, ptr
, pattern_len
))
4077 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
4078 len
= wcslen(facenameW
);
4090 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
4099 struct name_token
*token
= malloc(sizeof(*token
));
4104 while (*ptr
&& !is_name_separator_char(*ptr
)) {
4110 /* skip separators */
4111 while (is_name_separator_char(*ptr
)) {
4116 list_add_head(tokens
, &token
->entry
);
4120 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
4122 struct name_token
*token
, *token2
;
4123 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
4126 list_remove(&token
->entry
);
4128 /* don't include last separator */
4129 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
4130 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
4138 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
4140 struct name_token stretch_name
, weight_name
, style_name
;
4141 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
4142 WCHAR weightW
[32], stretchW
[32], styleW
[32];
4143 const WCHAR
*regular_ptr
= NULL
;
4144 DWRITE_FONT_STRETCH stretch
;
4145 DWRITE_FONT_WEIGHT weight
;
4149 /* remove leading and trailing spaces from family and face name */
4150 trim_spaces(familyW
, familynameW
);
4151 len
= trim_spaces(faceW
, facenameW
);
4153 /* remove rightmost regular variant from face name */
4154 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
4156 /* append face name to family name, FIXME check if face name is a substring of family name */
4159 wcscat(familynameW
, L
" ");
4160 wcscat(familynameW
, facenameW
);
4163 /* tokenize with " .-_" */
4164 fontname_tokenize(&tokens
, familynameW
);
4166 /* extract and resolve style */
4167 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
4169 /* extract stretch */
4170 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
4172 /* extract weight */
4173 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
4175 /* resolve weight */
4176 if (weight
!= font
->weight
)
4178 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
4179 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
4180 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
4181 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
4182 !(abs((int)weight
- (int)font
->weight
) <= 150 &&
4183 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
4184 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
4185 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
))
4187 font
->weight
= weight
;
4191 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
4192 it's leaning in opposite direction from normal comparing to specified stretch or if specified
4193 stretch itself is normal (extracted stretch is never normal). */
4194 if (stretch
!= font
->stretch
) {
4195 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
4196 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
4197 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
4199 font
->stretch
= stretch
;
4203 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
4205 /* get final combined string from what's left in token list, list is released */
4206 fontname_tokens_to_str(&tokens
, finalW
);
4208 if (!wcscmp(familyW
, finalW
))
4211 /* construct face name */
4212 wcscpy(familyW
, finalW
);
4214 /* resolved weight name */
4215 if (weight_name
.ptr
)
4216 font_name_token_to_str(&weight_name
, weightW
);
4217 /* ignore normal weight */
4218 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
4220 /* for known weight values use appropriate names */
4221 else if (is_known_weight_value(font
->weight
, weightW
)) {
4223 /* use Wnnn format as a fallback in case weight is not one of known values */
4225 swprintf(weightW
, ARRAY_SIZE(weightW
), L
"W%d", font
->weight
);
4227 /* resolved stretch name */
4228 if (stretch_name
.ptr
)
4229 font_name_token_to_str(&stretch_name
, stretchW
);
4230 /* ignore normal stretch */
4231 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
4233 /* use predefined stretch names */
4236 static const WCHAR
*stretchnamesW
[] =
4238 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4243 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
4249 wcscpy(stretchW
, stretchnamesW
[font
->stretch
]);
4252 /* resolved style name */
4254 font_name_token_to_str(&style_name
, styleW
);
4255 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
4257 /* use predefined names */
4259 wcscpy(styleW
, font
->style
== DWRITE_FONT_STYLE_ITALIC
? L
"Italic" : L
"Oblique");
4261 /* use Regular match if it was found initially */
4262 if (!*weightW
&& !*stretchW
&& !*styleW
)
4263 wcscpy(faceW
, regular_ptr
? regular_ptr
: L
"Regular");
4268 if (*stretchW
) wcscpy(faceW
, stretchW
);
4272 if (*faceW
) wcscat(faceW
, L
" ");
4273 wcscat(faceW
, weightW
);
4278 if (*faceW
) wcscat(faceW
, L
" ");
4279 wcscat(faceW
, styleW
);
4283 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
4287 static HRESULT
init_font_data(const struct fontface_desc
*desc
, DWRITE_FONT_FAMILY_MODEL family_model
,
4288 struct dwrite_font_data
**ret
)
4290 static const float width_axis_values
[] =
4292 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4293 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
4294 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
4295 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
4296 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
4297 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
4298 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
4299 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
4300 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
4301 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
4304 struct file_stream_desc stream_desc
;
4305 struct dwrite_font_props props
;
4306 struct dwrite_font_data
*data
;
4307 WCHAR familyW
[255], faceW
[255];
4312 if (!(data
= calloc(1, sizeof(*data
))))
4313 return E_OUTOFMEMORY
;
4316 data
->file
= desc
->file
;
4317 data
->face_index
= desc
->index
;
4318 data
->face_type
= desc
->face_type
;
4319 IDWriteFontFile_AddRef(data
->file
);
4321 stream_desc
.stream
= desc
->stream
;
4322 stream_desc
.face_type
= desc
->face_type
;
4323 stream_desc
.face_index
= desc
->index
;
4324 opentype_get_font_properties(&stream_desc
, &props
);
4325 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
4326 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
4328 if (FAILED(hr
= opentype_get_font_familyname(&stream_desc
, family_model
, &data
->family_names
)))
4330 WARN("Unable to get family name from the font file, hr %#lx.\n", hr
);
4331 release_font_data(data
);
4335 data
->style
= props
.style
;
4336 data
->stretch
= props
.stretch
;
4337 data
->weight
= props
.weight
;
4338 data
->panose
= props
.panose
;
4339 data
->fontsig
= props
.fontsig
;
4340 data
->lf
= props
.lf
;
4341 data
->flags
= props
.flags
;
4343 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4344 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
4346 if (family_model
== DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
4347 && font_apply_differentiation_rules(data
, familyW
, faceW
))
4349 set_en_localizedstring(data
->family_names
, familyW
);
4350 set_en_localizedstring(data
->names
, faceW
);
4353 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4355 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
4356 data
->axis
[0].value
= props
.weight
;
4357 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
4358 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
4359 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
4360 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
4366 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS simulations
,
4367 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
4369 struct dwrite_font_data
*data
;
4373 if (!(data
= calloc(1, sizeof(*data
))))
4374 return E_OUTOFMEMORY
;
4378 data
->simulations
|= simulations
;
4379 if (simulations
& DWRITE_FONT_SIMULATIONS_BOLD
)
4380 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
4381 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4382 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4383 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4385 IDWriteFontFile_AddRef(data
->file
);
4386 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4388 create_localizedstrings(&data
->names
);
4389 add_localizedstring(data
->names
, L
"en-us", facenameW
);
4391 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4397 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4399 struct dwrite_fontfamily_data
*data
;
4401 if (!(data
= calloc(1, sizeof(*data
))))
4402 return E_OUTOFMEMORY
;
4405 data
->familyname
= familyname
;
4406 IDWriteLocalizedStrings_AddRef(familyname
);
4413 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4415 size_t i
, j
, heaviest
;
4417 for (i
= 0; i
< family
->count
; ++i
)
4419 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4422 if (family
->fonts
[i
]->bold_sim_tested
)
4425 family
->fonts
[i
]->bold_sim_tested
= 1;
4426 for (j
= i
; j
< family
->count
; ++j
)
4428 if (family
->fonts
[j
]->bold_sim_tested
)
4431 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4432 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4433 if (family
->fonts
[j
]->weight
> weight
) {
4434 weight
= family
->fonts
[j
]->weight
;
4437 family
->fonts
[j
]->bold_sim_tested
= 1;
4441 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550)
4443 static const struct name_pattern weightsim_patterns
[] =
4445 { L
"extra", L
"light" },
4446 { L
"ext", L
"light" },
4447 { L
"ultra", L
"light" },
4448 { L
"semi", L
"light" },
4449 { L
"semi", L
"bold" },
4450 { L
"demi", L
"bold" },
4459 WCHAR facenameW
[255], initialW
[255];
4460 struct dwrite_font_data
*boldface
;
4463 /* add Bold simulation based on heaviest face data */
4465 /* Simulated face name should only contain Bold as weight term,
4466 so remove existing regular and weight terms. */
4467 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4468 facename_remove_regular_term(initialW
, -1);
4470 /* remove current weight pattern */
4471 fontname_tokenize(&tokens
, initialW
);
4472 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4473 fontname_tokens_to_str(&tokens
, facenameW
);
4475 /* Bold suffix for new name */
4476 if (*facenameW
) wcscat(facenameW
, L
" ");
4477 wcscat(facenameW
, L
"Bold");
4479 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4480 boldface
->bold_sim_tested
= 1;
4481 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4482 fontfamily_add_font(family
, boldface
);
4488 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4492 for (i
= 0; i
< family
->count
; ++i
)
4494 UINT32 regular
= ~0u, oblique
= ~0u;
4495 struct dwrite_font_data
*obliqueface
;
4496 WCHAR facenameW
[255];
4498 if (family
->fonts
[i
]->oblique_sim_tested
)
4501 family
->fonts
[i
]->oblique_sim_tested
= 1;
4502 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4504 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4507 /* find regular style with same weight/stretch values */
4508 for (j
= i
; j
< family
->count
; ++j
)
4510 if (family
->fonts
[j
]->oblique_sim_tested
)
4513 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4514 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4516 family
->fonts
[j
]->oblique_sim_tested
= 1;
4517 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4520 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4524 if (regular
!= ~0u && oblique
!= ~0u)
4528 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4532 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4536 /* add oblique simulation based on this regular face */
4538 /* remove regular term if any, append 'Oblique' */
4539 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4540 facename_remove_regular_term(facenameW
, -1);
4542 if (*facenameW
) wcscat(facenameW
, L
" ");
4543 wcscat(facenameW
, L
"Oblique");
4545 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4546 obliqueface
->oblique_sim_tested
= 1;
4547 obliqueface
->lf
.lfItalic
= 1;
4548 fontfamily_add_font(family
, obliqueface
);
4553 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4554 const WCHAR
*replacement_name
)
4556 UINT32 i
= collection_find_family(collection
, replacement_name
);
4557 struct dwrite_fontfamily_data
*target
;
4558 IDWriteLocalizedStrings
*strings
;
4561 /* replacement does not exist */
4565 hr
= create_localizedstrings(&strings
);
4569 /* add a new family with target name, reuse font data from replacement */
4570 add_localizedstring(strings
, L
"en-us", target_name
);
4571 hr
= init_fontfamily_data(strings
, &target
);
4573 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4576 for (i
= 0; i
< replacement
->count
; ++i
)
4578 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4579 addref_font_data(replacement
->fonts
[i
]);
4582 fontcollection_add_family(collection
, target
);
4583 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4584 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4586 IDWriteLocalizedStrings_Release(strings
);
4590 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4591 system font collections. */
4592 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4594 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4599 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4602 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4607 max_namelen
++; /* returned value doesn't include room for '\0' */
4608 name
= malloc(max_namelen
* sizeof(WCHAR
));
4609 data
= malloc(max_datalen
);
4611 datalen
= max_datalen
;
4612 namelen
= max_namelen
;
4613 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4614 if (collection_find_family(collection
, name
) == ~0u) {
4615 if (type
== REG_MULTI_SZ
) {
4616 WCHAR
*replacement
= data
;
4617 while (*replacement
) {
4618 if (fontcollection_add_replacement(collection
, name
, replacement
))
4620 replacement
+= wcslen(replacement
) + 1;
4623 else if (type
== REG_SZ
)
4624 fontcollection_add_replacement(collection
, name
, data
);
4627 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4629 datalen
= max_datalen
;
4630 namelen
= max_namelen
;
4638 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4639 IDWriteFontCollection3
**ret
)
4641 struct fontfile_enum
{
4643 IDWriteFontFile
*file
;
4645 struct fontfile_enum
*fileenum
, *fileenum2
;
4646 struct dwrite_fontcollection
*collection
;
4647 struct list scannedfiles
;
4648 BOOL current
= FALSE
;
4654 if (!(collection
= calloc(1, sizeof(*collection
))))
4655 return E_OUTOFMEMORY
;
4657 hr
= init_font_collection(collection
, factory
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
, is_system
);
4664 *ret
= &collection
->IDWriteFontCollection3_iface
;
4666 TRACE("building font collection:\n");
4668 list_init(&scannedfiles
);
4669 while (hr
== S_OK
) {
4670 DWRITE_FONT_FACE_TYPE face_type
;
4671 DWRITE_FONT_FILE_TYPE file_type
;
4672 BOOL supported
, same
= FALSE
;
4673 IDWriteFontFileStream
*stream
;
4674 IDWriteFontFile
*file
;
4678 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4679 if (FAILED(hr
) || !current
)
4682 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4686 /* check if we've scanned this file already */
4687 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4688 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4693 IDWriteFontFile_Release(file
);
4697 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4698 IDWriteFontFile_Release(file
);
4702 /* Unsupported formats are skipped. */
4703 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4704 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4705 TRACE("Unsupported font (%p, 0x%08lx, %d, %u)\n", file
, hr
, supported
, face_count
);
4706 IDWriteFontFileStream_Release(stream
);
4707 IDWriteFontFile_Release(file
);
4712 /* add to scanned list */
4713 fileenum
= malloc(sizeof(*fileenum
));
4714 fileenum
->file
= file
;
4715 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4717 for (i
= 0; i
< face_count
; ++i
)
4719 struct dwrite_font_data
*font_data
;
4720 struct fontface_desc desc
;
4724 desc
.factory
= factory
;
4725 desc
.face_type
= face_type
;
4727 desc
.stream
= stream
;
4729 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4730 desc
.font_data
= NULL
;
4732 /* Allocate an initialize new font data structure. */
4733 hr
= init_font_data(&desc
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
, &font_data
);
4736 /* move to next one */
4741 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4743 /* ignore dot named faces */
4744 if (familyW
[0] == '.')
4746 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4747 release_font_data(font_data
);
4751 index
= collection_find_family(collection
, familyW
);
4753 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4755 struct dwrite_fontfamily_data
*family_data
;
4757 /* create and init new family */
4758 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4760 /* add font to family, family - to collection */
4761 hr
= fontfamily_add_font(family_data
, font_data
);
4763 hr
= fontcollection_add_family(collection
, family_data
);
4766 release_fontfamily_data(family_data
);
4772 release_font_data(font_data
);
4777 IDWriteFontFileStream_Release(stream
);
4780 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
)
4782 IDWriteFontFile_Release(fileenum
->file
);
4783 list_remove(&fileenum
->entry
);
4787 for (i
= 0; i
< collection
->count
; ++i
)
4789 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4790 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4794 fontcollection_add_replacements(collection
);
4799 static HRESULT
collection_add_font_entry(struct dwrite_fontcollection
*collection
, const struct fontface_desc
*desc
)
4801 struct dwrite_font_data
*font_data
;
4806 if (FAILED(hr
= init_font_data(desc
, collection
->family_model
, &font_data
)))
4809 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4811 /* ignore dot named faces */
4812 if (familyW
[0] == '.')
4814 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4815 release_font_data(font_data
);
4819 index
= collection_find_family(collection
, familyW
);
4821 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4824 struct dwrite_fontfamily_data
*family_data
;
4826 /* Create and initialize new family */
4827 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4830 /* add font to family, family - to collection */
4831 hr
= fontfamily_add_font(family_data
, font_data
);
4833 hr
= fontcollection_add_family(collection
, family_data
);
4836 release_fontfamily_data(family_data
);
4841 release_font_data(font_data
);
4846 HRESULT
create_font_collection_from_set(IDWriteFactory7
*factory
, IDWriteFontSet
*fontset
,
4847 DWRITE_FONT_FAMILY_MODEL family_model
, REFGUID riid
, void **ret
)
4849 struct dwrite_fontset
*set
= unsafe_impl_from_IDWriteFontSet(fontset
);
4850 struct dwrite_fontcollection
*collection
;
4856 if (!(collection
= calloc(1, sizeof(*collection
))))
4857 return E_OUTOFMEMORY
;
4859 if (FAILED(hr
= init_font_collection(collection
, factory
, family_model
, FALSE
)))
4865 for (i
= 0; i
< set
->count
; ++i
)
4867 const struct dwrite_fontset_entry
*entry
= set
->entries
[i
];
4868 IDWriteFontFileStream
*stream
;
4869 struct fontface_desc desc
;
4871 if (FAILED(get_filestream_from_file(entry
->desc
.file
, &stream
)))
4873 WARN("Failed to get file stream.\n");
4877 desc
.factory
= factory
;
4878 desc
.face_type
= entry
->desc
.face_type
;
4879 desc
.file
= entry
->desc
.file
;
4880 desc
.stream
= stream
;
4881 desc
.index
= entry
->desc
.face_index
;
4882 desc
.simulations
= entry
->desc
.simulations
;
4883 desc
.font_data
= NULL
;
4885 if (FAILED(hr
= collection_add_font_entry(collection
, &desc
)))
4886 WARN("Failed to add font collection element, hr %#lx.\n", hr
);
4888 IDWriteFontFileStream_Release(stream
);
4891 if (family_model
== DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
)
4893 for (i
= 0; i
< collection
->count
; ++i
)
4895 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4896 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4900 hr
= IDWriteFontCollection3_QueryInterface(&collection
->IDWriteFontCollection3_iface
, riid
, ret
);
4901 IDWriteFontCollection3_Release(&collection
->IDWriteFontCollection3_iface
);
4906 struct system_fontfile_enumerator
4908 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4911 IDWriteFactory7
*factory
;
4916 DWORD filename_size
;
4919 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4921 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4924 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4926 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4927 IDWriteFontFileEnumerator_AddRef(iface
);
4932 WARN("%s not implemented.\n", debugstr_guid(riid
));
4936 return E_NOINTERFACE
;
4939 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4941 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4942 return InterlockedIncrement(&enumerator
->refcount
);
4945 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4947 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4948 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
4952 IDWriteFactory7_Release(enumerator
->factory
);
4953 RegCloseKey(enumerator
->hkey
);
4954 free(enumerator
->filename
);
4961 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4965 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4966 if (!wcschr(filename
, '\\'))
4968 WCHAR fullpathW
[MAX_PATH
];
4970 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4971 wcscat(fullpathW
, L
"\\fonts\\");
4972 wcscat(fullpathW
, filename
);
4974 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4977 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4982 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4984 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4988 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4991 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4994 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4996 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4997 WCHAR name_buf
[256], *name
= name_buf
;
4998 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
5003 enumerator
->index
++;
5005 /* iterate until we find next string value */
5008 name_count
= max_name_count
;
5009 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
5011 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
5012 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
5013 if (r
== ERROR_MORE_DATA
) {
5014 if (name_count
>= max_name_count
) {
5015 if (name
!= name_buf
) free(name
);
5016 max_name_count
*= 2;
5017 name
= malloc(max_name_count
* sizeof(*name
));
5018 if (!name
) return E_OUTOFMEMORY
;
5020 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
))
5022 free(enumerator
->filename
);
5023 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
5024 if (!(enumerator
->filename
= malloc(enumerator
->filename_size
)))
5031 } while (r
== ERROR_MORE_DATA
);
5033 if (r
!= ERROR_SUCCESS
) {
5034 enumerator
->filename
[0] = 0;
5037 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
5038 if (type
== REG_SZ
&& *name
!= '@') {
5042 enumerator
->index
++;
5044 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
5047 if (name
!= name_buf
) free(name
);
5051 static const IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
5053 systemfontfileenumerator_QueryInterface
,
5054 systemfontfileenumerator_AddRef
,
5055 systemfontfileenumerator_Release
,
5056 systemfontfileenumerator_MoveNext
,
5057 systemfontfileenumerator_GetCurrentFontFile
5060 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
5062 struct system_fontfile_enumerator
*enumerator
;
5066 if (!(enumerator
= calloc(1, sizeof(*enumerator
))))
5067 return E_OUTOFMEMORY
;
5069 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
5070 enumerator
->refcount
= 1;
5071 enumerator
->factory
= factory
;
5072 enumerator
->index
= -1;
5073 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
5074 enumerator
->filename
= malloc(enumerator
->filename_size
);
5075 if (!enumerator
->filename
)
5078 return E_OUTOFMEMORY
;
5081 IDWriteFactory7_AddRef(factory
);
5083 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 0,
5084 GENERIC_READ
, &enumerator
->hkey
))
5086 ERR("failed to open fonts list key\n");
5087 IDWriteFactory7_Release(factory
);
5088 free(enumerator
->filename
);
5093 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
5098 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, DWRITE_FONT_FAMILY_MODEL family_model
,
5099 IDWriteFontCollection
**collection
)
5101 IDWriteFontFileEnumerator
*enumerator
;
5102 IDWriteFontSet
*fontset
;
5107 if (family_model
== DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC
)
5109 if (SUCCEEDED(hr
= create_system_fontset(factory
, &IID_IDWriteFontSet
, (void **)&fontset
)))
5111 hr
= create_font_collection_from_set(factory
, fontset
, family_model
,
5112 &IID_IDWriteFontCollection
, (void **)collection
);
5113 IDWriteFontSet_Release(fontset
);
5118 if (SUCCEEDED(hr
= create_system_fontfile_enumerator(factory
, &enumerator
)))
5120 TRACE("Building system font collection for factory %p.\n", factory
);
5121 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
5122 IDWriteFontFileEnumerator_Release(enumerator
);
5129 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
5130 const WCHAR
*keynameW
, const WCHAR
*pathW
)
5132 struct dwrite_fontfamily_data
*family_data
;
5133 IDWriteLocalizedStrings
*names
;
5134 DWRITE_FONT_FACE_TYPE face_type
;
5135 DWRITE_FONT_FILE_TYPE file_type
;
5136 IDWriteFontFileStream
*stream
;
5137 IDWriteFontFile
*file
;
5138 UINT32 face_count
, i
;
5142 /* create font file from this path */
5143 hr
= create_local_file_reference(factory
, pathW
, &file
);
5147 if (FAILED(get_filestream_from_file(file
, &stream
))) {
5148 IDWriteFontFile_Release(file
);
5152 /* Unsupported formats are skipped. */
5153 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
5154 if (FAILED(hr
) || !supported
|| face_count
== 0) {
5155 TRACE("Unsupported font (%p, 0x%08lx, %d, %u)\n", file
, hr
, supported
, face_count
);
5156 IDWriteFontFileStream_Release(stream
);
5157 IDWriteFontFile_Release(file
);
5161 /* create and init new family */
5163 /* Family names are added for non-specific locale, represented with empty string.
5164 Default family appears with empty family name. */
5165 create_localizedstrings(&names
);
5166 if (!wcsicmp(keynameW
, L
"SystemDefaultEUDCFont"))
5167 add_localizedstring(names
, L
"", L
"");
5169 add_localizedstring(names
, L
"", keynameW
);
5171 hr
= init_fontfamily_data(names
, &family_data
);
5172 IDWriteLocalizedStrings_Release(names
);
5174 IDWriteFontFile_Release(file
);
5178 /* fill with faces */
5179 for (i
= 0; i
< face_count
; i
++) {
5180 struct dwrite_font_data
*font_data
;
5181 struct fontface_desc desc
;
5183 /* Allocate new font data structure. */
5184 desc
.factory
= factory
;
5185 desc
.face_type
= face_type
;
5188 desc
.stream
= stream
;
5189 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
5190 desc
.font_data
= NULL
;
5192 hr
= init_font_data(&desc
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
, &font_data
);
5196 /* add font to family */
5197 hr
= fontfamily_add_font(family_data
, font_data
);
5199 release_font_data(font_data
);
5202 /* add family to collection */
5203 hr
= fontcollection_add_family(collection
, family_data
);
5205 release_fontfamily_data(family_data
);
5206 IDWriteFontFileStream_Release(stream
);
5207 IDWriteFontFile_Release(file
);
5212 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
5214 struct dwrite_fontcollection
*collection
;
5215 WCHAR eudckeypathW
[16];
5223 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
5227 if (!(collection
= calloc(1, sizeof(*collection
))))
5228 return E_OUTOFMEMORY
;
5230 hr
= init_font_collection(collection
, factory
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
, FALSE
);
5237 *ret
= &collection
->IDWriteFontCollection3_iface
;
5239 /* return empty collection if EUDC fonts are not configured */
5240 swprintf(eudckeypathW
, ARRAY_SIZE(eudckeypathW
), L
"EUDC\\%u", GetACP());
5241 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
5244 retval
= ERROR_SUCCESS
;
5246 while (retval
!= ERROR_NO_MORE_ITEMS
) {
5247 WCHAR keynameW
[64], pathW
[MAX_PATH
];
5248 DWORD type
, path_len
, name_len
;
5250 path_len
= ARRAY_SIZE(pathW
);
5251 name_len
= ARRAY_SIZE(keynameW
);
5252 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
5253 if (retval
|| type
!= REG_SZ
)
5256 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
5258 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
5260 RegCloseKey(eudckey
);
5262 /* try to add global default if not defined for specific codepage */
5264 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, L
"",
5266 if (FAILED(hr
) || !exists
)
5268 hr
= eudc_collection_add_family(factory
, collection
, L
"", L
"EUDC.TTE");
5270 WARN("failed to add global default EUDC font, 0x%08lx\n", hr
);
5273 /* EUDC collection offers simulated faces too */
5274 for (i
= 0; i
< collection
->count
; ++i
)
5276 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
5277 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
5283 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
5285 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5287 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
5290 IDWriteFontFile_AddRef(iface
);
5294 WARN("%s not implemented.\n", debugstr_guid(riid
));
5297 return E_NOINTERFACE
;
5300 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
5302 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5303 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
5305 TRACE("%p, refcount %ld.\n", iface
, refcount
);
5310 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
5312 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5313 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
5315 TRACE("%p, refcount %ld.\n", iface
, refcount
);
5319 IDWriteFontFileLoader_Release(file
->loader
);
5321 IDWriteFontFileStream_Release(file
->stream
);
5322 free(file
->reference_key
);
5329 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
5331 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5333 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
5335 *key
= file
->reference_key
;
5336 *key_size
= file
->key_size
;
5341 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
5343 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5345 TRACE("%p, %p.\n", iface
, loader
);
5347 *loader
= file
->loader
;
5348 IDWriteFontFileLoader_AddRef(*loader
);
5353 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
5354 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
5356 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5357 IDWriteFontFileStream
*stream
;
5360 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
5362 *is_supported
= FALSE
;
5363 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
5365 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
5368 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
5372 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
5374 /* TODO: Further Analysis */
5375 IDWriteFontFileStream_Release(stream
);
5379 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
5381 dwritefontfile_QueryInterface
,
5382 dwritefontfile_AddRef
,
5383 dwritefontfile_Release
,
5384 dwritefontfile_GetReferenceKey
,
5385 dwritefontfile_GetLoader
,
5386 dwritefontfile_Analyze
,
5389 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
5390 IDWriteFontFile
**ret
)
5392 struct dwrite_fontfile
*file
;
5397 file
= calloc(1, sizeof(*file
));
5398 key
= malloc(key_size
);
5403 return E_OUTOFMEMORY
;
5406 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
5408 IDWriteFontFileLoader_AddRef(loader
);
5409 file
->loader
= loader
;
5410 file
->stream
= NULL
;
5411 file
->reference_key
= key
;
5412 memcpy(file
->reference_key
, reference_key
, key_size
);
5413 file
->key_size
= key_size
;
5415 *ret
= &file
->IDWriteFontFile_iface
;
5420 static UINT64
dwrite_fontface_get_font_object(struct dwrite_fontface
*fontface
)
5422 struct create_font_object_params create_params
;
5423 struct release_font_object_params release_params
;
5424 UINT64 font_object
, size
;
5425 const void *data_ptr
;
5428 if (!fontface
->font_object
&& SUCCEEDED(IDWriteFontFileStream_GetFileSize(fontface
->stream
, &size
)))
5430 if (SUCCEEDED(IDWriteFontFileStream_ReadFileFragment(fontface
->stream
, &data_ptr
, 0, size
, &data_context
)))
5432 create_params
.data
= data_ptr
;
5433 create_params
.size
= size
;
5434 create_params
.index
= fontface
->index
;
5435 create_params
.object
= &font_object
;
5437 UNIX_CALL(create_font_object
, &create_params
);
5441 WARN("Backend failed to create font object.\n");
5442 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, data_context
);
5446 if (!InterlockedCompareExchange64((LONGLONG
*)&fontface
->font_object
, font_object
, 0))
5448 fontface
->data_context
= data_context
;
5452 release_params
.object
= font_object
;
5453 UNIX_CALL(release_font_object
, &release_params
);
5454 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, data_context
);
5459 return fontface
->font_object
;
5462 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
5464 struct file_stream_desc stream_desc
;
5465 struct dwrite_font_data
*font_data
;
5466 struct dwrite_fontface
*fontface
;
5472 if (!(fontface
= calloc(1, sizeof(*fontface
))))
5473 return E_OUTOFMEMORY
;
5475 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
5476 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
5477 fontface
->refcount
= 1;
5478 fontface
->type
= desc
->face_type
;
5479 fontface
->vdmx
.exists
= TRUE
;
5480 fontface
->gasp
.exists
= TRUE
;
5481 fontface
->cpal
.exists
= TRUE
;
5482 fontface
->colr
.exists
= TRUE
;
5483 fontface
->kern
.exists
= TRUE
;
5484 fontface
->index
= desc
->index
;
5485 fontface
->simulations
= desc
->simulations
;
5486 fontface
->factory
= desc
->factory
;
5487 IDWriteFactory7_AddRef(fontface
->factory
);
5488 fontface
->file
= desc
->file
;
5489 IDWriteFontFile_AddRef(fontface
->file
);
5490 fontface
->stream
= desc
->stream
;
5491 IDWriteFontFileStream_AddRef(fontface
->stream
);
5492 InitializeCriticalSection(&fontface
->cs
);
5493 fontface_cache_init(fontface
);
5495 stream_desc
.stream
= fontface
->stream
;
5496 stream_desc
.face_type
= desc
->face_type
;
5497 stream_desc
.face_index
= desc
->index
;
5498 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
5499 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
5500 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
5501 /* TODO: test what happens if caret is already slanted */
5502 if (fontface
->caret
.slopeRise
== 1) {
5503 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
5504 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
5507 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
5509 /* Font properties are reused from font object when 'normal' face creation path is used:
5510 collection -> family -> matching font -> fontface.
5512 If face is created directly from factory we have to go through properties resolution.
5514 if (desc
->font_data
)
5516 font_data
= addref_font_data(desc
->font_data
);
5520 hr
= init_font_data(desc
, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
, &font_data
);
5523 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5528 fontface
->weight
= font_data
->weight
;
5529 fontface
->style
= font_data
->style
;
5530 fontface
->stretch
= font_data
->stretch
;
5531 fontface
->panose
= font_data
->panose
;
5532 fontface
->fontsig
= font_data
->fontsig
;
5533 fontface
->lf
= font_data
->lf
;
5534 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5535 fontface
->names
= font_data
->names
;
5536 if (fontface
->names
)
5537 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5538 fontface
->family_names
= font_data
->family_names
;
5539 if (fontface
->family_names
)
5540 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5541 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5542 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5544 if (fontface
->info_strings
[i
])
5545 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5547 fontface
->cmap
.stream
= fontface
->stream
;
5548 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5549 release_font_data(font_data
);
5551 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5552 fontface
->get_font_object
= dwrite_fontface_get_font_object
;
5554 *ret
= &fontface
->IDWriteFontFace5_iface
;
5559 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5566 struct local_cached_stream
5569 IDWriteFontFileStream
*stream
;
5570 struct local_refkey
*key
;
5574 struct dwrite_localfontfilestream
5576 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5579 struct local_cached_stream
*entry
;
5580 const void *file_ptr
;
5584 struct dwrite_localfontfileloader
5586 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5589 struct list streams
;
5590 CRITICAL_SECTION cs
;
5593 static struct dwrite_localfontfileloader local_fontfile_loader
;
5595 struct dwrite_inmemory_stream_data
5603 struct dwrite_inmemory_filestream
5605 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5608 struct dwrite_inmemory_stream_data
*data
;
5611 struct dwrite_inmemory_fileloader
5613 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5616 struct dwrite_inmemory_stream_data
**streams
;
5621 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5623 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5626 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5628 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5631 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5633 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5636 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5638 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5641 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5643 if (InterlockedDecrement(&stream
->refcount
) == 0)
5646 IUnknown_Release(stream
->owner
);
5653 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5655 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5657 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5659 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5660 IsEqualIID(riid
, &IID_IUnknown
))
5663 if (InterlockedIncrement(&stream
->refcount
) == 1)
5665 InterlockedDecrement(&stream
->refcount
);
5672 WARN("%s not implemented.\n", debugstr_guid(riid
));
5675 return E_NOINTERFACE
;
5678 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5680 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5681 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5683 TRACE_(dwrite_file
)("%p, refcount %ld.\n", iface
, refcount
);
5688 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5690 list_remove(&stream
->entry
);
5695 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5697 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5698 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5700 TRACE_(dwrite_file
)("%p, refcount %ld.\n", iface
, refcount
);
5704 UnmapViewOfFile(stream
->file_ptr
);
5706 EnterCriticalSection(&local_fontfile_loader
.cs
);
5707 release_cached_stream(stream
->entry
);
5708 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5716 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5717 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5719 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5721 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5722 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5724 *fragment_context
= NULL
;
5726 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5728 *fragment_start
= NULL
;
5732 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5736 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5738 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5741 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5743 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5745 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5747 *size
= stream
->size
;
5751 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5753 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5756 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5758 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5759 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5760 *last_writetime
= li
.QuadPart
;
5765 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5767 localfontfilestream_QueryInterface
,
5768 localfontfilestream_AddRef
,
5769 localfontfilestream_Release
,
5770 localfontfilestream_ReadFileFragment
,
5771 localfontfilestream_ReleaseFileFragment
,
5772 localfontfilestream_GetFileSize
,
5773 localfontfilestream_GetLastWriteTime
5776 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5777 IDWriteFontFileStream
**ret
)
5779 struct dwrite_localfontfilestream
*object
;
5783 if (!(object
= calloc(1, sizeof(*object
))))
5784 return E_OUTOFMEMORY
;
5786 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5787 object
->refcount
= 1;
5789 object
->file_ptr
= file_ptr
;
5790 object
->size
= size
;
5791 object
->entry
= entry
;
5793 *ret
= &object
->IDWriteFontFileStream_iface
;
5798 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5800 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5802 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5803 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5804 IsEqualIID(riid
, &IID_IUnknown
))
5807 IDWriteLocalFontFileLoader_AddRef(iface
);
5811 WARN("%s not implemented.\n", debugstr_guid(riid
));
5814 return E_NOINTERFACE
;
5817 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5819 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5820 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5822 TRACE("%p, refcount %ld.\n", iface
, refcount
);
5827 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5829 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5830 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5832 TRACE("%p, refcount %ld.\n", iface
, refcount
);
5837 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5839 const struct local_refkey
*refkey
= key
;
5840 struct local_cached_stream
*stream
;
5841 IDWriteFontFileStream
*filestream
;
5842 HANDLE file
, mapping
;
5849 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5850 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5851 if (file
== INVALID_HANDLE_VALUE
) {
5852 WARN_(dwrite_file
)("Failed to open the file %s, error %ld.\n", debugstr_w(refkey
->name
), GetLastError());
5856 GetFileSizeEx(file
, &size
);
5857 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5862 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5863 CloseHandle(mapping
);
5865 ERR("mapping failed, file size %s, error %ld\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5869 if (!(stream
= malloc(sizeof(*stream
))))
5871 UnmapViewOfFile(file_ptr
);
5872 return E_OUTOFMEMORY
;
5875 if (!(stream
->key
= malloc(key_size
)))
5877 UnmapViewOfFile(file_ptr
);
5879 return E_OUTOFMEMORY
;
5882 stream
->key_size
= key_size
;
5883 memcpy(stream
->key
, key
, key_size
);
5885 if (FAILED(hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
)))
5887 UnmapViewOfFile(file_ptr
);
5893 stream
->stream
= filestream
;
5900 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5901 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5903 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5904 struct local_cached_stream
*stream
;
5907 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5909 EnterCriticalSection(&loader
->cs
);
5913 /* search cache first */
5914 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5916 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5917 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5922 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5924 list_add_head(&loader
->streams
, &stream
->entry
);
5925 *ret
= stream
->stream
;
5928 LeaveCriticalSection(&loader
->cs
);
5933 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5934 UINT32 key_size
, UINT32
*length
)
5936 const struct local_refkey
*refkey
= key
;
5938 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5940 *length
= wcslen(refkey
->name
);
5944 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5945 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5947 const struct local_refkey
*refkey
= key
;
5949 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5951 if (length
< wcslen(refkey
->name
))
5952 return E_INVALIDARG
;
5954 wcscpy(path
, refkey
->name
);
5958 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5959 UINT32 key_size
, FILETIME
*writetime
)
5961 const struct local_refkey
*refkey
= key
;
5963 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5965 *writetime
= refkey
->writetime
;
5969 static const IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5971 localfontfileloader_QueryInterface
,
5972 localfontfileloader_AddRef
,
5973 localfontfileloader_Release
,
5974 localfontfileloader_CreateStreamFromKey
,
5975 localfontfileloader_GetFilePathLengthFromKey
,
5976 localfontfileloader_GetFilePathFromKey
,
5977 localfontfileloader_GetLastWriteTimeFromKey
5980 void init_local_fontfile_loader(void)
5982 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5983 local_fontfile_loader
.refcount
= 1;
5984 list_init(&local_fontfile_loader
.streams
);
5985 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5986 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5989 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5991 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5994 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5996 struct local_refkey
*refkey
;
5999 return E_INVALIDARG
;
6001 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (wcslen(path
)+1)*sizeof(WCHAR
);
6004 if (!(refkey
= malloc(*size
)))
6005 return E_OUTOFMEMORY
;
6008 refkey
->writetime
= *writetime
;
6010 WIN32_FILE_ATTRIBUTE_DATA info
;
6012 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
6013 refkey
->writetime
= info
.ftLastWriteTime
;
6015 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
6017 wcscpy(refkey
->name
, path
);
6024 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
6026 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6028 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
6029 IsEqualIID(riid
, &IID_IUnknown
))
6032 IDWriteGlyphRunAnalysis_AddRef(iface
);
6036 WARN("%s not implemented.\n", debugstr_guid(riid
));
6039 return E_NOINTERFACE
;
6042 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
6044 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6045 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
6047 TRACE("%p, refcount %ld.\n", iface
, refcount
);
6052 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
6054 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6055 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
6057 TRACE("%p, refcount %ld.\n", iface
, refcount
);
6061 if (analysis
->run
.fontFace
)
6062 IDWriteFontFace_Release(analysis
->run
.fontFace
);
6063 free(analysis
->glyphs
);
6064 free(analysis
->origins
);
6065 free(analysis
->bitmap
);
6072 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
6074 struct dwrite_glyphbitmap glyph_bitmap
;
6077 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
6078 *bounds
= analysis
->bounds
;
6082 if (analysis
->run
.isSideways
)
6083 FIXME("sideways runs are not supported.\n");
6085 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
6086 glyph_bitmap
.simulations
= IDWriteFontFace_GetSimulations(analysis
->run
.fontFace
);
6087 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
6088 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6089 glyph_bitmap
.m
= &analysis
->m
;
6091 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
6092 RECT
*bbox
= &glyph_bitmap
.bbox
;
6095 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
6096 dwrite_fontface_get_glyph_bbox(analysis
->run
.fontFace
, &glyph_bitmap
);
6098 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
6099 (bbox
->bottom
- bbox
->top
);
6100 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
6101 analysis
->max_glyph_bitmap_size
= bitmap_size
;
6103 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
6104 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
6107 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
6108 *bounds
= analysis
->bounds
;
6111 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
6112 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
6114 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6116 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
6118 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
6119 SetRectEmpty(bounds
);
6120 return E_INVALIDARG
;
6123 if (type
!= analysis
->texture_type
)
6125 SetRectEmpty(bounds
);
6129 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
6133 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
6135 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
6136 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
6137 (runbounds
->left
- bounds
->left
) * 3;
6139 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
6140 runbounds
->left
- bounds
->left
;
6143 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
6145 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
6146 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(analysis
->run
.fontFace
);
6147 struct dwrite_glyphbitmap glyph_bitmap
;
6148 D2D_POINT_2F origin
;
6152 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
6153 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
6155 if (!(analysis
->bitmap
= calloc(1, size
)))
6157 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
6158 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
6159 return E_OUTOFMEMORY
;
6162 origin
.x
= origin
.y
= 0.0f
;
6164 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
6165 glyph_bitmap
.simulations
= fontface
->simulations
;
6166 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
6167 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6168 glyph_bitmap
.m
= &analysis
->m
;
6169 if (!(glyph_bitmap
.buf
= malloc(analysis
->max_glyph_bitmap_size
)))
6170 return E_OUTOFMEMORY
;
6172 bbox
= &glyph_bitmap
.bbox
;
6174 for (i
= 0; i
< analysis
->run
.glyphCount
; ++i
)
6176 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
6177 int x
, y
, width
, height
;
6178 unsigned int is_1bpp
;
6180 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
6181 dwrite_fontface_get_glyph_bbox(analysis
->run
.fontFace
, &glyph_bitmap
);
6183 if (IsRectEmpty(bbox
))
6186 width
= bbox
->right
- bbox
->left
;
6187 height
= bbox
->bottom
- bbox
->top
;
6189 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
6190 memset(src
, 0, height
* glyph_bitmap
.pitch
);
6192 if (FAILED(dwrite_fontface_get_glyph_bitmap(fontface
, analysis
->rendering_mode
, &is_1bpp
, &glyph_bitmap
)))
6194 WARN("Failed to render glyph[%u] = %#x.\n", i
, glyph_bitmap
.glyph
);
6198 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
6200 /* blit to analysis bitmap */
6201 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
6204 /* convert 1bpp to 8bpp/24bpp */
6205 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
6206 for (y
= 0; y
< height
; y
++) {
6207 for (x
= 0; x
< width
; x
++)
6208 if (src
[x
/ 8] & masks
[x
% 8])
6209 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
6210 src
+= glyph_bitmap
.pitch
;
6211 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
6215 for (y
= 0; y
< height
; y
++) {
6216 for (x
= 0; x
< width
; x
++)
6217 if (src
[x
/ 8] & masks
[x
% 8])
6218 dst
[x
] = DWRITE_ALPHA_MAX
;
6219 src
+= glyph_bitmap
.pitch
;
6220 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
6225 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
6226 for (y
= 0; y
< height
; y
++) {
6227 for (x
= 0; x
< width
; x
++)
6228 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
6229 src
+= glyph_bitmap
.pitch
;
6230 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
6234 for (y
= 0; y
< height
; y
++) {
6235 for (x
= 0; x
< width
; x
++)
6237 src
+= glyph_bitmap
.pitch
;
6238 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
6243 free(glyph_bitmap
.buf
);
6245 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
6247 /* we don't need this anymore */
6248 free(analysis
->glyphs
);
6249 free(analysis
->origins
);
6250 IDWriteFontFace_Release(analysis
->run
.fontFace
);
6252 analysis
->glyphs
= NULL
;
6253 analysis
->origins
= NULL
;
6254 analysis
->run
.glyphIndices
= NULL
;
6255 analysis
->run
.fontFace
= NULL
;
6260 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
6261 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
6263 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6267 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
6269 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
6270 return E_INVALIDARG
;
6272 /* make sure buffer is large enough for requested texture type */
6273 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
6274 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
6277 if (size
< required
)
6278 return E_NOT_SUFFICIENT_BUFFER
;
6280 /* validate requested texture type */
6281 if (analysis
->texture_type
!= type
)
6282 return DWRITE_E_UNSUPPORTEDOPERATION
;
6284 memset(bitmap
, 0, size
);
6285 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
6286 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
6288 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
6289 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
6290 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
6291 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
6295 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
6299 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
6303 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
6304 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
6306 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
6307 memcpy(dst
, src
, draw_width
);
6316 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
6317 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
6319 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6321 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
6324 return E_INVALIDARG
;
6326 switch (analysis
->rendering_mode
)
6328 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
6329 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
6332 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
6333 *gamma
= (FLOAT
)value
/ 1000.0f
;
6335 *cleartypelevel
= 1.0f
;
6338 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
6339 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
6341 case DWRITE_RENDERING_MODE1_ALIASED
:
6342 case DWRITE_RENDERING_MODE1_NATURAL
:
6343 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
6344 *gamma
= IDWriteRenderingParams_GetGamma(params
);
6345 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
6346 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
6355 static const IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
6357 glyphrunanalysis_QueryInterface
,
6358 glyphrunanalysis_AddRef
,
6359 glyphrunanalysis_Release
,
6360 glyphrunanalysis_GetAlphaTextureBounds
,
6361 glyphrunanalysis_CreateAlphaTexture
,
6362 glyphrunanalysis_GetAlphaBlendParams
6365 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
6368 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
6369 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
6373 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
6374 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
6376 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
6380 FIXME("Sideways mode is not supported.\n");
6382 EnterCriticalSection(&fontface
->cs
);
6383 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
6384 LeaveCriticalSection(&fontface
->cs
);
6386 switch (measuring_mode
)
6388 case DWRITE_MEASURING_MODE_NATURAL
:
6389 return (float)advance
* emsize
/ (float)upem
;
6390 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
6391 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
6392 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
6394 WARN("Unknown measuring mode %u.\n", measuring_mode
);
6399 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
6401 struct dwrite_glyphrunanalysis
*analysis
;
6406 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
6407 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
6408 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
6409 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
6410 return E_INVALIDARG
;
6412 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6413 return E_INVALIDARG
;
6415 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
6416 return E_INVALIDARG
;
6418 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
6419 return E_INVALIDARG
;
6421 if (!(analysis
= calloc(1, sizeof(*analysis
))))
6422 return E_OUTOFMEMORY
;
6424 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
6425 analysis
->refcount
= 1;
6426 analysis
->rendering_mode
= desc
->rendering_mode
;
6428 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
6429 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6430 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
6432 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
6434 analysis
->run
= *desc
->run
;
6435 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
6436 analysis
->glyphs
= calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
6437 analysis
->origins
= calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
6439 if (!analysis
->glyphs
|| !analysis
->origins
)
6441 free(analysis
->glyphs
);
6442 free(analysis
->origins
);
6444 analysis
->glyphs
= NULL
;
6445 analysis
->origins
= NULL
;
6447 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
6448 return E_OUTOFMEMORY
;
6451 /* check if transform is usable */
6452 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
6453 analysis
->m
= *desc
->transform
;
6454 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
6457 analysis
->run
.glyphIndices
= analysis
->glyphs
;
6458 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
6460 compute_glyph_origins(desc
->run
, desc
->measuring_mode
, desc
->origin
, desc
->transform
, analysis
->origins
);
6461 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6463 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
6464 transform_point(&analysis
->origins
[i
], &analysis
->m
);
6467 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6471 /* IDWriteColorGlyphRunEnumerator1 */
6472 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6474 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6476 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6477 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6478 IsEqualIID(riid
, &IID_IUnknown
))
6481 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6485 WARN("%s not implemented.\n", debugstr_guid(riid
));
6488 return E_NOINTERFACE
;
6491 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6493 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6494 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6496 TRACE("%p, refcount %lu.\n", iface
, refcount
);
6501 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6503 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6504 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6506 TRACE("%p, refcount %lu.\n", iface
, refcount
);
6510 free(glyphenum
->advances
);
6511 free(glyphenum
->color_advances
);
6512 free(glyphenum
->offsets
);
6513 free(glyphenum
->color_offsets
);
6514 free(glyphenum
->glyphindices
);
6515 free(glyphenum
->glyphs
);
6516 if (glyphenum
->colr
.context
)
6517 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6518 IDWriteFontFace5_Release(glyphenum
->fontface
);
6525 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6527 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6528 FLOAT origin
= 0.0f
;
6534 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6538 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6540 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6541 FLOAT advance_adj
= 0.0f
;
6542 BOOL got_palette_index
;
6545 /* start with regular glyphs */
6546 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6547 UINT32 first_glyph
= 0;
6549 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6550 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6551 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6552 first_glyph
= min(first_glyph
, g
);
6555 glyphenum
->glyphindices
[g
] = 1;
6556 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6557 if (glyphenum
->color_offsets
)
6558 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6561 colorrun
->baselineOriginX
= glyphenum
->origin
.x
+ get_glyph_origin(glyphenum
, first_glyph
);
6562 colorrun
->baselineOriginY
= glyphenum
->origin
.y
;
6563 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6564 colorrun
->paletteIndex
= 0xffff;
6565 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6566 glyphenum
->has_regular_glyphs
= FALSE
;
6570 colorrun
->glyphRun
.glyphCount
= 0;
6571 got_palette_index
= FALSE
;
6575 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6577 glyphenum
->glyphindices
[g
] = 1;
6579 /* all glyph layers were returned */
6580 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6581 advance_adj
+= glyphenum
->advances
[g
];
6585 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6586 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6587 if (!got_palette_index
) {
6588 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6589 /* use foreground color or request one from the font */
6590 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6591 if (colorrun
->paletteIndex
!= 0xffff)
6593 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6594 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6596 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08lx\n", glyphenum
->fontface
,
6597 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6599 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6600 colorrun
->baselineOriginX
= glyphenum
->origin
.x
+ get_glyph_origin(glyphenum
, g
);
6601 colorrun
->baselineOriginY
= glyphenum
->origin
.y
;
6602 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6603 got_palette_index
= TRUE
;
6606 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6607 /* offsets are relative to glyph origin, nothing to fix up */
6608 if (glyphenum
->color_offsets
)
6609 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6610 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6612 glyphenum
->color_advances
[index
-1] += advance_adj
;
6613 colorrun
->glyphRun
.glyphCount
++;
6617 advance_adj
+= glyphenum
->advances
[g
];
6620 /* reset last advance */
6621 if (colorrun
->glyphRun
.glyphCount
)
6622 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6624 return colorrun
->glyphRun
.glyphCount
> 0;
6627 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6629 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6631 TRACE("%p, %p.\n", iface
, has_run
);
6635 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6636 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6638 if (colorglyphenum_build_color_run(glyphenum
))
6641 glyphenum
->current_layer
++;
6644 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6649 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6650 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6652 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6655 return E_NOT_VALID_STATE
;
6658 *run
= &glyphenum
->colorrun
;
6662 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6663 DWRITE_COLOR_GLYPH_RUN
const **run
)
6665 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6667 TRACE("%p, %p.\n", iface
, run
);
6669 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6672 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6673 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6675 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6677 TRACE("%p, %p.\n", iface
, run
);
6679 return colorglyphenum_get_current_run(glyphenum
, run
);
6682 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6684 colorglyphenum_QueryInterface
,
6685 colorglyphenum_AddRef
,
6686 colorglyphenum_Release
,
6687 colorglyphenum_MoveNext
,
6688 colorglyphenum_GetCurrentRun
,
6689 colorglyphenum1_GetCurrentRun
,
6692 HRESULT
create_colorglyphenum(D2D1_POINT_2F origin
, const DWRITE_GLYPH_RUN
*run
,
6693 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_GLYPH_IMAGE_FORMATS formats
, DWRITE_MEASURING_MODE measuring_mode
,
6694 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator1
**ret
)
6696 struct dwrite_colorglyphenum
*colorglyphenum
;
6697 BOOL colorfont
, has_colored_glyph
;
6698 struct dwrite_fontface
*fontface
;
6703 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6705 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6706 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6708 return DWRITE_E_NOCOLOR
;
6710 if (!(formats
& (DWRITE_GLYPH_IMAGE_FORMATS_COLR
|
6711 DWRITE_GLYPH_IMAGE_FORMATS_SVG
|
6712 DWRITE_GLYPH_IMAGE_FORMATS_PNG
|
6713 DWRITE_GLYPH_IMAGE_FORMATS_JPEG
|
6714 DWRITE_GLYPH_IMAGE_FORMATS_TIFF
|
6715 DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8
)))
6717 return DWRITE_E_NOCOLOR
;
6720 if (formats
& ~(DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
| DWRITE_GLYPH_IMAGE_FORMATS_CFF
| DWRITE_GLYPH_IMAGE_FORMATS_COLR
))
6722 FIXME("Unimplemented formats requested %#x.\n", formats
);
6726 if (!(colorglyphenum
= calloc(1, sizeof(*colorglyphenum
))))
6727 return E_OUTOFMEMORY
;
6729 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6730 colorglyphenum
->refcount
= 1;
6731 colorglyphenum
->origin
= origin
;
6732 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6733 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6734 colorglyphenum
->glyphs
= NULL
;
6735 colorglyphenum
->run
= *run
;
6736 colorglyphenum
->run
.glyphIndices
= NULL
;
6737 colorglyphenum
->run
.glyphAdvances
= NULL
;
6738 colorglyphenum
->run
.glyphOffsets
= NULL
;
6739 colorglyphenum
->palette
= palette
;
6740 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6741 colorglyphenum
->colr
.exists
= TRUE
;
6742 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6743 colorglyphenum
->current_layer
= 0;
6744 colorglyphenum
->max_layer_num
= 0;
6746 colorglyphenum
->glyphs
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphs
));
6748 has_colored_glyph
= FALSE
;
6749 colorglyphenum
->has_regular_glyphs
= FALSE
;
6750 for (i
= 0; i
< run
->glyphCount
; i
++) {
6751 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6752 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6753 has_colored_glyph
= TRUE
;
6755 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6756 colorglyphenum
->has_regular_glyphs
= TRUE
;
6759 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6760 is supposed to proceed normally, like if font had no color info at all. */
6761 if (!has_colored_glyph
) {
6762 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6763 return DWRITE_E_NOCOLOR
;
6766 colorglyphenum
->advances
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6767 colorglyphenum
->color_advances
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6768 colorglyphenum
->glyphindices
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6769 if (run
->glyphOffsets
) {
6770 colorglyphenum
->offsets
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6771 colorglyphenum
->color_offsets
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6772 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6775 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6776 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6777 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6778 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6779 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6780 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6781 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6782 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6784 if (run
->glyphAdvances
)
6785 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6788 for (i
= 0; i
< run
->glyphCount
; ++i
)
6789 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6790 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6793 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6798 /* IDWriteFontFaceReference */
6799 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6801 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6803 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6804 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6805 IsEqualIID(riid
, &IID_IUnknown
))
6808 IDWriteFontFaceReference1_AddRef(iface
);
6812 WARN("%s not implemented.\n", debugstr_guid(riid
));
6816 return E_NOINTERFACE
;
6819 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6821 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6822 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6824 TRACE("%p, refcount %lu.\n", iface
, refcount
);
6829 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6831 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6832 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6834 TRACE("%p, refcount %lu.\n", iface
, refcount
);
6838 IDWriteFontFile_Release(reference
->file
);
6839 IDWriteFactory7_Release(reference
->factory
);
6840 free(reference
->axis_values
);
6847 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6849 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6851 TRACE("%p, %p.\n", iface
, fontface
);
6853 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6856 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6857 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6859 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6860 DWRITE_FONT_FILE_TYPE file_type
;
6861 DWRITE_FONT_FACE_TYPE face_type
;
6862 IDWriteFontFace
*fontface
;
6867 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6869 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6873 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6874 simulations
, &fontface
);
6877 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6878 IDWriteFontFace_Release(fontface
);
6884 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6886 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6887 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6890 TRACE("%p, %p.\n", iface
, ref
);
6892 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6893 reference
->simulations
== other
->simulations
;
6894 if (reference
->axis_values_count
)
6896 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6897 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6903 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6905 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6907 TRACE("%p.\n", iface
);
6909 return reference
->index
;
6912 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6914 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6916 TRACE("%p.\n", iface
);
6918 return reference
->simulations
;
6921 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6923 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6924 IDWriteFontFileLoader
*loader
;
6929 TRACE("%p, %p.\n", iface
, file
);
6931 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6935 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6939 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6940 IDWriteFontFileLoader_Release(loader
);
6945 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6947 FIXME("%p.\n", iface
);
6952 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6954 FIXME("%p.\n", iface
);
6959 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6961 FIXME("%p, %p.\n", iface
, writetime
);
6966 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6968 FIXME("%p.\n", iface
);
6970 return DWRITE_LOCALITY_LOCAL
;
6973 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6975 FIXME("%p.\n", iface
);
6980 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6981 WCHAR
const *chars
, UINT32 count
)
6983 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6988 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6989 UINT16
const *glyphs
, UINT32 count
)
6991 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6996 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6997 UINT64 offset
, UINT64 size
)
6999 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
7004 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
7006 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
7007 IDWriteFontFace3
*fontface3
;
7010 TRACE("%p, %p.\n", iface
, fontface
);
7012 /* FIXME: created instance should likely respect given axis. */
7013 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
7016 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
7017 IDWriteFontFace3_Release(fontface3
);
7023 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
7025 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
7027 TRACE("%p.\n", iface
);
7029 return reference
->axis_values_count
;
7032 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
7033 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
7035 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
7037 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
7039 if (value_count
< reference
->axis_values_count
)
7040 return E_NOT_SUFFICIENT_BUFFER
;
7042 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
7047 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
7049 fontfacereference_QueryInterface
,
7050 fontfacereference_AddRef
,
7051 fontfacereference_Release
,
7052 fontfacereference_CreateFontFace
,
7053 fontfacereference_CreateFontFaceWithSimulations
,
7054 fontfacereference_Equals
,
7055 fontfacereference_GetFontFaceIndex
,
7056 fontfacereference_GetSimulations
,
7057 fontfacereference_GetFontFile
,
7058 fontfacereference_GetLocalFileSize
,
7059 fontfacereference_GetFileSize
,
7060 fontfacereference_GetFileTime
,
7061 fontfacereference_GetLocality
,
7062 fontfacereference_EnqueueFontDownloadRequest
,
7063 fontfacereference_EnqueueCharacterDownloadRequest
,
7064 fontfacereference_EnqueueGlyphDownloadRequest
,
7065 fontfacereference_EnqueueFileFragmentDownloadRequest
,
7066 fontfacereference1_CreateFontFace
,
7067 fontfacereference1_GetFontAxisValueCount
,
7068 fontfacereference1_GetFontAxisValues
,
7071 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
7072 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
7073 IDWriteFontFaceReference1
**ret
)
7075 struct dwrite_fontfacereference
*object
;
7079 if (!is_simulation_valid(simulations
))
7080 return E_INVALIDARG
;
7082 if (!(object
= calloc(1, sizeof(*object
))))
7083 return E_OUTOFMEMORY
;
7085 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
7086 object
->refcount
= 1;
7088 object
->factory
= factory
;
7089 IDWriteFactory7_AddRef(object
->factory
);
7090 object
->file
= file
;
7091 IDWriteFontFile_AddRef(object
->file
);
7092 object
->index
= index
;
7093 object
->simulations
= simulations
;
7094 if (axis_values_count
)
7096 if (!(object
->axis_values
= malloc(axis_values_count
* sizeof(*axis_values
))))
7098 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
7099 return E_OUTOFMEMORY
;
7101 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
7102 object
->axis_values_count
= axis_values_count
;
7105 *ret
= &object
->IDWriteFontFaceReference1_iface
;
7110 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
7112 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7114 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
7116 IDWriteFontFileStream_AddRef(iface
);
7122 WARN("%s not implemented.\n", debugstr_guid(riid
));
7123 return E_NOINTERFACE
;
7126 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
7128 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
7129 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
7131 TRACE_(dwrite_file
)("%p, refcount %lu.\n", iface
, refcount
);
7136 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
7138 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
7139 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
7141 TRACE_(dwrite_file
)("%p, refcount %lu.\n", iface
, refcount
);
7145 release_inmemory_stream(stream
->data
);
7152 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
7153 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
7155 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
7157 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
7158 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
7160 *fragment_context
= NULL
;
7162 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
7163 *fragment_start
= NULL
;
7167 *fragment_start
= (char *)stream
->data
->data
+ offset
;
7171 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
7173 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
7176 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
7178 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
7180 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
7182 *size
= stream
->data
->size
;
7187 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
7189 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
7191 *last_writetime
= 0;
7196 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
7197 inmemoryfilestream_QueryInterface
,
7198 inmemoryfilestream_AddRef
,
7199 inmemoryfilestream_Release
,
7200 inmemoryfilestream_ReadFileFragment
,
7201 inmemoryfilestream_ReleaseFileFragment
,
7202 inmemoryfilestream_GetFileSize
,
7203 inmemoryfilestream_GetLastWriteTime
,
7206 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
7207 REFIID riid
, void **obj
)
7209 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7211 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
7212 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
7213 IsEqualIID(riid
, &IID_IUnknown
))
7216 IDWriteInMemoryFontFileLoader_AddRef(iface
);
7220 WARN("%s not implemented.\n", debugstr_guid(riid
));
7224 return E_NOINTERFACE
;
7227 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
7229 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7230 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
7232 TRACE("%p, refcount %lu.\n", iface
, refcount
);
7237 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
7239 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7240 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
7243 TRACE("%p, refcount %lu.\n", iface
, refcount
);
7247 for (i
= 0; i
< loader
->count
; ++i
)
7248 release_inmemory_stream(loader
->streams
[i
]);
7249 free(loader
->streams
);
7256 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
7257 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
7259 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7260 struct dwrite_inmemory_filestream
*stream
;
7263 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
7267 if (key_size
!= sizeof(DWORD
))
7268 return E_INVALIDARG
;
7270 index
= *(DWORD
*)key
;
7272 if (index
>= loader
->count
)
7273 return E_INVALIDARG
;
7275 if (!(stream
= malloc(sizeof(*stream
))))
7276 return E_OUTOFMEMORY
;
7278 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
7279 stream
->refcount
= 1;
7280 stream
->data
= loader
->streams
[index
];
7281 InterlockedIncrement(&stream
->data
->refcount
);
7283 *ret
= &stream
->IDWriteFontFileStream_iface
;
7288 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
7289 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
7291 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7292 struct dwrite_inmemory_stream_data
*stream
;
7295 TRACE("%p, %p, %p, %u, %p, %p.\n", iface
, factory
, data
, data_size
, owner
, fontfile
);
7299 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
7300 return E_OUTOFMEMORY
;
7302 if (!(stream
= malloc(sizeof(*stream
))))
7303 return E_OUTOFMEMORY
;
7305 stream
->refcount
= 1;
7306 stream
->size
= data_size
;
7307 stream
->owner
= owner
;
7308 if (stream
->owner
) {
7309 IUnknown_AddRef(stream
->owner
);
7310 stream
->data
= (void *)data
;
7313 if (!(stream
->data
= malloc(data_size
)))
7316 return E_OUTOFMEMORY
;
7318 memcpy(stream
->data
, data
, data_size
);
7321 key
= loader
->count
;
7322 loader
->streams
[loader
->count
++] = stream
;
7324 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
7325 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
7328 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
7330 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7332 TRACE("%p.\n", iface
);
7334 return loader
->count
;
7337 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
7339 inmemoryfontfileloader_QueryInterface
,
7340 inmemoryfontfileloader_AddRef
,
7341 inmemoryfontfileloader_Release
,
7342 inmemoryfontfileloader_CreateStreamFromKey
,
7343 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
7344 inmemoryfontfileloader_GetFileCount
,
7347 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
7349 struct dwrite_inmemory_fileloader
*loader
;
7353 if (!(loader
= calloc(1, sizeof(*loader
))))
7354 return E_OUTOFMEMORY
;
7356 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
7357 loader
->refcount
= 1;
7359 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
7364 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
7366 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7368 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
7369 IsEqualIID(riid
, &IID_IUnknown
))
7372 IDWriteFontResource_AddRef(iface
);
7376 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7378 return E_NOINTERFACE
;
7381 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
7383 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7384 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
7386 TRACE("%p, refcount %lu.\n", iface
, refcount
);
7391 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
7393 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7394 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
7396 TRACE("%p, refcount %lu.\n", iface
, refcount
);
7400 IDWriteFactory7_Release(resource
->factory
);
7401 IDWriteFontFile_Release(resource
->file
);
7402 free(resource
->axis
);
7409 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
7411 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7413 TRACE("%p, %p.\n", iface
, fontfile
);
7415 *fontfile
= resource
->file
;
7416 IDWriteFontFile_AddRef(*fontfile
);
7421 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
7423 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7425 TRACE("%p.\n", iface
);
7427 return resource
->face_index
;
7430 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
7432 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7434 TRACE("%p.\n", iface
);
7436 return resource
->axis_count
;
7439 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
7440 DWRITE_FONT_AXIS_VALUE
*values
, UINT32 count
)
7442 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7445 TRACE("%p, %p, %u.\n", iface
, values
, count
);
7447 if (count
< resource
->axis_count
)
7448 return E_NOT_SUFFICIENT_BUFFER
;
7450 for (i
= 0; i
< resource
->axis_count
; ++i
)
7452 values
[i
].axisTag
= resource
->axis
[i
].tag
;
7453 values
[i
].value
= resource
->axis
[i
].default_value
;
7459 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
7460 DWRITE_FONT_AXIS_RANGE
*ranges
, UINT32 count
)
7462 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7465 TRACE("%p, %p, %u.\n", iface
, ranges
, count
);
7467 if (count
< resource
->axis_count
)
7468 return E_NOT_SUFFICIENT_BUFFER
;
7470 for (i
= 0; i
< resource
->axis_count
; ++i
)
7472 ranges
[i
].axisTag
= resource
->axis
[i
].tag
;
7473 ranges
[i
].minValue
= resource
->axis
[i
].min_value
;
7474 ranges
[i
].maxValue
= resource
->axis
[i
].max_value
;
7480 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7483 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7485 TRACE("%p, %u.\n", iface
, axis
);
7487 return axis
< resource
->axis_count
? resource
->axis
[axis
].attributes
: 0;
7490 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7491 IDWriteLocalizedStrings
**names
)
7493 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7498 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7500 FIXME("%p, %u.\n", iface
, axis
);
7505 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7506 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7508 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7513 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7515 FIXME("%p.\n", iface
);
7520 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7521 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7522 IDWriteFontFace5
**fontface
)
7524 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7525 IDWriteFontFaceReference1
*reference
;
7528 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7530 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7531 simulations
, axis_values
, num_values
, &reference
);
7534 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7535 IDWriteFontFaceReference1_Release(reference
);
7541 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7542 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7543 IDWriteFontFaceReference1
**reference
)
7545 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7547 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7549 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7550 simulations
, axis_values
, num_values
, reference
);
7553 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7555 dwritefontresource_QueryInterface
,
7556 dwritefontresource_AddRef
,
7557 dwritefontresource_Release
,
7558 dwritefontresource_GetFontFile
,
7559 dwritefontresource_GetFontFaceIndex
,
7560 dwritefontresource_GetFontAxisCount
,
7561 dwritefontresource_GetDefaultFontAxisValues
,
7562 dwritefontresource_GetFontAxisRanges
,
7563 dwritefontresource_GetFontAxisAttributes
,
7564 dwritefontresource_GetAxisNames
,
7565 dwritefontresource_GetAxisValueNameCount
,
7566 dwritefontresource_GetAxisValueNames
,
7567 dwritefontresource_HasVariations
,
7568 dwritefontresource_CreateFontFace
,
7569 dwritefontresource_CreateFontFaceReference
,
7572 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7573 IDWriteFontResource
**ret
)
7575 struct dwrite_fontresource
*resource
;
7576 struct file_stream_desc stream_desc
;
7577 DWRITE_FONT_FILE_TYPE file_type
;
7578 DWRITE_FONT_FACE_TYPE face_type
;
7579 unsigned int face_count
;
7580 BOOL supported
= FALSE
;
7585 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
)))
7589 return DWRITE_E_FILEFORMAT
;
7591 if (!(resource
= calloc(1, sizeof(*resource
))))
7592 return E_OUTOFMEMORY
;
7594 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7595 resource
->refcount
= 1;
7596 resource
->face_index
= face_index
;
7597 resource
->file
= file
;
7598 IDWriteFontFile_AddRef(resource
->file
);
7599 resource
->factory
= factory
;
7600 IDWriteFactory7_AddRef(resource
->factory
);
7602 get_filestream_from_file(file
, &stream_desc
.stream
);
7603 stream_desc
.face_type
= face_type
;
7604 stream_desc
.face_index
= face_index
;
7606 opentype_get_font_var_axis(&stream_desc
, &resource
->axis
, &resource
->axis_count
);
7608 if (stream_desc
.stream
)
7609 IDWriteFontFileStream_Release(stream_desc
.stream
);
7611 *ret
= &resource
->IDWriteFontResource_iface
;
7616 static HRESULT WINAPI
dwritefontset_QueryInterface(IDWriteFontSet3
*iface
, REFIID riid
, void **obj
)
7618 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7620 if (IsEqualIID(riid
, &IID_IDWriteFontSet3
) ||
7621 IsEqualIID(riid
, &IID_IDWriteFontSet2
) ||
7622 IsEqualIID(riid
, &IID_IDWriteFontSet1
) ||
7623 IsEqualIID(riid
, &IID_IDWriteFontSet
))
7626 IDWriteFontSet3_AddRef(iface
);
7630 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7632 return E_NOINTERFACE
;
7635 static ULONG WINAPI
dwritefontset_AddRef(IDWriteFontSet3
*iface
)
7637 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7638 ULONG refcount
= InterlockedIncrement(&set
->refcount
);
7640 TRACE("%p, refcount %lu.\n", iface
, refcount
);
7645 #define MISSING_SET_PROP ((void *)0x1)
7647 static void release_fontset_entry(struct dwrite_fontset_entry
*entry
)
7651 if (InterlockedDecrement(&entry
->refcount
) > 0)
7653 IDWriteFontFile_Release(entry
->desc
.file
);
7654 for (i
= 0; i
< ARRAY_SIZE(entry
->props
); ++i
)
7656 if (entry
->props
[i
] && entry
->props
[i
] != MISSING_SET_PROP
)
7657 IDWriteLocalizedStrings_Release(entry
->props
[i
]);
7662 static struct dwrite_fontset_entry
* addref_fontset_entry(struct dwrite_fontset_entry
*entry
)
7664 InterlockedIncrement(&entry
->refcount
);
7668 static IDWriteLocalizedStrings
* fontset_entry_get_property(struct dwrite_fontset_entry
*entry
,
7669 DWRITE_FONT_PROPERTY_ID property
)
7671 struct file_stream_desc stream_desc
= { 0 };
7672 IDWriteLocalizedStrings
*value
;
7674 assert(property
> DWRITE_FONT_PROPERTY_ID_NONE
&& property
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
);
7676 if (entry
->props
[property
] == MISSING_SET_PROP
)
7679 if ((value
= entry
->props
[property
]))
7681 IDWriteLocalizedStrings_AddRef(value
);
7685 get_filestream_from_file(entry
->desc
.file
, &stream_desc
.stream
);
7686 stream_desc
.face_type
= entry
->desc
.face_type
;
7687 stream_desc
.face_index
= entry
->desc
.face_index
;
7689 if (property
== DWRITE_FONT_PROPERTY_ID_FULL_NAME
)
7690 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_FULL_NAME
, &value
);
7691 else if (property
== DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
)
7692 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME
, &value
);
7693 else if (property
== DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
)
7694 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG
, &value
);
7695 else if (property
== DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
)
7696 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
, &value
);
7697 else if (property
== DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME
)
7698 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, &value
);
7700 WARN("Unsupported property %u.\n", property
);
7702 if (stream_desc
.stream
)
7703 IDWriteFontFileStream_Release(stream_desc
.stream
);
7707 entry
->props
[property
] = value
;
7708 IDWriteLocalizedStrings_AddRef(value
);
7711 entry
->props
[property
] = MISSING_SET_PROP
;
7716 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7717 struct dwrite_fontset_entry
**entries
, unsigned int count
);
7719 static ULONG WINAPI
dwritefontset_Release(IDWriteFontSet3
*iface
)
7721 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7722 ULONG refcount
= InterlockedDecrement(&set
->refcount
);
7725 TRACE("%p, refcount %lu.\n", iface
, refcount
);
7729 IDWriteFactory7_Release(set
->factory
);
7730 for (i
= 0; i
< set
->count
; ++i
)
7731 release_fontset_entry(set
->entries
[i
]);
7739 static UINT32 WINAPI
dwritefontset_GetFontCount(IDWriteFontSet3
*iface
)
7741 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7743 TRACE("%p.\n", iface
);
7748 static HRESULT WINAPI
dwritefontset_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7749 IDWriteFontFaceReference
**reference
)
7751 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7753 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
7757 if (index
>= set
->count
)
7758 return E_INVALIDARG
;
7760 return IDWriteFactory7_CreateFontFaceReference_(set
->factory
, set
->entries
[index
]->desc
.file
,
7761 set
->entries
[index
]->desc
.face_index
, set
->entries
[index
]->desc
.simulations
, reference
);
7764 static HRESULT WINAPI
dwritefontset_FindFontFaceReference(IDWriteFontSet3
*iface
,
7765 IDWriteFontFaceReference
*reference
, UINT32
*index
, BOOL
*exists
)
7767 FIXME("%p, %p, %p, %p.\n", iface
, reference
, index
, exists
);
7772 static HRESULT WINAPI
dwritefontset_FindFontFace(IDWriteFontSet3
*iface
, IDWriteFontFace
*fontface
,
7773 UINT32
*index
, BOOL
*exists
)
7775 FIXME("%p, %p, %p, %p.\n", iface
, fontface
, index
, exists
);
7780 static HRESULT WINAPI
dwritefontset_GetPropertyValues__(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7781 IDWriteStringList
**values
)
7783 FIXME("%p, %d, %p.\n", iface
, id
, values
);
7788 static HRESULT WINAPI
dwritefontset_GetPropertyValues_(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7789 WCHAR
const *preferred_locales
, IDWriteStringList
**values
)
7791 FIXME("%p, %d, %s, %p.\n", iface
, id
, debugstr_w(preferred_locales
), values
);
7796 static HRESULT WINAPI
dwritefontset_GetPropertyValues(IDWriteFontSet3
*iface
, UINT32 index
, DWRITE_FONT_PROPERTY_ID id
,
7797 BOOL
*exists
, IDWriteLocalizedStrings
**values
)
7799 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7801 TRACE("%p, %u, %d, %p, %p.\n", iface
, index
, id
, exists
, values
);
7803 if (!(id
> DWRITE_FONT_PROPERTY_ID_NONE
&& id
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
) ||
7804 index
>= set
->count
)
7808 return E_INVALIDARG
;
7811 *values
= fontset_entry_get_property(set
->entries
[index
], id
);
7812 *exists
= !!*values
;
7817 static HRESULT WINAPI
dwritefontset_GetPropertyOccurrenceCount(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7820 FIXME("%p, %p, %p.\n", iface
, property
, count
);
7825 static BOOL
fontset_entry_is_matching(struct dwrite_fontset_entry
*entry
, DWRITE_FONT_PROPERTY
const *props
,
7828 IDWriteLocalizedStrings
*value
;
7832 for (i
= 0; i
< count
; ++i
)
7834 switch (props
[i
].propertyId
)
7836 case DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
:
7837 case DWRITE_FONT_PROPERTY_ID_FULL_NAME
:
7838 case DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
:
7839 case DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
:
7840 case DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME
:
7841 if (!(value
= fontset_entry_get_property(entry
, props
[i
].propertyId
)))
7844 ret
= localizedstrings_contains(value
, props
[i
].propertyValue
);
7845 IDWriteLocalizedStrings_Release(value
);
7846 if (!ret
) return FALSE
;
7848 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
:
7849 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME
:
7850 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME
:
7851 case DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG
:
7852 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
7853 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
7854 case DWRITE_FONT_PROPERTY_ID_STYLE
:
7855 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
:
7856 FIXME("Unsupported property %d.\n", props
[i
].propertyId
);
7866 static HRESULT WINAPI
dwritefontset_GetMatchingFonts_(IDWriteFontSet3
*iface
, WCHAR
const *family
, DWRITE_FONT_WEIGHT weight
,
7867 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontSet
**fontset
)
7869 FIXME("%p, %s, %d, %d, %d, %p.\n", iface
, debugstr_w(family
), weight
, stretch
, style
, fontset
);
7874 static HRESULT WINAPI
dwritefontset_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
, UINT32 count
,
7875 IDWriteFontSet
**filtered_set
)
7877 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7878 struct dwrite_fontset_entry
**entries
;
7879 unsigned int i
, matched_count
= 0;
7880 struct dwrite_fontset
*object
;
7882 TRACE("%p, %p, %u, %p.\n", iface
, props
, count
, filtered_set
);
7884 if (!props
&& count
)
7885 return E_INVALIDARG
;
7887 if (!(object
= calloc(1, sizeof(*object
))))
7888 return E_OUTOFMEMORY
;
7890 if (!(entries
= calloc(set
->count
, sizeof(*entries
))))
7893 return E_OUTOFMEMORY
;
7896 for (i
= 0; i
< set
->count
; ++i
)
7898 if (fontset_entry_is_matching(set
->entries
[i
], props
, count
))
7900 entries
[matched_count
++] = addref_fontset_entry(set
->entries
[i
]);
7910 init_fontset(object
, set
->factory
, entries
, matched_count
);
7912 *filtered_set
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7917 static HRESULT WINAPI
dwritefontset1_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7918 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontSet1
**fontset
)
7920 FIXME("%p, %p, %p, %u, %p.\n", iface
, property
, axis_values
, num_values
, fontset
);
7925 static HRESULT WINAPI
dwritefontset1_GetFirstFontResources(IDWriteFontSet3
*iface
, IDWriteFontSet1
**fontset
)
7927 FIXME("%p, %p.\n", iface
, fontset
);
7932 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts__(IDWriteFontSet3
*iface
, UINT32
const *indices
,
7933 UINT32 num_indices
, IDWriteFontSet1
**fontset
)
7935 FIXME("%p, %p, %u, %p.\n", iface
, indices
, num_indices
, fontset
);
7940 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *axis_ranges
,
7941 UINT32 num_ranges
, BOOL select_any_range
, IDWriteFontSet1
**fontset
)
7943 FIXME("%p, %p, %u, %d, %p.\n", iface
, axis_ranges
, num_ranges
, select_any_range
, fontset
);
7948 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7949 UINT32 num_properties
, BOOL select_any_property
, IDWriteFontSet1
**fontset
)
7951 FIXME("%p, %p, %u, %d, %p.\n", iface
, props
, num_properties
, select_any_property
, fontset
);
7956 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *ranges
,
7957 UINT32 num_ranges
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7959 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, ranges
, num_ranges
, select_any_range
, indices
, num_indices
, actual_num_indices
);
7964 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7965 UINT32 num_properties
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7967 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, props
, num_properties
, select_any_range
, indices
,
7968 num_indices
, actual_num_indices
);
7973 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges_(IDWriteFontSet3
*iface
, UINT32 font_index
,
7974 DWRITE_FONT_AXIS_RANGE
*axis_ranges
, UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7976 FIXME("%p, %u, %p, %u, %p.\n", iface
, font_index
, axis_ranges
, num_ranges
, actual_num_ranges
);
7981 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
*axis_ranges
,
7982 UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7984 FIXME("%p, %p, %u, %p.\n", iface
, axis_ranges
, num_ranges
, actual_num_ranges
);
7989 static HRESULT WINAPI
dwritefontset1_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7990 IDWriteFontFaceReference1
**reference
)
7992 FIXME("%p, %u, %p.\n", iface
, index
, reference
);
7997 static HRESULT WINAPI
dwritefontset1_CreateFontResource(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontResource
**resource
)
7999 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
8001 TRACE("%p, %u, %p.\n", iface
, index
, resource
);
8005 if (index
>= set
->count
)
8006 return E_INVALIDARG
;
8008 return IDWriteFactory7_CreateFontResource(set
->factory
, set
->entries
[index
]->desc
.file
,
8009 set
->entries
[index
]->desc
.face_index
, resource
);
8012 static HRESULT WINAPI
dwritefontset1_CreateFontFace(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontFace5
**fontface
)
8014 FIXME("%p, %u, %p.\n", iface
, index
, fontface
);
8019 static DWRITE_LOCALITY WINAPI
dwritefontset1_GetFontLocality(IDWriteFontSet3
*iface
, UINT32 index
)
8021 FIXME("%p, %u.\n", iface
, index
);
8023 return DWRITE_LOCALITY_LOCAL
;
8026 static HANDLE WINAPI
dwritefontset2_GetExpirationEvent(IDWriteFontSet3
*iface
)
8028 FIXME("%p.\n", iface
);
8033 static DWRITE_FONT_SOURCE_TYPE WINAPI
dwritefontset3_GetFontSourceType(IDWriteFontSet3
*iface
, UINT32 index
)
8035 FIXME("%p, %u.\n", iface
, index
);
8037 return DWRITE_FONT_SOURCE_TYPE_UNKNOWN
;
8040 static UINT32 WINAPI
dwritefontset3_GetFontSourceNameLength(IDWriteFontSet3
*iface
, UINT32 index
)
8042 FIXME("%p, %u.\n", iface
, index
);
8047 static HRESULT WINAPI
dwritefontset3_GetFontSourceName(IDWriteFontSet3
*iface
, UINT32 index
, WCHAR
*buffer
, UINT32 buffer_size
)
8049 FIXME("%p, %u, %p, %u.\n", iface
, index
, buffer
, buffer_size
);
8054 static const IDWriteFontSet3Vtbl fontsetvtbl
=
8056 dwritefontset_QueryInterface
,
8057 dwritefontset_AddRef
,
8058 dwritefontset_Release
,
8059 dwritefontset_GetFontCount
,
8060 dwritefontset_GetFontFaceReference
,
8061 dwritefontset_FindFontFaceReference
,
8062 dwritefontset_FindFontFace
,
8063 dwritefontset_GetPropertyValues__
,
8064 dwritefontset_GetPropertyValues_
,
8065 dwritefontset_GetPropertyValues
,
8066 dwritefontset_GetPropertyOccurrenceCount
,
8067 dwritefontset_GetMatchingFonts_
,
8068 dwritefontset_GetMatchingFonts
,
8069 dwritefontset1_GetMatchingFonts
,
8070 dwritefontset1_GetFirstFontResources
,
8071 dwritefontset1_GetFilteredFonts__
,
8072 dwritefontset1_GetFilteredFonts_
,
8073 dwritefontset1_GetFilteredFonts
,
8074 dwritefontset1_GetFilteredFontIndices_
,
8075 dwritefontset1_GetFilteredFontIndices
,
8076 dwritefontset1_GetFontAxisRanges_
,
8077 dwritefontset1_GetFontAxisRanges
,
8078 dwritefontset1_GetFontFaceReference
,
8079 dwritefontset1_CreateFontResource
,
8080 dwritefontset1_CreateFontFace
,
8081 dwritefontset1_GetFontLocality
,
8082 dwritefontset2_GetExpirationEvent
,
8083 dwritefontset3_GetFontSourceType
,
8084 dwritefontset3_GetFontSourceNameLength
,
8085 dwritefontset3_GetFontSourceName
,
8088 static struct dwrite_fontset
*unsafe_impl_from_IDWriteFontSet(IDWriteFontSet
*iface
)
8092 assert(iface
->lpVtbl
== (IDWriteFontSetVtbl
*)&fontsetvtbl
);
8093 return CONTAINING_RECORD(iface
, struct dwrite_fontset
, IDWriteFontSet3_iface
);
8096 static HRESULT
fontset_create_entry(IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
,
8097 unsigned int face_index
, unsigned int simulations
, struct dwrite_fontset_entry
**ret
)
8099 struct dwrite_fontset_entry
*entry
;
8101 if (!(entry
= calloc(1, sizeof(*entry
))))
8102 return E_OUTOFMEMORY
;
8104 entry
->refcount
= 1;
8105 entry
->desc
.file
= file
;
8106 IDWriteFontFile_AddRef(entry
->desc
.file
);
8107 entry
->desc
.face_type
= face_type
;
8108 entry
->desc
.face_index
= face_index
;
8109 entry
->desc
.simulations
= simulations
;
8116 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
8117 struct dwrite_fontset_entry
**entries
, unsigned int count
)
8119 object
->IDWriteFontSet3_iface
.lpVtbl
= &fontsetvtbl
;
8120 object
->refcount
= 1;
8121 object
->factory
= factory
;
8122 IDWriteFactory7_AddRef(object
->factory
);
8123 object
->entries
= entries
;
8124 object
->count
= count
;
8127 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
8128 unsigned int count
, IDWriteFontSet1
**ret
)
8130 struct dwrite_fontset_entry
**entries
= NULL
;
8131 struct dwrite_fontset
*object
;
8134 if (!(object
= calloc(1, sizeof(*object
))))
8135 return E_OUTOFMEMORY
;
8139 entries
= calloc(count
, sizeof(*entries
));
8141 /* FIXME: set available properties too */
8143 for (i
= 0; i
< count
; ++i
)
8145 fontset_create_entry(fonts
[i
]->file
, fonts
[i
]->face_type
, fonts
[i
]->face_index
,
8146 fonts
[i
]->simulations
, &entries
[i
]);
8149 init_fontset(object
, factory
, entries
, count
);
8151 *ret
= (IDWriteFontSet1
*)&object
->IDWriteFontSet3_iface
;
8156 static HRESULT
fontset_builder_create_fontset(IDWriteFactory7
*factory
, struct dwrite_fontset_entry
**src_entries
,
8157 unsigned int count
, IDWriteFontSet
**ret
)
8159 struct dwrite_fontset_entry
**entries
= NULL
;
8160 struct dwrite_fontset
*object
;
8163 if (!(object
= calloc(1, sizeof(*object
))))
8164 return E_OUTOFMEMORY
;
8168 entries
= calloc(count
, sizeof(*entries
));
8170 for (i
= 0; i
< count
; ++i
)
8171 entries
[i
] = addref_fontset_entry(src_entries
[i
]);
8173 init_fontset(object
, factory
, entries
, count
);
8175 *ret
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
8180 static HRESULT WINAPI
dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2
*iface
,
8181 REFIID riid
, void **obj
)
8183 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
8185 if (IsEqualIID(riid
, &IID_IDWriteFontSetBuilder2
) ||
8186 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder1
) ||
8187 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder
) ||
8188 IsEqualIID(riid
, &IID_IUnknown
))
8191 IDWriteFontSetBuilder2_AddRef(iface
);
8195 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
8197 return E_NOINTERFACE
;
8200 static ULONG WINAPI
dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2
*iface
)
8202 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8203 ULONG refcount
= InterlockedIncrement(&builder
->refcount
);
8205 TRACE("%p, refcount %lu.\n", iface
, refcount
);
8210 static ULONG WINAPI
dwritefontsetbuilder_Release(IDWriteFontSetBuilder2
*iface
)
8212 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8213 ULONG refcount
= InterlockedDecrement(&builder
->refcount
);
8216 TRACE("%p, refcount %lu.\n", iface
, refcount
);
8220 IDWriteFactory7_Release(builder
->factory
);
8221 for (i
= 0; i
< builder
->count
; ++i
)
8222 release_fontset_entry(builder
->entries
[i
]);
8223 free(builder
->entries
);
8230 static HRESULT
fontset_builder_add_entry(struct dwrite_fontset_builder
*builder
, const struct dwrite_fontset_entry_desc
*desc
)
8232 struct dwrite_fontset_entry
*entry
;
8235 if (!dwrite_array_reserve((void **)&builder
->entries
, &builder
->capacity
, builder
->count
+ 1,
8236 sizeof(*builder
->entries
)))
8238 return E_OUTOFMEMORY
;
8241 if (FAILED(hr
= fontset_create_entry(desc
->file
, desc
->face_type
, desc
->face_index
, desc
->simulations
, &entry
)))
8244 builder
->entries
[builder
->count
++] = entry
;
8249 static HRESULT
fontset_builder_add_file(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
)
8251 struct dwrite_fontset_entry_desc desc
= { 0 };
8252 DWRITE_FONT_FILE_TYPE filetype
;
8253 unsigned int i
, face_count
;
8254 BOOL supported
= FALSE
;
8258 if (FAILED(hr
= IDWriteFontFile_Analyze(desc
.file
, &supported
, &filetype
, &desc
.face_type
, &face_count
)))
8262 return DWRITE_E_FILEFORMAT
;
8264 for (i
= 0; i
< face_count
; ++i
)
8266 desc
.face_index
= i
;
8267 if (FAILED(hr
= fontset_builder_add_entry(builder
, &desc
)))
8274 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2
*iface
,
8275 IDWriteFontFaceReference
*ref
, DWRITE_FONT_PROPERTY
const *props
, UINT32 prop_count
)
8277 FIXME("%p, %p, %p, %u.\n", iface
, ref
, props
, prop_count
);
8282 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2
*iface
,
8283 IDWriteFontFaceReference
*reference
)
8285 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8286 struct dwrite_fontset_entry_desc desc
= { 0 };
8287 DWRITE_FONT_FILE_TYPE file_type
;
8288 unsigned int face_count
;
8292 TRACE("%p, %p.\n", iface
, reference
);
8294 if (FAILED(hr
= IDWriteFontFaceReference_GetFontFile(reference
, &desc
.file
))) return hr
;
8296 if (SUCCEEDED(hr
= IDWriteFontFile_Analyze(desc
.file
, &supported
, &file_type
, &desc
.face_type
, &face_count
)))
8299 hr
= DWRITE_E_FILEFORMAT
;
8303 desc
.face_index
= IDWriteFontFaceReference_GetFontFaceIndex(reference
);
8304 desc
.simulations
= IDWriteFontFaceReference_GetSimulations(reference
);
8305 hr
= fontset_builder_add_entry(builder
, &desc
);
8309 IDWriteFontFile_Release(desc
.file
);
8314 static HRESULT WINAPI
dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
*fontset
)
8316 FIXME("%p, %p.\n", iface
, fontset
);
8321 static HRESULT WINAPI
dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
**fontset
)
8323 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8325 TRACE("%p, %p.\n", iface
, fontset
);
8327 return fontset_builder_create_fontset(builder
->factory
, builder
->entries
, builder
->count
, fontset
);
8330 static HRESULT WINAPI
dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
)
8332 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8334 TRACE("%p, %p.\n", iface
, file
);
8336 return fontset_builder_add_file(builder
, file
);
8339 static HRESULT WINAPI
dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
,
8340 unsigned int face_index
, DWRITE_FONT_SIMULATIONS simulations
, const DWRITE_FONT_AXIS_VALUE
*axis_values
,
8341 unsigned int num_values
, const DWRITE_FONT_AXIS_RANGE
*axis_ranges
, unsigned int num_ranges
,
8342 const DWRITE_FONT_PROPERTY
*props
, unsigned int num_properties
)
8344 FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface
, file
, face_index
, simulations
, axis_values
, num_values
,
8345 axis_ranges
, num_ranges
, props
, num_properties
);
8350 static HRESULT WINAPI
dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2
*iface
, const WCHAR
*filepath
)
8352 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8353 IDWriteFontFile
*file
;
8356 TRACE("%p, %s.\n", iface
, debugstr_w(filepath
));
8358 if (FAILED(hr
= IDWriteFactory7_CreateFontFileReference(builder
->factory
, filepath
, NULL
, &file
)))
8361 hr
= fontset_builder_add_file(builder
, file
);
8362 IDWriteFontFile_Release(file
);
8366 static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl
=
8368 dwritefontsetbuilder_QueryInterface
,
8369 dwritefontsetbuilder_AddRef
,
8370 dwritefontsetbuilder_Release
,
8371 dwritefontsetbuilder_AddFontFaceReference_
,
8372 dwritefontsetbuilder_AddFontFaceReference
,
8373 dwritefontsetbuilder_AddFontSet
,
8374 dwritefontsetbuilder_CreateFontSet
,
8375 dwritefontsetbuilder1_AddFontFile
,
8376 dwritefontsetbuilder2_AddFont
,
8377 dwritefontsetbuilder2_AddFontFile
,
8380 HRESULT
create_fontset_builder(IDWriteFactory7
*factory
, IDWriteFontSetBuilder2
**ret
)
8382 struct dwrite_fontset_builder
*builder
;
8386 if (!(builder
= calloc(1, sizeof(*builder
))))
8387 return E_OUTOFMEMORY
;
8389 builder
->IDWriteFontSetBuilder2_iface
.lpVtbl
= &fontsetbuildervtbl
;
8390 builder
->refcount
= 1;
8391 builder
->factory
= factory
;
8392 IDWriteFactory7_AddRef(builder
->factory
);
8394 *ret
= &builder
->IDWriteFontSetBuilder2_iface
;