4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2017 Nikolay Sivov for CodeWeavers
6 * Copyright 2014 Aric Stewart for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "dwrite_private.h"
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 struct dwrite_fontfamily_data
**family_data
;
341 struct dwrite_fontfamily
343 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
344 IDWriteFontList2 IDWriteFontList2_iface
;
347 struct dwrite_fontfamily_data
*data
;
348 struct dwrite_fontcollection
*collection
;
351 struct dwrite_fontlist
353 IDWriteFontList2 IDWriteFontList2_iface
;
356 struct dwrite_font_data
**fonts
;
358 struct dwrite_fontfamily
*family
;
363 IDWriteFont3 IDWriteFont3_iface
;
366 DWRITE_FONT_STYLE style
;
367 struct dwrite_font_data
*data
;
368 struct dwrite_fontfamily
*family
;
371 enum runanalysis_flags
{
372 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
373 RUNANALYSIS_BITMAP_READY
= 1 << 1,
374 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
377 struct dwrite_glyphrunanalysis
379 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
382 DWRITE_RENDERING_MODE1 rendering_mode
;
383 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
384 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
387 D2D_POINT_2F
*origins
;
392 UINT32 max_glyph_bitmap_size
;
395 struct dwrite_colorglyphenum
397 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
400 FLOAT origin_x
; /* 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 #define GLYPH_BLOCK_SHIFT 8
420 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
421 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
422 #define GLYPH_MAX 65536
424 struct dwrite_fontfile
426 IDWriteFontFile IDWriteFontFile_iface
;
429 IDWriteFontFileLoader
*loader
;
432 IDWriteFontFileStream
*stream
;
435 struct dwrite_fontfacereference
437 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
440 IDWriteFontFile
*file
;
443 DWRITE_FONT_AXIS_VALUE
*axis_values
;
444 UINT32 axis_values_count
;
445 IDWriteFactory7
*factory
;
448 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
450 struct dwrite_fontresource
452 IDWriteFontResource IDWriteFontResource_iface
;
455 IDWriteFontFile
*file
;
457 IDWriteFactory7
*factory
;
460 struct dwrite_fontset_entry
463 IDWriteFontFile
*file
;
464 DWRITE_FONT_FACE_TYPE face_type
;
465 unsigned int face_index
;
466 unsigned int simulations
;
467 IDWriteLocalizedStrings
*props
[DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
+ 1];
470 struct dwrite_fontset
472 IDWriteFontSet3 IDWriteFontSet3_iface
;
474 IDWriteFactory7
*factory
;
476 struct dwrite_fontset_entry
**entries
;
480 struct dwrite_fontset_builder
482 IDWriteFontSetBuilder2 IDWriteFontSetBuilder2_iface
;
484 IDWriteFactory7
*factory
;
486 struct dwrite_fontset_entry
**entries
;
491 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
492 unsigned int count
, IDWriteFontSet1
**ret
);
494 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
496 struct dwrite_fontface
*fontface
= context
;
499 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
500 size
, data_context
, &exists
)) || !exists
)
504 *data_context
= NULL
;
508 static void dwrite_release_font_table(void *context
, void *data_context
)
510 struct dwrite_fontface
*fontface
= context
;
511 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
514 static UINT16
dwrite_get_font_upem(void *context
)
516 struct dwrite_fontface
*fontface
= context
;
517 return fontface
->metrics
.designUnitsPerEm
;
520 static UINT16
dwritefontface_get_glyph(struct dwrite_fontface
*fontface
, unsigned int ch
)
522 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
523 return opentype_cmap_get_glyph(&fontface
->cmap
, ch
);
526 static BOOL
dwrite_has_glyph(void *context
, unsigned int codepoint
)
528 struct dwrite_fontface
*fontface
= context
;
529 return !!dwritefontface_get_glyph(fontface
, codepoint
);
532 static UINT16
dwrite_get_glyph(void *context
, unsigned int codepoint
)
534 struct dwrite_fontface
*fontface
= context
;
535 return dwritefontface_get_glyph(fontface
, codepoint
);
538 static const struct shaping_font_ops dwrite_font_ops
=
540 dwrite_grab_font_table
,
541 dwrite_release_font_table
,
542 dwrite_get_font_upem
,
547 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
549 if (fontface
->shaping_cache
)
550 return fontface
->shaping_cache
;
552 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
555 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
557 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
560 static struct dwrite_fontface
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
562 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFaceReference_iface
);
565 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
567 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
570 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
);
572 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
574 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
577 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
579 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
582 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
584 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
587 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
589 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
592 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
594 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
597 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
599 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
602 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
604 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
607 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
609 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
612 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
614 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
617 static struct dwrite_fontset_builder
*impl_from_IDWriteFontSetBuilder2(IDWriteFontSetBuilder2
*iface
)
619 return CONTAINING_RECORD(iface
, struct dwrite_fontset_builder
, IDWriteFontSetBuilder2_iface
);
622 static struct dwrite_fontset
*impl_from_IDWriteFontSet3(IDWriteFontSet3
*iface
)
624 return CONTAINING_RECORD(iface
, struct dwrite_fontset
, IDWriteFontSet3_iface
);
627 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
629 static const DWRITE_GLYPH_METRICS nil
;
630 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
632 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
633 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
637 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
639 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
643 /* start new block */
644 if (!(*block
= calloc(GLYPH_BLOCK_SIZE
, sizeof(*metrics
))))
645 return E_OUTOFMEMORY
;
648 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
652 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
656 if (table
->data
|| !table
->exists
)
659 table
->exists
= FALSE
;
660 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
662 if (FAILED(hr
) || !table
->exists
) {
663 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
670 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
671 struct dwrite_font_propvec
*vec
)
673 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
674 vec
->style
= style
* 7.0f
;
675 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
678 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
680 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
683 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
685 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
688 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
690 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
691 return &fontface
->vdmx
;
694 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
696 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
697 return &fontface
->gasp
;
700 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
702 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
703 return &fontface
->cpal
;
706 static struct dwrite_font_data
* addref_font_data(struct dwrite_font_data
*data
)
708 InterlockedIncrement(&data
->refcount
);
712 static void release_font_data(struct dwrite_font_data
*data
)
716 if (InterlockedDecrement(&data
->refcount
) > 0)
719 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
721 if (data
->info_strings
[i
])
722 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
725 IDWriteLocalizedStrings_Release(data
->names
);
727 if (data
->family_names
)
728 IDWriteLocalizedStrings_Release(data
->family_names
);
730 dwrite_cmap_release(&data
->cmap
);
731 IDWriteFontFile_Release(data
->file
);
732 free(data
->facename
);
736 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
740 if (InterlockedDecrement(&data
->refcount
) > 0)
743 for (i
= 0; i
< data
->count
; ++i
)
744 release_font_data(data
->fonts
[i
]);
746 IDWriteLocalizedStrings_Release(data
->familyname
);
750 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
752 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
753 fontface
->cached
= NULL
;
756 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
758 UINT32 left_key_size
, right_key_size
;
759 const void *left_key
, *right_key
;
765 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
769 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
773 if (left_key_size
!= right_key_size
)
776 return !memcmp(left_key
, right_key
, left_key_size
);
779 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
781 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
783 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
785 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
786 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
787 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
788 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
789 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
790 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
791 IsEqualIID(riid
, &IID_IUnknown
))
795 else if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
))
796 *obj
= &fontface
->IDWriteFontFaceReference_iface
;
802 if (InterlockedIncrement(&fontface
->refcount
) == 1)
804 InterlockedDecrement(&fontface
->refcount
);
811 WARN("%s not implemented.\n", debugstr_guid(riid
));
813 return E_NOINTERFACE
;
816 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
818 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
819 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
821 TRACE("%p, refcount %u.\n", iface
, refcount
);
826 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
828 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
829 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
830 struct release_font_object_params params
= { fontface
->font_object
};
832 TRACE("%p, refcount %u.\n", iface
, refcount
);
838 if (fontface
->cached
)
840 factory_lock(fontface
->factory
);
841 list_remove(&fontface
->cached
->entry
);
842 factory_unlock(fontface
->factory
);
843 free(fontface
->cached
);
845 release_scriptshaping_cache(fontface
->shaping_cache
);
846 if (fontface
->vdmx
.context
)
847 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
848 if (fontface
->gasp
.context
)
849 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
850 if (fontface
->cpal
.context
)
851 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
852 if (fontface
->colr
.context
)
853 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
854 if (fontface
->kern
.context
)
855 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->kern
.context
);
857 IDWriteFontFile_Release(fontface
->file
);
859 IDWriteLocalizedStrings_Release(fontface
->names
);
860 if (fontface
->family_names
)
861 IDWriteLocalizedStrings_Release(fontface
->family_names
);
862 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
864 if (fontface
->info_strings
[i
])
865 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
868 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
869 free(fontface
->glyphs
[i
]);
871 UNIX_CALL(release_font_object
, ¶ms
);
872 if (fontface
->stream
)
874 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, fontface
->data_context
);
875 IDWriteFontFileStream_Release(fontface
->stream
);
877 fontface_cache_clear(fontface
);
879 dwrite_cmap_release(&fontface
->cmap
);
880 IDWriteFactory7_Release(fontface
->factory
);
881 DeleteCriticalSection(&fontface
->cs
);
888 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
890 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
892 TRACE("%p.\n", iface
);
894 return fontface
->type
;
897 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
898 IDWriteFontFile
**fontfiles
)
900 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
902 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
906 *number_of_files
= 1;
910 if (!*number_of_files
)
913 IDWriteFontFile_AddRef(fontface
->file
);
914 *fontfiles
= fontface
->file
;
919 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
921 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
923 TRACE("%p.\n", iface
);
925 return fontface
->index
;
928 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
930 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
932 TRACE("%p.\n", iface
);
934 return fontface
->simulations
;
937 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
939 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
941 TRACE("%p.\n", iface
);
943 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
946 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
948 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
950 TRACE("%p, %p.\n", iface
, metrics
);
952 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
955 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
957 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
958 struct get_glyph_count_params params
;
961 TRACE("%p.\n", iface
);
963 params
.object
= fontface
->get_font_object(fontface
);
964 params
.count
= &count
;
965 UNIX_CALL(get_glyph_count
, ¶ms
);
970 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
971 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
973 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
974 struct get_design_glyph_metrics_params params
;
975 DWRITE_GLYPH_METRICS metrics
;
979 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
985 FIXME("sideways metrics are not supported.\n");
987 params
.object
= fontface
->get_font_object(fontface
);
988 params
.simulations
= fontface
->simulations
;
989 params
.upem
= fontface
->metrics
.designUnitsPerEm
;
990 params
.ascent
= fontface
->typo_metrics
.ascent
;
991 params
.metrics
= &metrics
;
993 EnterCriticalSection(&fontface
->cs
);
994 for (i
= 0; i
< glyph_count
; ++i
)
997 if (get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
) != S_OK
)
999 params
.glyph
= glyphs
[i
];
1000 UNIX_CALL(get_design_glyph_metrics
, ¶ms
);
1001 if (FAILED(hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
))) break;
1005 LeaveCriticalSection(&fontface
->cs
);
1010 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
1011 UINT32 count
, UINT16
*glyphs
)
1013 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1016 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
1019 return E_INVALIDARG
;
1023 memset(glyphs
, 0, count
* sizeof(*glyphs
));
1024 return E_INVALIDARG
;
1027 for (i
= 0; i
< count
; ++i
)
1028 glyphs
[i
] = dwritefontface_get_glyph(fontface
, codepoints
[i
]);
1033 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
1034 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
1036 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1037 struct file_stream_desc stream_desc
;
1039 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
1041 stream_desc
.stream
= fontface
->stream
;
1042 stream_desc
.face_type
= fontface
->type
;
1043 stream_desc
.face_index
= fontface
->index
;
1044 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
1047 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
1049 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1051 TRACE("%p, %p.\n", iface
, table_context
);
1053 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
1056 static void apply_outline_point_offset(const D2D1_POINT_2F
*src
, const D2D1_POINT_2F
*offset
,
1059 dst
->x
= src
->x
+ offset
->x
;
1060 dst
->y
= src
->y
+ offset
->y
;
1063 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
1064 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
1065 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
1067 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1068 D2D1_POINT_2F
*origins
, baseline_origin
= { 0 };
1069 struct dwrite_outline outline
, outline_size
;
1070 struct get_glyph_outline_params params
;
1071 D2D1_BEZIER_SEGMENT segment
;
1072 D2D1_POINT_2F point
;
1073 DWRITE_GLYPH_RUN run
;
1074 unsigned int i
, j
, p
;
1078 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
1079 count
, is_sideways
, is_rtl
, sink
);
1081 if (!glyphs
|| !sink
)
1082 return E_INVALIDARG
;
1087 run
.fontFace
= (IDWriteFontFace
*)iface
;
1088 run
.fontEmSize
= emSize
;
1089 run
.glyphCount
= count
;
1090 run
.glyphIndices
= glyphs
;
1091 run
.glyphAdvances
= advances
;
1092 run
.glyphOffsets
= offsets
;
1093 run
.isSideways
= is_sideways
;
1094 run
.bidiLevel
= is_rtl
? 1 : 0;
1096 if (!(origins
= malloc(sizeof(*origins
) * count
)))
1097 return E_OUTOFMEMORY
;
1099 if (FAILED(hr
= compute_glyph_origins(&run
, DWRITE_MEASURING_MODE_NATURAL
, baseline_origin
, NULL
, origins
)))
1105 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
1107 memset(&outline_size
, 0, sizeof(outline_size
));
1108 memset(&outline
, 0, sizeof(outline
));
1110 params
.object
= fontface
->get_font_object(fontface
);
1111 params
.simulations
= fontface
->simulations
;
1112 params
.emsize
= emSize
;
1114 for (i
= 0; i
< count
; ++i
)
1116 outline
.tags
.count
= outline
.points
.count
= 0;
1118 EnterCriticalSection(&fontface
->cs
);
1120 params
.glyph
= glyphs
[i
];
1121 params
.outline
= &outline_size
;
1123 if (!(status
= UNIX_CALL(get_glyph_outline
, ¶ms
)))
1125 dwrite_array_reserve((void **)&outline
.tags
.values
, &outline
.tags
.size
, outline_size
.tags
.count
,
1126 sizeof(*outline
.tags
.values
));
1127 dwrite_array_reserve((void **)&outline
.points
.values
, &outline
.points
.size
, outline_size
.points
.count
,
1128 sizeof(*outline
.points
.values
));
1130 params
.outline
= &outline
;
1131 if ((status
= UNIX_CALL(get_glyph_outline
, ¶ms
)))
1133 WARN("Failed to get glyph outline for glyph %u.\n", glyphs
[i
]);
1136 LeaveCriticalSection(&fontface
->cs
);
1141 for (j
= 0, p
= 0; j
< outline
.tags
.count
; ++j
)
1143 switch (outline
.tags
.values
[j
])
1145 case OUTLINE_BEGIN_FIGURE
:
1146 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
1147 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, point
, D2D1_FIGURE_BEGIN_FILLED
);
1149 case OUTLINE_END_FIGURE
:
1150 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
1153 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &point
);
1154 ID2D1SimplifiedGeometrySink_AddLines(sink
, &point
, 1);
1156 case OUTLINE_BEZIER
:
1157 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point1
);
1158 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point2
);
1159 apply_outline_point_offset(&outline
.points
.values
[p
++], &origins
[i
], &segment
.point3
);
1160 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, &segment
, 1);
1166 free(outline
.tags
.values
);
1167 free(outline
.points
.values
);
1173 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
1174 float ppem
, unsigned int gasp
)
1176 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
1180 case DWRITE_MEASURING_MODE_NATURAL
:
1182 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
1183 mode
= DWRITE_RENDERING_MODE_NATURAL
;
1185 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
1188 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1189 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
1191 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1192 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
1201 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1202 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
1204 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1208 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
1211 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
1212 return E_INVALIDARG
;
1215 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1216 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
1219 ppem
= emSize
* ppdip
;
1221 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
1222 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
1226 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
1227 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
1231 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
1232 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
1234 DWRITE_FONT_METRICS1 metrics1
;
1235 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
1236 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
1240 static inline int round_metric(FLOAT metric
)
1242 return (int)floorf(metric
+ 0.5f
);
1245 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
1247 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
1250 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
1253 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
1254 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
1255 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
1257 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1258 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1259 DWRITE_MEASURING_MODE mode
;
1264 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
1265 glyph_count
, metrics
, is_sideways
);
1267 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1268 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
1270 size
= emSize
* ppdip
;
1271 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
1272 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1274 EnterCriticalSection(&fontface
->cs
);
1275 for (i
= 0; i
< glyph_count
; ++i
)
1277 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
1278 DWRITE_GLYPH_METRICS design
;
1281 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
1285 ret
->advanceWidth
= fontface_get_glyph_advance(fontface
, size
, glyphs
[i
], mode
, &has_contours
);
1287 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
1289 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
1291 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
1292 SCALE_METRIC(leftSideBearing
);
1293 SCALE_METRIC(rightSideBearing
);
1294 SCALE_METRIC(topSideBearing
);
1295 SCALE_METRIC(advanceHeight
);
1296 SCALE_METRIC(bottomSideBearing
);
1297 SCALE_METRIC(verticalOriginY
);
1300 LeaveCriticalSection(&fontface
->cs
);
1305 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1307 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1309 TRACE("%p, %p.\n", iface
, metrics
);
1311 *metrics
= fontface
->metrics
;
1314 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
1315 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
1317 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1318 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
1319 UINT16 ascent
, descent
;
1322 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
1324 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
1325 memset(metrics
, 0, sizeof(*metrics
));
1326 return E_INVALIDARG
;
1329 em_size
*= pixels_per_dip
;
1330 if (m
&& m
->m22
!= 0.0f
)
1331 em_size
*= fabs(m
->m22
);
1333 scale
= em_size
/ design
->designUnitsPerEm
;
1334 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
1336 ascent
= round_metric(design
->ascent
* scale
);
1337 descent
= round_metric(design
->descent
* scale
);
1340 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
1341 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
1342 metrics
->ascent
= round_metric(ascent
/ scale
);
1343 metrics
->descent
= round_metric(descent
/ scale
);
1345 SCALE_METRIC(lineGap
);
1346 SCALE_METRIC(capHeight
);
1347 SCALE_METRIC(xHeight
);
1348 SCALE_METRIC(underlinePosition
);
1349 SCALE_METRIC(underlineThickness
);
1350 SCALE_METRIC(strikethroughPosition
);
1351 SCALE_METRIC(strikethroughThickness
);
1352 SCALE_METRIC(glyphBoxLeft
);
1353 SCALE_METRIC(glyphBoxTop
);
1354 SCALE_METRIC(glyphBoxRight
);
1355 SCALE_METRIC(glyphBoxBottom
);
1356 SCALE_METRIC(subscriptPositionX
);
1357 SCALE_METRIC(subscriptPositionY
);
1358 SCALE_METRIC(subscriptSizeX
);
1359 SCALE_METRIC(subscriptSizeY
);
1360 SCALE_METRIC(superscriptPositionX
);
1361 SCALE_METRIC(superscriptPositionY
);
1362 SCALE_METRIC(superscriptSizeX
);
1363 SCALE_METRIC(superscriptSizeY
);
1365 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
1371 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
1373 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1375 TRACE("%p, %p.\n", iface
, metrics
);
1377 *metrics
= fontface
->caret
;
1380 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
1381 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1383 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1385 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1388 if (max_count
&& !ranges
)
1389 return E_INVALIDARG
;
1391 dwrite_cmap_init(&fontface
->cmap
, NULL
, fontface
->index
, fontface
->type
);
1392 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
1395 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
1397 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1399 TRACE("%p.\n", iface
);
1401 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
1404 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
1405 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
1407 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
1412 FIXME("Sideways mode is not supported.\n");
1414 switch (measuring_mode
)
1416 case DWRITE_MEASURING_MODE_NATURAL
:
1417 advance
= fontface_get_glyph_advance(fontface
, fontface
->metrics
.designUnitsPerEm
, glyph
,
1418 measuring_mode
, &has_contours
);
1420 advance
+= adjustment
;
1423 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
1424 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
1429 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
1430 FIXME("Transform is not supported.\n");
1432 advance
= fontface_get_glyph_advance(fontface
, emsize
, glyph
, measuring_mode
, &has_contours
);
1434 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1436 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1440 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1445 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1446 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1448 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1451 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1454 FIXME("sideways mode not supported\n");
1456 EnterCriticalSection(&fontface
->cs
);
1457 for (i
= 0; i
< glyph_count
; ++i
)
1459 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1460 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1462 LeaveCriticalSection(&fontface
->cs
);
1467 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1468 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1469 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1471 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1472 DWRITE_MEASURING_MODE measuring_mode
;
1475 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1476 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1478 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1479 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1480 return E_INVALIDARG
;
1483 if (em_size
== 0.0f
) {
1484 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1488 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1490 EnterCriticalSection(&fontface
->cs
);
1491 for (i
= 0; i
< glyph_count
; ++i
)
1493 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1494 glyphs
[i
], is_sideways
);
1496 LeaveCriticalSection(&fontface
->cs
);
1501 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1502 const UINT16
*glyphs
, INT32
*values
)
1504 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1506 TRACE("%p, %u, %p, %p.\n", iface
, count
, glyphs
, values
);
1508 if (!(glyphs
|| values
) || !count
)
1509 return E_INVALIDARG
;
1511 if (!glyphs
|| count
== 1)
1513 memset(values
, 0, count
* sizeof(*values
));
1514 return E_INVALIDARG
;
1517 return opentype_get_kerning_pairs(fontface
, count
, glyphs
, values
);
1520 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1522 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1524 TRACE("%p.\n", iface
);
1526 return opentype_has_kerning_pairs(fontface
);
1529 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1530 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1531 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1533 DWRITE_GRID_FIT_MODE gridfitmode
;
1534 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1535 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1538 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1539 const UINT16
*nominal_glyphs
, UINT16
*glyphs
)
1541 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1543 TRACE("%p, %u, %p, %p.\n", iface
, glyph_count
, nominal_glyphs
, glyphs
);
1545 return opentype_get_vertical_glyph_variants(fontface
, glyph_count
, nominal_glyphs
, glyphs
);
1548 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1550 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1552 TRACE("%p.\n", iface
);
1554 return opentype_has_vertical_variants(fontface
);
1557 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1559 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1561 TRACE("%p.\n", iface
);
1563 return !!(fontface
->flags
& FONT_IS_COLORED
);
1566 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1568 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1570 TRACE("%p.\n", iface
);
1572 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1575 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1577 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1579 TRACE("%p.\n", iface
);
1581 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1584 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1585 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1587 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1589 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1591 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1594 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1595 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1596 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1597 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1599 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1603 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1604 measuringmode
, params
, renderingmode
, gridfitmode
);
1606 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1607 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1610 FIXME("sideways mode not supported\n");
1612 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1614 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1615 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1617 IDWriteRenderingParams2
*params2
;
1620 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1622 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1623 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1624 IDWriteRenderingParams2_Release(params2
);
1627 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1630 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1632 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1634 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1635 if (emSize
>= emthreshold
)
1636 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1638 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1641 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1642 if (emSize
>= emthreshold
)
1643 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1644 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1645 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1647 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1648 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1654 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
,
1655 IDWriteFontFaceReference
**reference
)
1657 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1659 TRACE("%p, %p.\n", iface
, reference
);
1661 *reference
= &fontface
->IDWriteFontFaceReference_iface
;
1662 IDWriteFontFaceReference_AddRef(*reference
);
1667 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1669 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1671 TRACE("%p, %p.\n", iface
, panose
);
1673 *panose
= fontface
->panose
;
1676 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1678 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1680 TRACE("%p.\n", iface
);
1682 return fontface
->weight
;
1685 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1687 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1689 TRACE("%p.\n", iface
);
1691 return fontface
->stretch
;
1694 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1696 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1698 TRACE("%p.\n", iface
);
1700 return fontface
->style
;
1703 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1705 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1707 TRACE("%p, %p.\n", iface
, names
);
1709 return clone_localizedstrings(fontface
->family_names
, names
);
1712 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1714 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1716 TRACE("%p, %p.\n", iface
, names
);
1718 return clone_localizedstrings(fontface
->names
, names
);
1721 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1722 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1723 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1730 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1731 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1736 if (!strings_cache
[stringid
])
1738 struct file_stream_desc desc
= *stream_desc
;
1741 hr
= get_filestream_from_file(file
, &desc
.stream
);
1743 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1745 if (!stream_desc
->stream
&& desc
.stream
)
1746 IDWriteFontFileStream_Release(desc
.stream
);
1749 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1751 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1759 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1760 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1762 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1763 struct file_stream_desc stream_desc
;
1765 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1767 stream_desc
.stream
= fontface
->stream
;
1768 stream_desc
.face_index
= fontface
->index
;
1769 stream_desc
.face_type
= fontface
->type
;
1770 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1773 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1775 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1777 TRACE("%p, %#x.\n", iface
, ch
);
1779 return !!dwritefontface_get_glyph(fontface
, ch
);
1782 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1783 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1784 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1786 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1790 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1791 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1793 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
1794 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1797 FIXME("sideways mode not supported\n");
1799 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1801 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1802 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1804 IDWriteRenderingParams3
*params3
;
1807 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1809 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1810 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1811 IDWriteRenderingParams3_Release(params3
);
1814 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1817 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1819 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1821 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1822 if (emSize
>= emthreshold
)
1823 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1825 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1828 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1829 if (emSize
>= emthreshold
)
1830 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1831 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1832 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1834 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1835 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1841 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1843 FIXME("%p, %#x: stub\n", iface
, ch
);
1848 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1850 FIXME("%p, %u: stub\n", iface
, glyph
);
1855 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1856 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1858 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1863 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1864 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1866 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1871 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1872 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1874 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1879 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1881 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1883 TRACE("%p.\n", iface
);
1885 return fontface
->glyph_image_formats
;
1888 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1889 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1891 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1896 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1898 FIXME("%p, %p: stub\n", iface
, context
);
1901 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1903 FIXME("%p: stub\n", iface
);
1908 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1911 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1916 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1921 FIXME("%p: stub\n", iface
);
1926 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1928 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1930 TRACE("%p, %p.\n", iface
, resource
);
1932 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->file
, fontface
->index
, resource
);
1935 static BOOL WINAPI
dwritefontface5_Equals(IDWriteFontFace5
*iface
, IDWriteFontFace
*other
)
1937 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
), *other_face
;
1939 TRACE("%p, %p.\n", iface
, other
);
1941 if (!(other_face
= unsafe_impl_from_IDWriteFontFace(other
)))
1944 /* TODO: add variations support */
1946 return fontface
->index
== other_face
->index
&&
1947 fontface
->simulations
== other_face
->simulations
&&
1948 is_same_fontfile(fontface
->file
, other_face
->file
);
1951 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1953 dwritefontface_QueryInterface
,
1954 dwritefontface_AddRef
,
1955 dwritefontface_Release
,
1956 dwritefontface_GetType
,
1957 dwritefontface_GetFiles
,
1958 dwritefontface_GetIndex
,
1959 dwritefontface_GetSimulations
,
1960 dwritefontface_IsSymbolFont
,
1961 dwritefontface_GetMetrics
,
1962 dwritefontface_GetGlyphCount
,
1963 dwritefontface_GetDesignGlyphMetrics
,
1964 dwritefontface_GetGlyphIndices
,
1965 dwritefontface_TryGetFontTable
,
1966 dwritefontface_ReleaseFontTable
,
1967 dwritefontface_GetGlyphRunOutline
,
1968 dwritefontface_GetRecommendedRenderingMode
,
1969 dwritefontface_GetGdiCompatibleMetrics
,
1970 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1971 dwritefontface1_GetMetrics
,
1972 dwritefontface1_GetGdiCompatibleMetrics
,
1973 dwritefontface1_GetCaretMetrics
,
1974 dwritefontface1_GetUnicodeRanges
,
1975 dwritefontface1_IsMonospacedFont
,
1976 dwritefontface1_GetDesignGlyphAdvances
,
1977 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1978 dwritefontface1_GetKerningPairAdjustments
,
1979 dwritefontface1_HasKerningPairs
,
1980 dwritefontface1_GetRecommendedRenderingMode
,
1981 dwritefontface1_GetVerticalGlyphVariants
,
1982 dwritefontface1_HasVerticalGlyphVariants
,
1983 dwritefontface2_IsColorFont
,
1984 dwritefontface2_GetColorPaletteCount
,
1985 dwritefontface2_GetPaletteEntryCount
,
1986 dwritefontface2_GetPaletteEntries
,
1987 dwritefontface2_GetRecommendedRenderingMode
,
1988 dwritefontface3_GetFontFaceReference
,
1989 dwritefontface3_GetPanose
,
1990 dwritefontface3_GetWeight
,
1991 dwritefontface3_GetStretch
,
1992 dwritefontface3_GetStyle
,
1993 dwritefontface3_GetFamilyNames
,
1994 dwritefontface3_GetFaceNames
,
1995 dwritefontface3_GetInformationalStrings
,
1996 dwritefontface3_HasCharacter
,
1997 dwritefontface3_GetRecommendedRenderingMode
,
1998 dwritefontface3_IsCharacterLocal
,
1999 dwritefontface3_IsGlyphLocal
,
2000 dwritefontface3_AreCharactersLocal
,
2001 dwritefontface3_AreGlyphsLocal
,
2002 dwritefontface4_GetGlyphImageFormats_
,
2003 dwritefontface4_GetGlyphImageFormats
,
2004 dwritefontface4_GetGlyphImageData
,
2005 dwritefontface4_ReleaseGlyphImageData
,
2006 dwritefontface5_GetFontAxisValueCount
,
2007 dwritefontface5_GetFontAxisValues
,
2008 dwritefontface5_HasVariations
,
2009 dwritefontface5_GetFontResource
,
2010 dwritefontface5_Equals
,
2013 static HRESULT WINAPI
dwritefontface_reference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
2015 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2016 return IDWriteFontFace5_QueryInterface(&fontface
->IDWriteFontFace5_iface
, riid
, obj
);
2019 static ULONG WINAPI
dwritefontface_reference_AddRef(IDWriteFontFaceReference
*iface
)
2021 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2022 return IDWriteFontFace5_AddRef(&fontface
->IDWriteFontFace5_iface
);
2025 static ULONG WINAPI
dwritefontface_reference_Release(IDWriteFontFaceReference
*iface
)
2027 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2028 return IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
2031 static HRESULT WINAPI
dwritefontface_reference_CreateFontFace(IDWriteFontFaceReference
*iface
,
2032 IDWriteFontFace3
**ret
)
2034 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2036 TRACE("%p, %p.\n", iface
, ret
);
2038 *ret
= (IDWriteFontFace3
*)&fontface
->IDWriteFontFace5_iface
;
2039 IDWriteFontFace3_AddRef(*ret
);
2044 static HRESULT WINAPI
dwritefontface_reference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
2045 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
2047 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2048 DWRITE_FONT_FILE_TYPE file_type
;
2049 DWRITE_FONT_FACE_TYPE face_type
;
2050 IDWriteFontFace
*face
;
2055 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
2057 hr
= IDWriteFontFile_Analyze(fontface
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
2061 hr
= IDWriteFactory7_CreateFontFace(fontface
->factory
, face_type
, 1, &fontface
->file
, fontface
->index
,
2062 simulations
, &face
);
2065 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void **)ret
);
2066 IDWriteFontFace_Release(face
);
2072 static BOOL WINAPI
dwritefontface_reference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
2074 FIXME("%p, %p.\n", iface
, ref
);
2079 static UINT32 WINAPI
dwritefontface_reference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
2081 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2083 TRACE("%p.\n", iface
);
2085 return fontface
->index
;
2088 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_reference_GetSimulations(IDWriteFontFaceReference
*iface
)
2090 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2092 TRACE("%p.\n", iface
);
2094 return fontface
->simulations
;
2097 static HRESULT WINAPI
dwritefontface_reference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
2099 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFaceReference(iface
);
2101 TRACE("%p, %p.\n", iface
, file
);
2103 *file
= fontface
->file
;
2104 IDWriteFontFile_AddRef(*file
);
2109 static UINT64 WINAPI
dwritefontface_reference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
2111 FIXME("%p.\n", iface
);
2116 static UINT64 WINAPI
dwritefontface_reference_GetFileSize(IDWriteFontFaceReference
*iface
)
2118 FIXME("%p.\n", iface
);
2123 static HRESULT WINAPI
dwritefontface_reference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
2125 FIXME("%p, %p.\n", iface
, writetime
);
2130 static DWRITE_LOCALITY WINAPI
dwritefontface_reference_GetLocality(IDWriteFontFaceReference
*iface
)
2132 FIXME("%p.\n", iface
);
2134 return DWRITE_LOCALITY_LOCAL
;
2137 static HRESULT WINAPI
dwritefontface_reference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
2139 FIXME("%p.\n", iface
);
2144 static HRESULT WINAPI
dwritefontface_reference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
,
2145 WCHAR
const *chars
, UINT32 count
)
2147 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
2152 static HRESULT WINAPI
dwritefontface_reference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
,
2153 UINT16
const *glyphs
, UINT32 count
)
2155 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
2160 static HRESULT WINAPI
dwritefontface_reference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
2161 UINT64 offset
, UINT64 size
)
2163 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
2168 static const IDWriteFontFaceReferenceVtbl dwritefontface_reference_vtbl
=
2170 dwritefontface_reference_QueryInterface
,
2171 dwritefontface_reference_AddRef
,
2172 dwritefontface_reference_Release
,
2173 dwritefontface_reference_CreateFontFace
,
2174 dwritefontface_reference_CreateFontFaceWithSimulations
,
2175 dwritefontface_reference_Equals
,
2176 dwritefontface_reference_GetFontFaceIndex
,
2177 dwritefontface_reference_GetSimulations
,
2178 dwritefontface_reference_GetFontFile
,
2179 dwritefontface_reference_GetLocalFileSize
,
2180 dwritefontface_reference_GetFileSize
,
2181 dwritefontface_reference_GetFileTime
,
2182 dwritefontface_reference_GetLocality
,
2183 dwritefontface_reference_EnqueueFontDownloadRequest
,
2184 dwritefontface_reference_EnqueueCharacterDownloadRequest
,
2185 dwritefontface_reference_EnqueueGlyphDownloadRequest
,
2186 dwritefontface_reference_EnqueueFileFragmentDownloadRequest
,
2189 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
2191 struct dwrite_font_data
*data
= font
->data
;
2192 struct fontface_desc desc
;
2193 struct list
*cached_list
;
2198 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
2199 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
2203 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
2206 desc
.factory
= font
->family
->collection
->factory
;
2207 desc
.face_type
= data
->face_type
;
2208 desc
.file
= data
->file
;
2209 desc
.index
= data
->face_index
;
2210 desc
.simulations
= data
->simulations
;
2211 desc
.font_data
= data
;
2212 hr
= create_fontface(&desc
, cached_list
, fontface
);
2214 IDWriteFontFileStream_Release(desc
.stream
);
2218 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
2220 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2222 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
2223 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
2224 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
2225 IsEqualIID(riid
, &IID_IDWriteFont
) ||
2226 IsEqualIID(riid
, &IID_IUnknown
))
2229 IDWriteFont3_AddRef(iface
);
2233 WARN("%s not implemented.\n", debugstr_guid(riid
));
2236 return E_NOINTERFACE
;
2239 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
2241 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2242 ULONG refcount
= InterlockedIncrement(&font
->refcount
);
2244 TRACE("%p, refcount %d.\n", iface
, refcount
);
2249 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
2251 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2252 ULONG refcount
= InterlockedDecrement(&font
->refcount
);
2254 TRACE("%p, refcount %d.\n", iface
, refcount
);
2258 IDWriteFontFamily2_Release(&font
->family
->IDWriteFontFamily2_iface
);
2259 release_font_data(font
->data
);
2266 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
2268 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2270 TRACE("%p, %p.\n", iface
, family
);
2272 *family
= (IDWriteFontFamily
*)&font
->family
->IDWriteFontFamily2_iface
;
2273 IDWriteFontFamily_AddRef(*family
);
2277 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
2279 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2281 TRACE("%p.\n", iface
);
2283 return font
->data
->weight
;
2286 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
2288 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2290 TRACE("%p.\n", iface
);
2292 return font
->data
->stretch
;
2295 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
2297 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2299 TRACE("%p.\n", iface
);
2304 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
2306 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2308 TRACE("%p.\n", iface
);
2310 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
2313 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
2315 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2317 TRACE("%p, %p.\n", iface
, names
);
2319 return clone_localizedstrings(font
->data
->names
, names
);
2322 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
2323 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
2325 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2326 struct dwrite_font_data
*data
= font
->data
;
2327 struct file_stream_desc stream_desc
;
2329 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
2331 /* Stream will be created if necessary. */
2332 stream_desc
.stream
= NULL
;
2333 stream_desc
.face_index
= data
->face_index
;
2334 stream_desc
.face_type
= data
->face_type
;
2335 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
2338 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
2340 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2342 TRACE("%p.\n", iface
);
2344 return font
->data
->simulations
;
2347 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
2349 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2351 TRACE("%p, %p.\n", iface
, metrics
);
2353 memcpy(metrics
, &font
->data
->metrics
, sizeof(*metrics
));
2356 static BOOL
dwritefont_has_character(struct dwrite_font
*font
, UINT32 ch
)
2359 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2360 glyph
= opentype_cmap_get_glyph(&font
->data
->cmap
, ch
);
2364 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
2366 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2368 TRACE("%p, %#x, %p.\n", iface
, ch
, exists
);
2370 *exists
= dwritefont_has_character(font
, ch
);
2375 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
2377 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2379 TRACE("%p, %p.\n", iface
, fontface
);
2381 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2384 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
2386 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2388 TRACE("%p, %p.\n", iface
, metrics
);
2390 *metrics
= font
->data
->metrics
;
2393 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
2395 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2397 TRACE("%p, %p.\n", iface
, panose
);
2399 *panose
= font
->data
->panose
;
2402 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
,
2405 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2407 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
2410 if (max_count
&& !ranges
)
2411 return E_INVALIDARG
;
2413 dwrite_cmap_init(&font
->data
->cmap
, font
->data
->file
, font
->data
->face_index
, font
->data
->face_type
);
2414 return opentype_cmap_get_unicode_ranges(&font
->data
->cmap
, max_count
, ranges
, count
);
2417 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
2419 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2421 TRACE("%p.\n", iface
);
2423 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
2426 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
2428 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2430 TRACE("%p.\n", iface
);
2432 return !!(font
->data
->flags
& FONT_IS_COLORED
);
2435 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
2437 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2439 TRACE("%p, %p.\n", iface
, fontface
);
2441 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
2444 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*other
)
2446 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
), *other_font
;
2448 TRACE("%p, %p.\n", iface
, other
);
2450 if (!(other_font
= unsafe_impl_from_IDWriteFont(other
)))
2453 return font
->data
->face_index
== other_font
->data
->face_index
2454 && font
->data
->simulations
== other_font
->data
->simulations
2455 && is_same_fontfile(font
->data
->file
, other_font
->data
->file
);
2458 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
2460 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2462 TRACE("%p, %p.\n", iface
, reference
);
2464 return IDWriteFactory7_CreateFontFaceReference(font
->family
->collection
->factory
, font
->data
->file
,
2465 font
->data
->face_index
, font
->data
->simulations
, font
->data
->axis
, ARRAY_SIZE(font
->data
->axis
),
2466 (IDWriteFontFaceReference1
**)reference
);
2469 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
2471 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
2473 TRACE("%p, %#x.\n", iface
, ch
);
2475 return dwritefont_has_character(font
, ch
);
2478 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
2480 FIXME("%p: stub.\n", iface
);
2482 return DWRITE_LOCALITY_LOCAL
;
2485 static const IDWriteFont3Vtbl dwritefontvtbl
= {
2486 dwritefont_QueryInterface
,
2489 dwritefont_GetFontFamily
,
2490 dwritefont_GetWeight
,
2491 dwritefont_GetStretch
,
2492 dwritefont_GetStyle
,
2493 dwritefont_IsSymbolFont
,
2494 dwritefont_GetFaceNames
,
2495 dwritefont_GetInformationalStrings
,
2496 dwritefont_GetSimulations
,
2497 dwritefont_GetMetrics
,
2498 dwritefont_HasCharacter
,
2499 dwritefont_CreateFontFace
,
2500 dwritefont1_GetMetrics
,
2501 dwritefont1_GetPanose
,
2502 dwritefont1_GetUnicodeRanges
,
2503 dwritefont1_IsMonospacedFont
,
2504 dwritefont2_IsColorFont
,
2505 dwritefont3_CreateFontFace
,
2507 dwritefont3_GetFontFaceReference
,
2508 dwritefont3_HasCharacter
,
2509 dwritefont3_GetLocality
2512 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
2516 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
2517 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
2520 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
2524 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
2525 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
2528 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
2532 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
2534 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
2535 IDWriteFontFaceReference1_iface
);
2538 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
2540 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2541 *lf
= font
->data
->lf
;
2544 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
2546 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2550 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
2552 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
2553 *fontsig
= font
->data
->fontsig
;
2557 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
2559 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
2560 *fontsig
= fontface
->fontsig
;
2564 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
2566 struct dwrite_font
*object
;
2570 if (!(object
= calloc(1, sizeof(*object
))))
2571 return E_OUTOFMEMORY
;
2573 object
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
2574 object
->refcount
= 1;
2575 object
->family
= family
;
2576 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
2577 object
->data
= family
->data
->fonts
[index
];
2578 object
->style
= object
->data
->style
;
2579 addref_font_data(object
->data
);
2581 *font
= &object
->IDWriteFont3_iface
;
2586 /* IDWriteFontList2 */
2587 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2589 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2591 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2592 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2593 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
2594 IsEqualIID(riid
, &IID_IUnknown
))
2597 IDWriteFontList2_AddRef(iface
);
2601 WARN("%s not implemented.\n", debugstr_guid(riid
));
2604 return E_NOINTERFACE
;
2607 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
2609 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2610 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
2612 TRACE("%p, refcount %u.\n", iface
, refcount
);
2617 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
2619 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2620 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
2622 TRACE("%p, refcount %u.\n", iface
, refcount
);
2628 for (i
= 0; i
< fontlist
->font_count
; i
++)
2629 release_font_data(fontlist
->fonts
[i
]);
2630 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
2631 free(fontlist
->fonts
);
2638 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2640 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2641 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2644 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2646 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2648 TRACE("%p.\n", iface
);
2650 return fontlist
->font_count
;
2653 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2655 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2657 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2661 if (fontlist
->font_count
== 0)
2664 if (index
>= fontlist
->font_count
)
2665 return E_INVALIDARG
;
2667 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2670 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2672 FIXME("%p, %u.\n", iface
, index
);
2674 return DWRITE_LOCALITY_LOCAL
;
2677 static HRESULT
fontlist_get_font(const struct dwrite_fontlist
*fontlist
, unsigned int index
,
2678 IDWriteFont3
**font
)
2682 if (fontlist
->font_count
== 0)
2685 if (index
>= fontlist
->font_count
)
2688 return create_font(fontlist
->family
, index
, font
);
2691 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2693 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2695 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2697 return fontlist_get_font(fontlist
, index
, font
);
2700 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2701 IDWriteFontFaceReference
**reference
)
2703 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2707 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2711 if (SUCCEEDED(hr
= fontlist_get_font(fontlist
, index
, &font
)))
2713 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2714 IDWriteFont3_Release(font
);
2720 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2722 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2724 TRACE("%p, %p.\n", iface
, fontset
);
2726 return fontset_create_from_font_data(fontlist
->family
->collection
->factory
, fontlist
->fonts
,
2727 fontlist
->font_count
, fontset
);
2730 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2732 dwritefontlist_QueryInterface
,
2733 dwritefontlist_AddRef
,
2734 dwritefontlist_Release
,
2735 dwritefontlist_GetFontCollection
,
2736 dwritefontlist_GetFontCount
,
2737 dwritefontlist_GetFont
,
2738 dwritefontlist1_GetFontLocality
,
2739 dwritefontlist1_GetFont
,
2740 dwritefontlist1_GetFontFaceReference
,
2741 dwritefontlist2_GetFontSet
,
2744 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2746 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2748 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2750 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2751 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2752 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2753 IsEqualIID(riid
, &IID_IUnknown
))
2757 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2758 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2759 IsEqualIID(riid
, &IID_IDWriteFontList
))
2761 *obj
= &family
->IDWriteFontList2_iface
;
2765 WARN("%s not implemented.\n", debugstr_guid(riid
));
2767 return E_NOINTERFACE
;
2770 IUnknown_AddRef((IUnknown
*)*obj
);
2774 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2776 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2777 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2779 TRACE("%p, %u.\n", iface
, refcount
);
2784 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2786 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2787 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2789 TRACE("%p, %u.\n", iface
, refcount
);
2793 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2794 release_fontfamily_data(family
->data
);
2801 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2803 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2805 TRACE("%p, %p.\n", iface
, collection
);
2807 *collection
= (IDWriteFontCollection
*)&family
->collection
->IDWriteFontCollection3_iface
;
2808 IDWriteFontCollection_AddRef(*collection
);
2812 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2814 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2816 TRACE("%p.\n", iface
);
2818 return family
->data
->count
;
2821 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2823 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2825 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2829 if (!family
->data
->count
)
2832 if (index
>= family
->data
->count
)
2833 return E_INVALIDARG
;
2835 return create_font(family
, index
, (IDWriteFont3
**)font
);
2838 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2840 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2842 TRACE("%p, %p.\n", iface
, names
);
2844 return clone_localizedstrings(family
->data
->familyname
, names
);
2847 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2848 const struct dwrite_font_propvec
*req
)
2850 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2851 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2852 FLOAT cur_req_prod
, next_req_prod
;
2854 if (next_to_req
< cur_to_req
)
2857 if (next_to_req
> cur_to_req
)
2860 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2861 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2863 if (next_req_prod
> cur_req_prod
)
2866 if (next_req_prod
< cur_req_prod
)
2869 if (next
->stretch
> cur
->stretch
)
2871 if (next
->stretch
< cur
->stretch
)
2874 if (next
->style
> cur
->style
)
2876 if (next
->style
< cur
->style
)
2879 if (next
->weight
> cur
->weight
)
2881 if (next
->weight
< cur
->weight
)
2884 /* full match, no reason to prefer new variant */
2888 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2889 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2891 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2892 struct dwrite_font_propvec req
;
2895 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2897 if (!family
->data
->count
)
2900 return DWRITE_E_NOFONT
;
2903 init_font_prop_vec(weight
, stretch
, style
, &req
);
2906 for (i
= 1; i
< family
->data
->count
; ++i
)
2908 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2912 return create_font(family
, match
, (IDWriteFont3
**)font
);
2915 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2917 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2919 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2922 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2924 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2927 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2929 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2934 for (j
= 0; j
< b
; j
++) {
2935 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2936 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2937 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2938 fonts
->fonts
[j
+1] = s
;
2949 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2950 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2952 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2953 matching_filter_func func
= NULL
;
2954 struct dwrite_font_propvec req
;
2955 struct dwrite_fontlist
*fonts
;
2958 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2962 if (!(fonts
= malloc(sizeof(*fonts
))))
2963 return E_OUTOFMEMORY
;
2965 /* Allocate as many as family has, not all of them will be necessary used. */
2966 if (!(fonts
->fonts
= calloc(family
->data
->count
, sizeof(*fonts
->fonts
))))
2969 return E_OUTOFMEMORY
;
2972 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2973 fonts
->refcount
= 1;
2974 fonts
->family
= family
;
2975 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2976 fonts
->font_count
= 0;
2978 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2979 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2980 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2981 func
= is_font_acceptable_for_normal
;
2983 else /* requested oblique or italic */ {
2984 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2985 func
= is_font_acceptable_for_oblique_italic
;
2988 for (i
= 0; i
< family
->data
->count
; ++i
)
2990 if (!func
|| func(family
->data
->fonts
[i
]))
2992 fonts
->fonts
[fonts
->font_count
++] = addref_font_data(family
->data
->fonts
[i
]);
2996 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2997 init_font_prop_vec(weight
, stretch
, style
, &req
);
2998 matchingfonts_sort(fonts
, &req
);
3000 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
3004 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
3006 FIXME("%p, %u.\n", iface
, index
);
3008 return DWRITE_LOCALITY_LOCAL
;
3011 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
3013 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
3015 TRACE("%p, %u, %p.\n", iface
, index
, font
);
3019 if (!family
->data
->count
)
3022 if (index
>= family
->data
->count
)
3025 return create_font(family
, index
, font
);
3028 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
3029 IDWriteFontFaceReference
**reference
)
3031 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
3032 const struct dwrite_font_data
*font
;
3034 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
3038 if (index
>= family
->data
->count
)
3041 font
= family
->data
->fonts
[index
];
3042 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)family
->collection
->factory
,
3043 font
->file
, font
->face_index
, font
->simulations
, reference
);
3046 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
3047 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
3049 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
3054 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
3056 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
3058 TRACE("%p, %p.\n", iface
, fontset
);
3060 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
3061 family
->data
->count
, fontset
);
3064 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
3066 dwritefontfamily_QueryInterface
,
3067 dwritefontfamily_AddRef
,
3068 dwritefontfamily_Release
,
3069 dwritefontfamily_GetFontCollection
,
3070 dwritefontfamily_GetFontCount
,
3071 dwritefontfamily_GetFont
,
3072 dwritefontfamily_GetFamilyNames
,
3073 dwritefontfamily_GetFirstMatchingFont
,
3074 dwritefontfamily_GetMatchingFonts
,
3075 dwritefontfamily1_GetFontLocality
,
3076 dwritefontfamily1_GetFont
,
3077 dwritefontfamily1_GetFontFaceReference
,
3078 dwritefontfamily2_GetMatchingFonts
,
3079 dwritefontfamily2_GetFontSet
,
3082 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
3084 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3085 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
3088 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
3090 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3091 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
3094 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
3096 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3097 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
3100 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
3101 IDWriteFontCollection
**collection
)
3103 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3104 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
3107 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
3109 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3110 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
3113 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
3115 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3116 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
3119 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
3121 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3122 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
3125 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
3127 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3128 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
3131 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
3132 IDWriteFontFaceReference
**reference
)
3134 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3135 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
3138 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
3140 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
3142 TRACE("%p, %p.\n", iface
, fontset
);
3144 return fontset_create_from_font_data(family
->collection
->factory
, family
->data
->fonts
,
3145 family
->data
->count
, fontset
);
3148 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
3150 dwritefontfamilylist_QueryInterface
,
3151 dwritefontfamilylist_AddRef
,
3152 dwritefontfamilylist_Release
,
3153 dwritefontfamilylist_GetFontCollection
,
3154 dwritefontfamilylist_GetFontCount
,
3155 dwritefontfamilylist_GetFont
,
3156 dwritefontfamilylist1_GetFontLocality
,
3157 dwritefontfamilylist1_GetFont
,
3158 dwritefontfamilylist1_GetFontFaceReference
,
3159 dwritefontfamilylist2_GetFontSet
,
3162 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
3163 struct dwrite_fontfamily
**family
)
3165 struct dwrite_fontfamily
*object
;
3169 if (!(object
= calloc(1, sizeof(*object
))))
3170 return E_OUTOFMEMORY
;
3172 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
3173 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
3174 object
->refcount
= 1;
3175 object
->collection
= collection
;
3176 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
3177 object
->data
= collection
->family_data
[index
];
3178 InterlockedIncrement(&object
->data
->refcount
);
3185 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
3188 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
3191 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
3193 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3195 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
3197 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
3198 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
3199 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
3200 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
3201 IsEqualIID(riid
, &IID_IUnknown
))
3204 IDWriteFontCollection3_AddRef(iface
);
3210 if (IsEqualIID(riid
, &IID_issystemcollection
))
3213 WARN("%s not implemented.\n", debugstr_guid(riid
));
3215 return E_NOINTERFACE
;
3218 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
3220 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
3222 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
3223 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
3224 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
3225 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
3226 IsEqualIID(riid
, &IID_IUnknown
))
3229 IDWriteFontCollection3_AddRef(iface
);
3233 WARN("%s not implemented.\n", debugstr_guid(riid
));
3237 return E_NOINTERFACE
;
3240 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
3242 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3243 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
3245 TRACE("%p, refcount %d.\n", collection
, refcount
);
3250 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
3252 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3253 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
3256 TRACE("%p, refcount %d.\n", iface
, refcount
);
3260 factory_detach_fontcollection(collection
->factory
, iface
);
3261 for (i
= 0; i
< collection
->count
; ++i
)
3262 release_fontfamily_data(collection
->family_data
[i
]);
3263 free(collection
->family_data
);
3270 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
3272 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3274 TRACE("%p.\n", iface
);
3276 return collection
->count
;
3279 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3280 IDWriteFontFamily
**ret
)
3282 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3283 struct dwrite_fontfamily
*family
;
3286 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3290 if (index
>= collection
->count
)
3293 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3294 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
3299 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
3303 for (i
= 0; i
< collection
->count
; ++i
)
3305 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
3306 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
3309 for (j
= 0; j
< count
; j
++)
3312 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
3313 if (SUCCEEDED(hr
) && !wcsicmp(buffer
, name
))
3321 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
3322 UINT32
*index
, BOOL
*exists
)
3324 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3326 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
3328 *index
= collection_find_family(collection
, name
);
3329 *exists
= *index
!= ~0u;
3333 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
3336 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3337 struct dwrite_fontfamily
*family
;
3338 BOOL found_font
= FALSE
;
3339 IDWriteFontFile
*file
;
3340 UINT32 face_index
, count
;
3344 TRACE("%p, %p, %p.\n", iface
, face
, font
);
3349 return E_INVALIDARG
;
3352 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
3355 face_index
= IDWriteFontFace_GetIndex(face
);
3358 for (i
= 0; i
< collection
->count
; ++i
)
3360 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
3362 for (j
= 0; j
< family_data
->count
; ++j
)
3364 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
3366 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
3375 IDWriteFontFile_Release(file
);
3378 return DWRITE_E_NOFONT
;
3380 hr
= create_fontfamily(collection
, i
, &family
);
3384 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
3385 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
3389 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
3391 FIXME("%p, %p.\n", iface
, fontset
);
3396 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
3397 IDWriteFontFamily1
**ret
)
3399 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3400 struct dwrite_fontfamily
*family
;
3403 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3407 if (index
>= collection
->count
)
3410 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3411 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
3416 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
3417 UINT32 index
, IDWriteFontFamily2
**ret
)
3419 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
3420 struct dwrite_fontfamily
*family
;
3423 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
3427 if (index
>= collection
->count
)
3430 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
3431 *ret
= &family
->IDWriteFontFamily2_iface
;
3436 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
3437 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
3438 IDWriteFontList2
**fontlist
)
3440 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
3445 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
3447 FIXME("%p.\n", iface
);
3449 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
3452 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
3454 FIXME("%p, %p.\n", iface
, fontset
);
3459 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
3461 FIXME("%p.\n", iface
);
3466 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
3468 dwritefontcollection_QueryInterface
,
3469 dwritefontcollection_AddRef
,
3470 dwritefontcollection_Release
,
3471 dwritefontcollection_GetFontFamilyCount
,
3472 dwritefontcollection_GetFontFamily
,
3473 dwritefontcollection_FindFamilyName
,
3474 dwritefontcollection_GetFontFromFontFace
,
3475 dwritefontcollection1_GetFontSet
,
3476 dwritefontcollection1_GetFontFamily
,
3477 dwritefontcollection2_GetFontFamily
,
3478 dwritefontcollection2_GetMatchingFonts
,
3479 dwritefontcollection2_GetFontFamilyModel
,
3480 dwritefontcollection2_GetFontSet
,
3481 dwritefontcollection3_GetExpirationEvent
,
3484 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
3486 dwritesystemfontcollection_QueryInterface
,
3487 dwritefontcollection_AddRef
,
3488 dwritefontcollection_Release
,
3489 dwritefontcollection_GetFontFamilyCount
,
3490 dwritefontcollection_GetFontFamily
,
3491 dwritefontcollection_FindFamilyName
,
3492 dwritefontcollection_GetFontFromFontFace
,
3493 dwritefontcollection1_GetFontSet
,
3494 dwritefontcollection1_GetFontFamily
,
3495 dwritefontcollection2_GetFontFamily
,
3496 dwritefontcollection2_GetMatchingFonts
,
3497 dwritefontcollection2_GetFontFamilyModel
,
3498 dwritefontcollection2_GetFontSet
,
3499 dwritefontcollection3_GetExpirationEvent
,
3502 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
3504 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
3505 sizeof(*family_data
->fonts
)))
3507 return E_OUTOFMEMORY
;
3510 family_data
->fonts
[family_data
->count
++] = font_data
;
3511 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
3512 family_data
->has_normal_face
= 1;
3513 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3514 family_data
->has_oblique_face
= 1;
3516 family_data
->has_italic_face
= 1;
3520 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
3521 struct dwrite_fontfamily_data
*family
)
3523 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
3524 sizeof(*collection
->family_data
)))
3526 return E_OUTOFMEMORY
;
3529 collection
->family_data
[collection
->count
++] = family
;
3533 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
3535 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
3536 collection
->refcount
= 1;
3537 collection
->count
= 0;
3538 collection
->size
= 0;
3539 collection
->family_data
= NULL
;
3544 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3546 IDWriteFontFileLoader
*loader
;
3553 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3557 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3561 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3562 IDWriteFontFileLoader_Release(loader
);
3569 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
3571 BOOL exists
= FALSE
;
3576 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, L
"en-us", &index
, &exists
);
3577 if (FAILED(hr
) || !exists
)
3580 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
3583 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
3587 while (iswspace(*in
))
3591 if (!(len
= wcslen(in
)))
3594 while (iswspace(in
[len
-1]))
3597 memcpy(ret
, in
, len
*sizeof(WCHAR
));
3606 INT len
; /* token length */
3607 INT fulllen
; /* full length including following separators */
3610 static inline BOOL
is_name_separator_char(WCHAR ch
)
3612 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
3615 struct name_pattern
{
3616 const WCHAR
*part1
; /* NULL indicates end of list */
3617 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
3620 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
3622 const struct name_pattern
*pattern
;
3623 struct name_token
*token
;
3626 while ((pattern
= &patterns
[i
++])->part1
)
3628 int len_part1
= wcslen(pattern
->part1
);
3629 int len_part2
= pattern
->part2
? wcslen(pattern
->part2
) : 0;
3631 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
)
3635 /* simple case with single part pattern */
3636 if (token
->len
!= len_part1
)
3639 if (!wcsnicmp(token
->ptr
, pattern
->part1
, len_part1
))
3641 if (match
) *match
= *token
;
3642 list_remove(&token
->entry
);
3649 struct name_token
*next_token
;
3650 struct list
*next_entry
;
3652 /* pattern parts are stored in reading order, tokens list is reversed */
3653 if (token
->len
< len_part2
)
3656 /* it's possible to have combined string as a token, like ExtraCondensed */
3657 if (token
->len
== len_part1
+ len_part2
)
3659 if (wcsnicmp(token
->ptr
, pattern
->part1
, len_part1
))
3662 if (wcsnicmp(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3665 /* combined string match */
3666 if (match
) *match
= *token
;
3667 list_remove(&token
->entry
);
3672 /* now it's only possible to have two tokens matched to respective pattern parts */
3673 if (token
->len
!= len_part2
)
3676 next_entry
= list_next(tokens
, &token
->entry
);
3678 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3679 if (next_token
->len
!= len_part1
)
3682 if (wcsnicmp(token
->ptr
, pattern
->part2
, len_part2
))
3685 if (wcsnicmp(next_token
->ptr
, pattern
->part1
, len_part1
))
3688 /* both parts matched, remove tokens */
3690 match
->ptr
= next_token
->ptr
;
3691 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3693 list_remove(&token
->entry
);
3694 list_remove(&next_token
->entry
);
3710 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3712 static const struct name_pattern italic_patterns
[] =
3722 static const struct name_pattern oblique_patterns
[] =
3732 /* italic patterns first */
3733 if (match_pattern_list(tokens
, italic_patterns
, match
))
3734 return DWRITE_FONT_STYLE_ITALIC
;
3736 /* oblique patterns */
3737 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3738 return DWRITE_FONT_STYLE_OBLIQUE
;
3743 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3744 struct name_token
*match
)
3746 static const struct name_pattern ultracondensed_patterns
[] =
3748 { L
"extra", L
"compressed" },
3749 { L
"ext", L
"compressed" },
3750 { L
"ultra", L
"compressed" },
3751 { L
"ultra", L
"condensed" },
3752 { L
"ultra", L
"cond" },
3756 static const struct name_pattern extracondensed_patterns
[] =
3759 { L
"extra", L
"condensed" },
3760 { L
"ext", L
"condensed" },
3761 { L
"extra", L
"cond" },
3762 { L
"ext", L
"cond" },
3766 static const struct name_pattern semicondensed_patterns
[] =
3770 { L
"semi", L
"condensed" },
3771 { L
"semi", L
"cond" },
3775 static const struct name_pattern semiexpanded_patterns
[] =
3778 { L
"semi", L
"expanded" },
3779 { L
"semi", L
"extended" },
3783 static const struct name_pattern extraexpanded_patterns
[] =
3785 { L
"extra", L
"expanded" },
3786 { L
"ext", L
"expanded" },
3787 { L
"extra", L
"extended" },
3788 { L
"ext", L
"extended" },
3792 static const struct name_pattern ultraexpanded_patterns
[] =
3794 { L
"ultra", L
"expanded" },
3795 { L
"ultra", L
"extended" },
3799 static const struct name_pattern condensed_patterns
[] =
3806 static const struct name_pattern expanded_patterns
[] =
3813 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3814 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3816 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3817 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3819 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3820 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3822 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3823 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3825 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3826 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3828 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3829 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3831 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3832 return DWRITE_FONT_STRETCH_CONDENSED
;
3834 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3835 return DWRITE_FONT_STRETCH_EXPANDED
;
3840 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3841 struct name_token
*match
)
3843 static const struct name_pattern thin_patterns
[] =
3845 { L
"extra", L
"thin" },
3846 { L
"ext", L
"thin" },
3847 { L
"ultra", L
"thin" },
3851 static const struct name_pattern extralight_patterns
[] =
3853 { L
"extra", L
"light" },
3854 { L
"ext", L
"light" },
3855 { L
"ultra", L
"light" },
3859 static const struct name_pattern semilight_patterns
[] =
3861 { L
"semi", L
"light" },
3865 static const struct name_pattern demibold_patterns
[] =
3867 { L
"semi", L
"bold" },
3868 { L
"demi", L
"bold" },
3872 static const struct name_pattern extrabold_patterns
[] =
3874 { L
"extra", L
"bold" },
3875 { L
"ext", L
"bold" },
3876 { L
"ultra", L
"bold" },
3880 static const struct name_pattern extrablack_patterns
[] =
3882 { L
"extra", L
"black" },
3883 { L
"ext", L
"black" },
3884 { L
"ultra", L
"black" },
3888 static const struct name_pattern bold_patterns
[] =
3894 static const struct name_pattern thin2_patterns
[] =
3900 static const struct name_pattern light_patterns
[] =
3906 static const struct name_pattern medium_patterns
[] =
3912 static const struct name_pattern black_patterns
[] =
3920 static const struct name_pattern demibold2_patterns
[] =
3926 static const struct name_pattern extrabold2_patterns
[] =
3932 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3933 matching pattern. */
3935 if (match_pattern_list(tokens
, thin_patterns
, match
))
3936 return DWRITE_FONT_WEIGHT_THIN
;
3938 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3939 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3941 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3942 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3944 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3945 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3947 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3948 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3950 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3951 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3953 if (match_pattern_list(tokens
, bold_patterns
, match
))
3954 return DWRITE_FONT_WEIGHT_BOLD
;
3956 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3957 return DWRITE_FONT_WEIGHT_THIN
;
3959 if (match_pattern_list(tokens
, light_patterns
, match
))
3960 return DWRITE_FONT_WEIGHT_LIGHT
;
3962 if (match_pattern_list(tokens
, medium_patterns
, match
))
3963 return DWRITE_FONT_WEIGHT_MEDIUM
;
3965 if (match_pattern_list(tokens
, black_patterns
, match
))
3966 return DWRITE_FONT_WEIGHT_BLACK
;
3968 if (match_pattern_list(tokens
, black_patterns
, match
))
3969 return DWRITE_FONT_WEIGHT_BLACK
;
3971 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3972 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3974 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3975 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3977 /* FIXME: use abbreviated names to extract weight */
3982 struct knownweight_entry
3985 DWRITE_FONT_WEIGHT weight
;
3988 static int __cdecl
compare_knownweights(const void *a
, const void* b
)
3990 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3991 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3994 if (target
> entry
->weight
)
3996 else if (target
< entry
->weight
)
4002 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
4004 static const struct knownweight_entry knownweights
[] =
4006 { L
"Thin", DWRITE_FONT_WEIGHT_THIN
},
4007 { L
"Extra Light", DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
4008 { L
"Light", DWRITE_FONT_WEIGHT_LIGHT
},
4009 { L
"Semi Light", DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
4010 { L
"Medium", DWRITE_FONT_WEIGHT_MEDIUM
},
4011 { L
"Demi Bold", DWRITE_FONT_WEIGHT_DEMI_BOLD
},
4012 { L
"Bold", DWRITE_FONT_WEIGHT_BOLD
},
4013 { L
"Extra Bold", DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
4014 { L
"Black", DWRITE_FONT_WEIGHT_BLACK
},
4015 { L
"Extra Black", DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
4017 const struct knownweight_entry
*ptr
;
4019 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(*knownweights
),
4020 compare_knownweights
);
4026 wcscpy(nameW
, ptr
->nameW
);
4030 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
4032 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
4033 strW
[name
->len
] = 0;
4036 /* Modifies facenameW string, and returns pointer to regular term that was removed */
4037 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
4039 static const WCHAR
*regular_patterns
[] =
4049 const WCHAR
*regular_ptr
= NULL
, *ptr
;
4053 len
= wcslen(facenameW
);
4055 /* remove rightmost regular variant from face name */
4056 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++]))
4058 int pattern_len
= wcslen(ptr
);
4061 if (pattern_len
> len
)
4064 src
= facenameW
+ len
- pattern_len
;
4065 while (src
>= facenameW
)
4067 if (!wcsnicmp(src
, ptr
, pattern_len
))
4069 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
4070 len
= wcslen(facenameW
);
4082 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
4091 struct name_token
*token
= malloc(sizeof(*token
));
4096 while (*ptr
&& !is_name_separator_char(*ptr
)) {
4102 /* skip separators */
4103 while (is_name_separator_char(*ptr
)) {
4108 list_add_head(tokens
, &token
->entry
);
4112 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
4114 struct name_token
*token
, *token2
;
4115 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
4118 list_remove(&token
->entry
);
4120 /* don't include last separator */
4121 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
4122 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
4130 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
4132 struct name_token stretch_name
, weight_name
, style_name
;
4133 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
4134 WCHAR weightW
[32], stretchW
[32], styleW
[32];
4135 const WCHAR
*regular_ptr
= NULL
;
4136 DWRITE_FONT_STRETCH stretch
;
4137 DWRITE_FONT_WEIGHT weight
;
4141 /* remove leading and trailing spaces from family and face name */
4142 trim_spaces(familyW
, familynameW
);
4143 len
= trim_spaces(faceW
, facenameW
);
4145 /* remove rightmost regular variant from face name */
4146 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
4148 /* append face name to family name, FIXME check if face name is a substring of family name */
4151 wcscat(familynameW
, L
" ");
4152 wcscat(familynameW
, facenameW
);
4155 /* tokenize with " .-_" */
4156 fontname_tokenize(&tokens
, familynameW
);
4158 /* extract and resolve style */
4159 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
4161 /* extract stretch */
4162 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
4164 /* extract weight */
4165 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
4167 /* resolve weight */
4168 if (weight
!= font
->weight
)
4170 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
4171 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
4172 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
4173 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
4174 !(abs((int)weight
- (int)font
->weight
) <= 150 &&
4175 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
4176 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
4177 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
))
4179 font
->weight
= weight
;
4183 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
4184 it's leaning in opposite direction from normal comparing to specified stretch or if specified
4185 stretch itself is normal (extracted stretch is never normal). */
4186 if (stretch
!= font
->stretch
) {
4187 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
4188 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
4189 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
4191 font
->stretch
= stretch
;
4195 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
4197 /* get final combined string from what's left in token list, list is released */
4198 fontname_tokens_to_str(&tokens
, finalW
);
4200 if (!wcscmp(familyW
, finalW
))
4203 /* construct face name */
4204 wcscpy(familyW
, finalW
);
4206 /* resolved weight name */
4207 if (weight_name
.ptr
)
4208 font_name_token_to_str(&weight_name
, weightW
);
4209 /* ignore normal weight */
4210 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
4212 /* for known weight values use appropriate names */
4213 else if (is_known_weight_value(font
->weight
, weightW
)) {
4215 /* use Wnnn format as a fallback in case weight is not one of known values */
4217 swprintf(weightW
, ARRAY_SIZE(weightW
), L
"W%d", font
->weight
);
4219 /* resolved stretch name */
4220 if (stretch_name
.ptr
)
4221 font_name_token_to_str(&stretch_name
, stretchW
);
4222 /* ignore normal stretch */
4223 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
4225 /* use predefined stretch names */
4228 static const WCHAR
*stretchnamesW
[] =
4230 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4235 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
4241 wcscpy(stretchW
, stretchnamesW
[font
->stretch
]);
4244 /* resolved style name */
4246 font_name_token_to_str(&style_name
, styleW
);
4247 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
4249 /* use predefined names */
4251 wcscpy(styleW
, font
->style
== DWRITE_FONT_STYLE_ITALIC
? L
"Italic" : L
"Oblique");
4253 /* use Regular match if it was found initially */
4254 if (!*weightW
&& !*stretchW
&& !*styleW
)
4255 wcscpy(faceW
, regular_ptr
? regular_ptr
: L
"Regular");
4260 if (*stretchW
) wcscpy(faceW
, stretchW
);
4264 if (*faceW
) wcscat(faceW
, L
" ");
4265 wcscat(faceW
, weightW
);
4270 if (*faceW
) wcscat(faceW
, L
" ");
4271 wcscat(faceW
, styleW
);
4275 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
4279 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
4281 static const float width_axis_values
[] =
4283 0.0f
, /* DWRITE_FONT_STRETCH_UNDEFINED */
4284 50.0f
, /* DWRITE_FONT_STRETCH_ULTRA_CONDENSED */
4285 62.5f
, /* DWRITE_FONT_STRETCH_EXTRA_CONDENSED */
4286 75.0f
, /* DWRITE_FONT_STRETCH_CONDENSED */
4287 87.5f
, /* DWRITE_FONT_STRETCH_SEMI_CONDENSED */
4288 100.0f
, /* DWRITE_FONT_STRETCH_NORMAL */
4289 112.5f
, /* DWRITE_FONT_STRETCH_SEMI_EXPANDED */
4290 125.0f
, /* DWRITE_FONT_STRETCH_EXPANDED */
4291 150.0f
, /* DWRITE_FONT_STRETCH_EXTRA_EXPANDED */
4292 200.0f
, /* DWRITE_FONT_STRETCH_ULTRA_EXPANDED */
4295 struct file_stream_desc stream_desc
;
4296 struct dwrite_font_props props
;
4297 struct dwrite_font_data
*data
;
4298 WCHAR familyW
[255], faceW
[255];
4303 if (!(data
= calloc(1, sizeof(*data
))))
4304 return E_OUTOFMEMORY
;
4307 data
->file
= desc
->file
;
4308 data
->face_index
= desc
->index
;
4309 data
->face_type
= desc
->face_type
;
4310 IDWriteFontFile_AddRef(data
->file
);
4312 stream_desc
.stream
= desc
->stream
;
4313 stream_desc
.face_type
= desc
->face_type
;
4314 stream_desc
.face_index
= desc
->index
;
4315 opentype_get_font_properties(&stream_desc
, &props
);
4316 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
4317 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
4319 /* get family name from font file */
4320 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
4322 WARN("unable to get family name from font\n");
4323 release_font_data(data
);
4327 data
->style
= props
.style
;
4328 data
->stretch
= props
.stretch
;
4329 data
->weight
= props
.weight
;
4330 data
->panose
= props
.panose
;
4331 data
->fontsig
= props
.fontsig
;
4332 data
->lf
= props
.lf
;
4333 data
->flags
= props
.flags
;
4335 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4336 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
4337 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
4338 set_en_localizedstring(data
->family_names
, familyW
);
4339 set_en_localizedstring(data
->names
, faceW
);
4342 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4344 data
->axis
[0].axisTag
= DWRITE_FONT_AXIS_TAG_WEIGHT
;
4345 data
->axis
[0].value
= props
.weight
;
4346 data
->axis
[1].axisTag
= DWRITE_FONT_AXIS_TAG_WIDTH
;
4347 data
->axis
[1].value
= width_axis_values
[props
.stretch
];
4348 data
->axis
[2].axisTag
= DWRITE_FONT_AXIS_TAG_ITALIC
;
4349 data
->axis
[2].value
= data
->style
== DWRITE_FONT_STYLE_ITALIC
? 1.0f
: 0.0f
;
4355 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS simulations
,
4356 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
4358 struct dwrite_font_data
*data
;
4362 if (!(data
= calloc(1, sizeof(*data
))))
4363 return E_OUTOFMEMORY
;
4367 data
->simulations
|= simulations
;
4368 if (simulations
& DWRITE_FONT_SIMULATIONS_BOLD
)
4369 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
4370 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
)
4371 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
4372 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
4374 IDWriteFontFile_AddRef(data
->file
);
4375 IDWriteLocalizedStrings_AddRef(data
->family_names
);
4377 create_localizedstrings(&data
->names
);
4378 add_localizedstring(data
->names
, L
"en-us", facenameW
);
4380 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
4386 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
4388 struct dwrite_fontfamily_data
*data
;
4390 if (!(data
= calloc(1, sizeof(*data
))))
4391 return E_OUTOFMEMORY
;
4394 data
->familyname
= familyname
;
4395 IDWriteLocalizedStrings_AddRef(familyname
);
4402 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
4404 size_t i
, j
, heaviest
;
4406 for (i
= 0; i
< family
->count
; ++i
)
4408 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
4411 if (family
->fonts
[i
]->bold_sim_tested
)
4414 family
->fonts
[i
]->bold_sim_tested
= 1;
4415 for (j
= i
; j
< family
->count
; ++j
)
4417 if (family
->fonts
[j
]->bold_sim_tested
)
4420 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
4421 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4422 if (family
->fonts
[j
]->weight
> weight
) {
4423 weight
= family
->fonts
[j
]->weight
;
4426 family
->fonts
[j
]->bold_sim_tested
= 1;
4430 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550)
4432 static const struct name_pattern weightsim_patterns
[] =
4434 { L
"extra", L
"light" },
4435 { L
"ext", L
"light" },
4436 { L
"ultra", L
"light" },
4437 { L
"semi", L
"light" },
4438 { L
"semi", L
"bold" },
4439 { L
"demi", L
"bold" },
4448 WCHAR facenameW
[255], initialW
[255];
4449 struct dwrite_font_data
*boldface
;
4452 /* add Bold simulation based on heaviest face data */
4454 /* Simulated face name should only contain Bold as weight term,
4455 so remove existing regular and weight terms. */
4456 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
4457 facename_remove_regular_term(initialW
, -1);
4459 /* remove current weight pattern */
4460 fontname_tokenize(&tokens
, initialW
);
4461 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
4462 fontname_tokens_to_str(&tokens
, facenameW
);
4464 /* Bold suffix for new name */
4465 if (*facenameW
) wcscat(facenameW
, L
" ");
4466 wcscat(facenameW
, L
"Bold");
4468 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
4469 boldface
->bold_sim_tested
= 1;
4470 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
4471 fontfamily_add_font(family
, boldface
);
4477 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
4481 for (i
= 0; i
< family
->count
; ++i
)
4483 UINT32 regular
= ~0u, oblique
= ~0u;
4484 struct dwrite_font_data
*obliqueface
;
4485 WCHAR facenameW
[255];
4487 if (family
->fonts
[i
]->oblique_sim_tested
)
4490 family
->fonts
[i
]->oblique_sim_tested
= 1;
4491 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4493 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4496 /* find regular style with same weight/stretch values */
4497 for (j
= i
; j
< family
->count
; ++j
)
4499 if (family
->fonts
[j
]->oblique_sim_tested
)
4502 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
4503 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
4505 family
->fonts
[j
]->oblique_sim_tested
= 1;
4506 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
4509 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
4513 if (regular
!= ~0u && oblique
!= ~0u)
4517 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
4521 /* regular face exists, and corresponding oblique is present as well, nothing to do */
4525 /* add oblique simulation based on this regular face */
4527 /* remove regular term if any, append 'Oblique' */
4528 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
4529 facename_remove_regular_term(facenameW
, -1);
4531 if (*facenameW
) wcscat(facenameW
, L
" ");
4532 wcscat(facenameW
, L
"Oblique");
4534 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
4535 obliqueface
->oblique_sim_tested
= 1;
4536 obliqueface
->lf
.lfItalic
= 1;
4537 fontfamily_add_font(family
, obliqueface
);
4542 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
4543 const WCHAR
*replacement_name
)
4545 UINT32 i
= collection_find_family(collection
, replacement_name
);
4546 struct dwrite_fontfamily_data
*target
;
4547 IDWriteLocalizedStrings
*strings
;
4550 /* replacement does not exist */
4554 hr
= create_localizedstrings(&strings
);
4558 /* add a new family with target name, reuse font data from replacement */
4559 add_localizedstring(strings
, L
"en-us", target_name
);
4560 hr
= init_fontfamily_data(strings
, &target
);
4562 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
4565 for (i
= 0; i
< replacement
->count
; ++i
)
4567 fontfamily_add_font(target
, replacement
->fonts
[i
]);
4568 addref_font_data(replacement
->fonts
[i
]);
4571 fontcollection_add_family(collection
, target
);
4572 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
4573 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
4575 IDWriteLocalizedStrings_Release(strings
);
4579 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
4580 system font collections. */
4581 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
4583 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
4588 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
4591 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
4596 max_namelen
++; /* returned value doesn't include room for '\0' */
4597 name
= malloc(max_namelen
* sizeof(WCHAR
));
4598 data
= malloc(max_datalen
);
4600 datalen
= max_datalen
;
4601 namelen
= max_namelen
;
4602 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
4603 if (collection_find_family(collection
, name
) == ~0u) {
4604 if (type
== REG_MULTI_SZ
) {
4605 WCHAR
*replacement
= data
;
4606 while (*replacement
) {
4607 if (fontcollection_add_replacement(collection
, name
, replacement
))
4609 replacement
+= wcslen(replacement
) + 1;
4612 else if (type
== REG_SZ
)
4613 fontcollection_add_replacement(collection
, name
, data
);
4616 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
4618 datalen
= max_datalen
;
4619 namelen
= max_namelen
;
4627 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
4628 IDWriteFontCollection3
**ret
)
4630 struct fontfile_enum
{
4632 IDWriteFontFile
*file
;
4634 struct fontfile_enum
*fileenum
, *fileenum2
;
4635 struct dwrite_fontcollection
*collection
;
4636 struct list scannedfiles
;
4637 BOOL current
= FALSE
;
4643 if (!(collection
= calloc(1, sizeof(*collection
))))
4644 return E_OUTOFMEMORY
;
4646 hr
= init_font_collection(collection
, is_system
);
4653 *ret
= &collection
->IDWriteFontCollection3_iface
;
4655 TRACE("building font collection:\n");
4657 list_init(&scannedfiles
);
4658 while (hr
== S_OK
) {
4659 DWRITE_FONT_FACE_TYPE face_type
;
4660 DWRITE_FONT_FILE_TYPE file_type
;
4661 BOOL supported
, same
= FALSE
;
4662 IDWriteFontFileStream
*stream
;
4663 IDWriteFontFile
*file
;
4667 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4668 if (FAILED(hr
) || !current
)
4671 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4675 /* check if we've scanned this file already */
4676 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4677 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4682 IDWriteFontFile_Release(file
);
4686 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4687 IDWriteFontFile_Release(file
);
4691 /* Unsupported formats are skipped. */
4692 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4693 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4694 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4695 IDWriteFontFileStream_Release(stream
);
4696 IDWriteFontFile_Release(file
);
4701 /* add to scanned list */
4702 fileenum
= malloc(sizeof(*fileenum
));
4703 fileenum
->file
= file
;
4704 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4706 for (i
= 0; i
< face_count
; ++i
)
4708 struct dwrite_font_data
*font_data
;
4709 struct fontface_desc desc
;
4713 desc
.factory
= factory
;
4714 desc
.face_type
= face_type
;
4716 desc
.stream
= stream
;
4718 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4719 desc
.font_data
= NULL
;
4721 /* Allocate an initialize new font data structure. */
4722 hr
= init_font_data(&desc
, &font_data
);
4725 /* move to next one */
4730 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4732 /* ignore dot named faces */
4733 if (familyW
[0] == '.')
4735 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4736 release_font_data(font_data
);
4740 index
= collection_find_family(collection
, familyW
);
4742 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4744 struct dwrite_fontfamily_data
*family_data
;
4746 /* create and init new family */
4747 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4749 /* add font to family, family - to collection */
4750 hr
= fontfamily_add_font(family_data
, font_data
);
4752 hr
= fontcollection_add_family(collection
, family_data
);
4755 release_fontfamily_data(family_data
);
4761 release_font_data(font_data
);
4766 IDWriteFontFileStream_Release(stream
);
4769 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
)
4771 IDWriteFontFile_Release(fileenum
->file
);
4772 list_remove(&fileenum
->entry
);
4776 for (i
= 0; i
< collection
->count
; ++i
)
4778 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4779 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4783 fontcollection_add_replacements(collection
);
4785 collection
->factory
= factory
;
4786 IDWriteFactory7_AddRef(factory
);
4791 struct system_fontfile_enumerator
4793 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4796 IDWriteFactory7
*factory
;
4801 DWORD filename_size
;
4804 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4806 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4809 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4811 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4812 IDWriteFontFileEnumerator_AddRef(iface
);
4817 WARN("%s not implemented.\n", debugstr_guid(riid
));
4821 return E_NOINTERFACE
;
4824 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4826 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4827 return InterlockedIncrement(&enumerator
->refcount
);
4830 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4832 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4833 ULONG refcount
= InterlockedDecrement(&enumerator
->refcount
);
4837 IDWriteFactory7_Release(enumerator
->factory
);
4838 RegCloseKey(enumerator
->hkey
);
4839 free(enumerator
->filename
);
4846 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4850 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4851 if (!wcschr(filename
, '\\'))
4853 WCHAR fullpathW
[MAX_PATH
];
4855 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4856 wcscat(fullpathW
, L
"\\fonts\\");
4857 wcscat(fullpathW
, filename
);
4859 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4862 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4867 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4869 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4873 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4876 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4879 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4881 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4882 WCHAR name_buf
[256], *name
= name_buf
;
4883 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4888 enumerator
->index
++;
4890 /* iterate until we find next string value */
4893 name_count
= max_name_count
;
4894 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4896 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4897 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4898 if (r
== ERROR_MORE_DATA
) {
4899 if (name_count
>= max_name_count
) {
4900 if (name
!= name_buf
) free(name
);
4901 max_name_count
*= 2;
4902 name
= malloc(max_name_count
* sizeof(*name
));
4903 if (!name
) return E_OUTOFMEMORY
;
4905 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
))
4907 free(enumerator
->filename
);
4908 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4909 if (!(enumerator
->filename
= malloc(enumerator
->filename_size
)))
4916 } while (r
== ERROR_MORE_DATA
);
4918 if (r
!= ERROR_SUCCESS
) {
4919 enumerator
->filename
[0] = 0;
4922 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4923 if (type
== REG_SZ
&& *name
!= '@') {
4927 enumerator
->index
++;
4929 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4932 if (name
!= name_buf
) free(name
);
4936 static const IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4938 systemfontfileenumerator_QueryInterface
,
4939 systemfontfileenumerator_AddRef
,
4940 systemfontfileenumerator_Release
,
4941 systemfontfileenumerator_MoveNext
,
4942 systemfontfileenumerator_GetCurrentFontFile
4945 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4947 struct system_fontfile_enumerator
*enumerator
;
4951 if (!(enumerator
= calloc(1, sizeof(*enumerator
))))
4952 return E_OUTOFMEMORY
;
4954 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4955 enumerator
->refcount
= 1;
4956 enumerator
->factory
= factory
;
4957 enumerator
->index
= -1;
4958 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4959 enumerator
->filename
= malloc(enumerator
->filename_size
);
4960 if (!enumerator
->filename
)
4963 return E_OUTOFMEMORY
;
4966 IDWriteFactory7_AddRef(factory
);
4968 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 0,
4969 GENERIC_READ
, &enumerator
->hkey
))
4971 ERR("failed to open fonts list key\n");
4972 IDWriteFactory7_Release(factory
);
4973 free(enumerator
->filename
);
4978 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4983 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4985 IDWriteFontFileEnumerator
*enumerator
;
4990 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4994 TRACE("building system font collection for factory %p\n", factory
);
4995 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4996 IDWriteFontFileEnumerator_Release(enumerator
);
5000 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
5001 const WCHAR
*keynameW
, const WCHAR
*pathW
)
5003 struct dwrite_fontfamily_data
*family_data
;
5004 IDWriteLocalizedStrings
*names
;
5005 DWRITE_FONT_FACE_TYPE face_type
;
5006 DWRITE_FONT_FILE_TYPE file_type
;
5007 IDWriteFontFileStream
*stream
;
5008 IDWriteFontFile
*file
;
5009 UINT32 face_count
, i
;
5013 /* create font file from this path */
5014 hr
= create_local_file_reference(factory
, pathW
, &file
);
5018 if (FAILED(get_filestream_from_file(file
, &stream
))) {
5019 IDWriteFontFile_Release(file
);
5023 /* Unsupported formats are skipped. */
5024 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
5025 if (FAILED(hr
) || !supported
|| face_count
== 0) {
5026 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
5027 IDWriteFontFileStream_Release(stream
);
5028 IDWriteFontFile_Release(file
);
5032 /* create and init new family */
5034 /* Family names are added for non-specific locale, represented with empty string.
5035 Default family appears with empty family name. */
5036 create_localizedstrings(&names
);
5037 if (!wcsicmp(keynameW
, L
"SystemDefaultEUDCFont"))
5038 add_localizedstring(names
, L
"", L
"");
5040 add_localizedstring(names
, L
"", keynameW
);
5042 hr
= init_fontfamily_data(names
, &family_data
);
5043 IDWriteLocalizedStrings_Release(names
);
5045 IDWriteFontFile_Release(file
);
5049 /* fill with faces */
5050 for (i
= 0; i
< face_count
; i
++) {
5051 struct dwrite_font_data
*font_data
;
5052 struct fontface_desc desc
;
5054 /* Allocate new font data structure. */
5055 desc
.factory
= factory
;
5056 desc
.face_type
= face_type
;
5059 desc
.stream
= stream
;
5060 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
5061 desc
.font_data
= NULL
;
5063 hr
= init_font_data(&desc
, &font_data
);
5067 /* add font to family */
5068 hr
= fontfamily_add_font(family_data
, font_data
);
5070 release_font_data(font_data
);
5073 /* add family to collection */
5074 hr
= fontcollection_add_family(collection
, family_data
);
5076 release_fontfamily_data(family_data
);
5077 IDWriteFontFileStream_Release(stream
);
5078 IDWriteFontFile_Release(file
);
5083 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
5085 struct dwrite_fontcollection
*collection
;
5086 WCHAR eudckeypathW
[16];
5094 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
5098 if (!(collection
= calloc(1, sizeof(*collection
))))
5099 return E_OUTOFMEMORY
;
5101 hr
= init_font_collection(collection
, FALSE
);
5108 *ret
= &collection
->IDWriteFontCollection3_iface
;
5109 collection
->factory
= factory
;
5110 IDWriteFactory7_AddRef(factory
);
5112 /* return empty collection if EUDC fonts are not configured */
5113 swprintf(eudckeypathW
, ARRAY_SIZE(eudckeypathW
), L
"EUDC\\%u", GetACP());
5114 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
5117 retval
= ERROR_SUCCESS
;
5119 while (retval
!= ERROR_NO_MORE_ITEMS
) {
5120 WCHAR keynameW
[64], pathW
[MAX_PATH
];
5121 DWORD type
, path_len
, name_len
;
5123 path_len
= ARRAY_SIZE(pathW
);
5124 name_len
= ARRAY_SIZE(keynameW
);
5125 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
5126 if (retval
|| type
!= REG_SZ
)
5129 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
5131 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
5133 RegCloseKey(eudckey
);
5135 /* try to add global default if not defined for specific codepage */
5137 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, L
"",
5139 if (FAILED(hr
) || !exists
)
5141 hr
= eudc_collection_add_family(factory
, collection
, L
"", L
"EUDC.TTE");
5143 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
5146 /* EUDC collection offers simulated faces too */
5147 for (i
= 0; i
< collection
->count
; ++i
)
5149 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
5150 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
5156 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
5158 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5160 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
5163 IDWriteFontFile_AddRef(iface
);
5167 WARN("%s not implemented.\n", debugstr_guid(riid
));
5170 return E_NOINTERFACE
;
5173 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
5175 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5176 ULONG refcount
= InterlockedIncrement(&file
->refcount
);
5178 TRACE("%p, refcount %d.\n", iface
, refcount
);
5183 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
5185 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5186 ULONG refcount
= InterlockedDecrement(&file
->refcount
);
5188 TRACE("%p, refcount %d.\n", iface
, refcount
);
5192 IDWriteFontFileLoader_Release(file
->loader
);
5194 IDWriteFontFileStream_Release(file
->stream
);
5195 free(file
->reference_key
);
5202 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **key
, UINT32
*key_size
)
5204 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5206 TRACE("%p, %p, %p.\n", iface
, key
, key_size
);
5208 *key
= file
->reference_key
;
5209 *key_size
= file
->key_size
;
5214 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**loader
)
5216 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5218 TRACE("%p, %p.\n", iface
, loader
);
5220 *loader
= file
->loader
;
5221 IDWriteFontFileLoader_AddRef(*loader
);
5226 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
5227 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
5229 struct dwrite_fontfile
*file
= impl_from_IDWriteFontFile(iface
);
5230 IDWriteFontFileStream
*stream
;
5233 TRACE("%p, %p, %p, %p, %p.\n", iface
, is_supported
, file_type
, face_type
, face_count
);
5235 *is_supported
= FALSE
;
5236 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
5238 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
5241 hr
= IDWriteFontFileLoader_CreateStreamFromKey(file
->loader
, file
->reference_key
, file
->key_size
, &stream
);
5245 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
5247 /* TODO: Further Analysis */
5248 IDWriteFontFileStream_Release(stream
);
5252 static const IDWriteFontFileVtbl dwritefontfilevtbl
=
5254 dwritefontfile_QueryInterface
,
5255 dwritefontfile_AddRef
,
5256 dwritefontfile_Release
,
5257 dwritefontfile_GetReferenceKey
,
5258 dwritefontfile_GetLoader
,
5259 dwritefontfile_Analyze
,
5262 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
5263 IDWriteFontFile
**ret
)
5265 struct dwrite_fontfile
*file
;
5270 file
= calloc(1, sizeof(*file
));
5271 key
= malloc(key_size
);
5276 return E_OUTOFMEMORY
;
5279 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
5281 IDWriteFontFileLoader_AddRef(loader
);
5282 file
->loader
= loader
;
5283 file
->stream
= NULL
;
5284 file
->reference_key
= key
;
5285 memcpy(file
->reference_key
, reference_key
, key_size
);
5286 file
->key_size
= key_size
;
5288 *ret
= &file
->IDWriteFontFile_iface
;
5293 static UINT64
dwrite_fontface_get_font_object(struct dwrite_fontface
*fontface
)
5295 struct create_font_object_params create_params
;
5296 struct release_font_object_params release_params
;
5297 UINT64 font_object
, size
;
5298 const void *data_ptr
;
5301 if (!fontface
->font_object
&& SUCCEEDED(IDWriteFontFileStream_GetFileSize(fontface
->stream
, &size
)))
5303 if (SUCCEEDED(IDWriteFontFileStream_ReadFileFragment(fontface
->stream
, &data_ptr
, 0, size
, &data_context
)))
5305 create_params
.data
= data_ptr
;
5306 create_params
.size
= size
;
5307 create_params
.index
= fontface
->index
;
5308 create_params
.object
= &font_object
;
5310 UNIX_CALL(create_font_object
, &create_params
);
5314 WARN("Backend failed to create font object.\n");
5315 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, data_context
);
5319 if (!InterlockedCompareExchange64((LONGLONG
*)&fontface
->font_object
, font_object
, 0))
5321 fontface
->data_context
= data_context
;
5325 release_params
.object
= font_object
;
5326 UNIX_CALL(release_font_object
, &release_params
);
5327 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, data_context
);
5332 return fontface
->font_object
;
5335 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
5337 struct file_stream_desc stream_desc
;
5338 struct dwrite_font_data
*font_data
;
5339 struct dwrite_fontface
*fontface
;
5345 if (!(fontface
= calloc(1, sizeof(*fontface
))))
5346 return E_OUTOFMEMORY
;
5348 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
5349 fontface
->IDWriteFontFaceReference_iface
.lpVtbl
= &dwritefontface_reference_vtbl
;
5350 fontface
->refcount
= 1;
5351 fontface
->type
= desc
->face_type
;
5352 fontface
->vdmx
.exists
= TRUE
;
5353 fontface
->gasp
.exists
= TRUE
;
5354 fontface
->cpal
.exists
= TRUE
;
5355 fontface
->colr
.exists
= TRUE
;
5356 fontface
->kern
.exists
= TRUE
;
5357 fontface
->index
= desc
->index
;
5358 fontface
->simulations
= desc
->simulations
;
5359 fontface
->factory
= desc
->factory
;
5360 IDWriteFactory7_AddRef(fontface
->factory
);
5361 fontface
->file
= desc
->file
;
5362 IDWriteFontFile_AddRef(fontface
->file
);
5363 fontface
->stream
= desc
->stream
;
5364 IDWriteFontFileStream_AddRef(fontface
->stream
);
5365 InitializeCriticalSection(&fontface
->cs
);
5366 fontface_cache_init(fontface
);
5368 stream_desc
.stream
= fontface
->stream
;
5369 stream_desc
.face_type
= desc
->face_type
;
5370 stream_desc
.face_index
= desc
->index
;
5371 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
5372 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
5373 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
5374 /* TODO: test what happens if caret is already slanted */
5375 if (fontface
->caret
.slopeRise
== 1) {
5376 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
5377 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
5380 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
5382 /* Font properties are reused from font object when 'normal' face creation path is used:
5383 collection -> family -> matching font -> fontface.
5385 If face is created directly from factory we have to go through properties resolution.
5387 if (desc
->font_data
)
5389 font_data
= addref_font_data(desc
->font_data
);
5393 hr
= init_font_data(desc
, &font_data
);
5396 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
5401 fontface
->weight
= font_data
->weight
;
5402 fontface
->style
= font_data
->style
;
5403 fontface
->stretch
= font_data
->stretch
;
5404 fontface
->panose
= font_data
->panose
;
5405 fontface
->fontsig
= font_data
->fontsig
;
5406 fontface
->lf
= font_data
->lf
;
5407 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
5408 fontface
->names
= font_data
->names
;
5409 if (fontface
->names
)
5410 IDWriteLocalizedStrings_AddRef(fontface
->names
);
5411 fontface
->family_names
= font_data
->family_names
;
5412 if (fontface
->family_names
)
5413 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
5414 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
5415 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
5417 if (fontface
->info_strings
[i
])
5418 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
5420 fontface
->cmap
.stream
= fontface
->stream
;
5421 IDWriteFontFileStream_AddRef(fontface
->cmap
.stream
);
5422 release_font_data(font_data
);
5424 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
5425 fontface
->get_font_object
= dwrite_fontface_get_font_object
;
5427 *ret
= &fontface
->IDWriteFontFace5_iface
;
5432 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
5439 struct local_cached_stream
5442 IDWriteFontFileStream
*stream
;
5443 struct local_refkey
*key
;
5447 struct dwrite_localfontfilestream
5449 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5452 struct local_cached_stream
*entry
;
5453 const void *file_ptr
;
5457 struct dwrite_localfontfileloader
5459 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
5462 struct list streams
;
5463 CRITICAL_SECTION cs
;
5466 static struct dwrite_localfontfileloader local_fontfile_loader
;
5468 struct dwrite_inmemory_stream_data
5476 struct dwrite_inmemory_filestream
5478 IDWriteFontFileStream IDWriteFontFileStream_iface
;
5481 struct dwrite_inmemory_stream_data
*data
;
5484 struct dwrite_inmemory_fileloader
5486 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
5489 struct dwrite_inmemory_stream_data
**streams
;
5494 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
5496 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
5499 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5501 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
5504 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
5506 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
5509 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
5511 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
5514 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
5516 if (InterlockedDecrement(&stream
->refcount
) == 0)
5519 IUnknown_Release(stream
->owner
);
5526 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
5528 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5530 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5532 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
5533 IsEqualIID(riid
, &IID_IUnknown
))
5536 if (InterlockedIncrement(&stream
->refcount
) == 1)
5538 InterlockedDecrement(&stream
->refcount
);
5545 WARN("%s not implemented.\n", debugstr_guid(riid
));
5548 return E_NOINTERFACE
;
5551 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
5553 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5554 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
5556 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5561 static inline void release_cached_stream(struct local_cached_stream
*stream
)
5563 list_remove(&stream
->entry
);
5568 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
5570 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5571 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
5573 TRACE_(dwrite_file
)("%p, refcount %d.\n", iface
, refcount
);
5577 UnmapViewOfFile(stream
->file_ptr
);
5579 EnterCriticalSection(&local_fontfile_loader
.cs
);
5580 release_cached_stream(stream
->entry
);
5581 LeaveCriticalSection(&local_fontfile_loader
.cs
);
5589 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
5590 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
5592 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5594 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
5595 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
5597 *fragment_context
= NULL
;
5599 if ((offset
>= stream
->size
- 1) || (fragment_size
> stream
->size
- offset
))
5601 *fragment_start
= NULL
;
5605 *fragment_start
= (char *)stream
->file_ptr
+ offset
;
5609 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
5611 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
5614 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
5616 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5618 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
5620 *size
= stream
->size
;
5624 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
5626 struct dwrite_localfontfilestream
*stream
= impl_from_IDWriteFontFileStream(iface
);
5629 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
5631 li
.u
.LowPart
= stream
->entry
->key
->writetime
.dwLowDateTime
;
5632 li
.u
.HighPart
= stream
->entry
->key
->writetime
.dwHighDateTime
;
5633 *last_writetime
= li
.QuadPart
;
5638 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
5640 localfontfilestream_QueryInterface
,
5641 localfontfilestream_AddRef
,
5642 localfontfilestream_Release
,
5643 localfontfilestream_ReadFileFragment
,
5644 localfontfilestream_ReleaseFileFragment
,
5645 localfontfilestream_GetFileSize
,
5646 localfontfilestream_GetLastWriteTime
5649 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
,
5650 IDWriteFontFileStream
**ret
)
5652 struct dwrite_localfontfilestream
*object
;
5656 if (!(object
= calloc(1, sizeof(*object
))))
5657 return E_OUTOFMEMORY
;
5659 object
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
5660 object
->refcount
= 1;
5662 object
->file_ptr
= file_ptr
;
5663 object
->size
= size
;
5664 object
->entry
= entry
;
5666 *ret
= &object
->IDWriteFontFileStream_iface
;
5671 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
5673 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
5675 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
5676 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
5677 IsEqualIID(riid
, &IID_IUnknown
))
5680 IDWriteLocalFontFileLoader_AddRef(iface
);
5684 WARN("%s not implemented.\n", debugstr_guid(riid
));
5687 return E_NOINTERFACE
;
5690 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5692 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5693 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
5695 TRACE("%p, refcount %d.\n", iface
, refcount
);
5700 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5702 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5703 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
5705 TRACE("%p, refcount %d.\n", iface
, refcount
);
5710 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5712 const struct local_refkey
*refkey
= key
;
5713 struct local_cached_stream
*stream
;
5714 IDWriteFontFileStream
*filestream
;
5715 HANDLE file
, mapping
;
5722 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5723 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5724 if (file
== INVALID_HANDLE_VALUE
) {
5725 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5729 GetFileSizeEx(file
, &size
);
5730 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5735 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5736 CloseHandle(mapping
);
5738 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5742 if (!(stream
= malloc(sizeof(*stream
))))
5744 UnmapViewOfFile(file_ptr
);
5745 return E_OUTOFMEMORY
;
5748 if (!(stream
->key
= malloc(key_size
)))
5750 UnmapViewOfFile(file_ptr
);
5752 return E_OUTOFMEMORY
;
5755 stream
->key_size
= key_size
;
5756 memcpy(stream
->key
, key
, key_size
);
5758 if (FAILED(hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
)))
5760 UnmapViewOfFile(file_ptr
);
5766 stream
->stream
= filestream
;
5773 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5774 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5776 struct dwrite_localfontfileloader
*loader
= impl_from_IDWriteLocalFontFileLoader(iface
);
5777 struct local_cached_stream
*stream
;
5780 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
5782 EnterCriticalSection(&loader
->cs
);
5786 /* search cache first */
5787 LIST_FOR_EACH_ENTRY(stream
, &loader
->streams
, struct local_cached_stream
, entry
)
5789 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5790 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5795 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
)
5797 list_add_head(&loader
->streams
, &stream
->entry
);
5798 *ret
= stream
->stream
;
5801 LeaveCriticalSection(&loader
->cs
);
5806 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5807 UINT32 key_size
, UINT32
*length
)
5809 const struct local_refkey
*refkey
= key
;
5811 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, length
);
5813 *length
= wcslen(refkey
->name
);
5817 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5818 UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5820 const struct local_refkey
*refkey
= key
;
5822 TRACE("%p, %p, %u, %p, %u.\n", iface
, key
, key_size
, path
, length
);
5824 if (length
< wcslen(refkey
->name
))
5825 return E_INVALIDARG
;
5827 wcscpy(path
, refkey
->name
);
5831 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5832 UINT32 key_size
, FILETIME
*writetime
)
5834 const struct local_refkey
*refkey
= key
;
5836 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, writetime
);
5838 *writetime
= refkey
->writetime
;
5842 static const IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
=
5844 localfontfileloader_QueryInterface
,
5845 localfontfileloader_AddRef
,
5846 localfontfileloader_Release
,
5847 localfontfileloader_CreateStreamFromKey
,
5848 localfontfileloader_GetFilePathLengthFromKey
,
5849 localfontfileloader_GetFilePathFromKey
,
5850 localfontfileloader_GetLastWriteTimeFromKey
5853 void init_local_fontfile_loader(void)
5855 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5856 local_fontfile_loader
.refcount
= 1;
5857 list_init(&local_fontfile_loader
.streams
);
5858 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5859 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5862 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5864 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5867 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5869 struct local_refkey
*refkey
;
5872 return E_INVALIDARG
;
5874 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (wcslen(path
)+1)*sizeof(WCHAR
);
5877 if (!(refkey
= malloc(*size
)))
5878 return E_OUTOFMEMORY
;
5881 refkey
->writetime
= *writetime
;
5883 WIN32_FILE_ATTRIBUTE_DATA info
;
5885 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5886 refkey
->writetime
= info
.ftLastWriteTime
;
5888 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5890 wcscpy(refkey
->name
, path
);
5897 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5899 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5901 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5902 IsEqualIID(riid
, &IID_IUnknown
))
5905 IDWriteGlyphRunAnalysis_AddRef(iface
);
5909 WARN("%s not implemented.\n", debugstr_guid(riid
));
5912 return E_NOINTERFACE
;
5915 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5917 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5918 ULONG refcount
= InterlockedIncrement(&analysis
->refcount
);
5920 TRACE("%p, refcount %d.\n", iface
, refcount
);
5925 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5927 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5928 ULONG refcount
= InterlockedDecrement(&analysis
->refcount
);
5930 TRACE("%p, refcount %d.\n", iface
, refcount
);
5934 if (analysis
->run
.fontFace
)
5935 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5936 free(analysis
->glyphs
);
5937 free(analysis
->origins
);
5938 free(analysis
->bitmap
);
5945 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5947 struct dwrite_glyphbitmap glyph_bitmap
;
5950 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5951 *bounds
= analysis
->bounds
;
5955 if (analysis
->run
.isSideways
)
5956 FIXME("sideways runs are not supported.\n");
5958 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5959 glyph_bitmap
.simulations
= IDWriteFontFace_GetSimulations(analysis
->run
.fontFace
);
5960 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5961 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5962 glyph_bitmap
.m
= &analysis
->m
;
5964 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5965 RECT
*bbox
= &glyph_bitmap
.bbox
;
5968 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5969 dwrite_fontface_get_glyph_bbox(analysis
->run
.fontFace
, &glyph_bitmap
);
5971 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5972 (bbox
->bottom
- bbox
->top
);
5973 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5974 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5976 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5977 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5980 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5981 *bounds
= analysis
->bounds
;
5984 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
,
5985 DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5987 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5989 TRACE("%p, %d, %p.\n", iface
, type
, bounds
);
5991 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5992 SetRectEmpty(bounds
);
5993 return E_INVALIDARG
;
5996 if (type
!= analysis
->texture_type
)
5998 SetRectEmpty(bounds
);
6002 glyphrunanalysis_get_texturebounds(analysis
, bounds
);
6006 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
6008 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
6009 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
6010 (runbounds
->left
- bounds
->left
) * 3;
6012 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
6013 runbounds
->left
- bounds
->left
;
6016 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
6018 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
6019 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(analysis
->run
.fontFace
);
6020 struct dwrite_glyphbitmap glyph_bitmap
;
6021 D2D_POINT_2F origin
;
6025 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
6026 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
6028 if (!(analysis
->bitmap
= calloc(1, size
)))
6030 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
6031 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
6032 return E_OUTOFMEMORY
;
6035 origin
.x
= origin
.y
= 0.0f
;
6037 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
6038 glyph_bitmap
.simulations
= fontface
->simulations
;
6039 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
6040 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6041 glyph_bitmap
.m
= &analysis
->m
;
6042 if (!(glyph_bitmap
.buf
= malloc(analysis
->max_glyph_bitmap_size
)))
6043 return E_OUTOFMEMORY
;
6045 bbox
= &glyph_bitmap
.bbox
;
6047 for (i
= 0; i
< analysis
->run
.glyphCount
; ++i
)
6049 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
6050 int x
, y
, width
, height
;
6051 unsigned int is_1bpp
;
6053 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
6054 dwrite_fontface_get_glyph_bbox(analysis
->run
.fontFace
, &glyph_bitmap
);
6056 if (IsRectEmpty(bbox
))
6059 width
= bbox
->right
- bbox
->left
;
6060 height
= bbox
->bottom
- bbox
->top
;
6062 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
6063 memset(src
, 0, height
* glyph_bitmap
.pitch
);
6065 if (FAILED(dwrite_fontface_get_glyph_bitmap(fontface
, analysis
->rendering_mode
, &is_1bpp
, &glyph_bitmap
)))
6067 WARN("Failed to render glyph[%u] = %#x.\n", i
, glyph_bitmap
.glyph
);
6071 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
6073 /* blit to analysis bitmap */
6074 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
6077 /* convert 1bpp to 8bpp/24bpp */
6078 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
6079 for (y
= 0; y
< height
; y
++) {
6080 for (x
= 0; x
< width
; x
++)
6081 if (src
[x
/ 8] & masks
[x
% 8])
6082 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
6083 src
+= glyph_bitmap
.pitch
;
6084 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
6088 for (y
= 0; y
< height
; y
++) {
6089 for (x
= 0; x
< width
; x
++)
6090 if (src
[x
/ 8] & masks
[x
% 8])
6091 dst
[x
] = DWRITE_ALPHA_MAX
;
6092 src
+= glyph_bitmap
.pitch
;
6093 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
6098 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
6099 for (y
= 0; y
< height
; y
++) {
6100 for (x
= 0; x
< width
; x
++)
6101 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
6102 src
+= glyph_bitmap
.pitch
;
6103 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
6107 for (y
= 0; y
< height
; y
++) {
6108 for (x
= 0; x
< width
; x
++)
6110 src
+= glyph_bitmap
.pitch
;
6111 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
6116 free(glyph_bitmap
.buf
);
6118 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
6120 /* we don't need this anymore */
6121 free(analysis
->glyphs
);
6122 free(analysis
->origins
);
6123 IDWriteFontFace_Release(analysis
->run
.fontFace
);
6125 analysis
->glyphs
= NULL
;
6126 analysis
->origins
= NULL
;
6127 analysis
->run
.glyphIndices
= NULL
;
6128 analysis
->run
.fontFace
= NULL
;
6133 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
6134 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
6136 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6140 TRACE("%p, %d, %s, %p, %u.\n", iface
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
6142 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
6143 return E_INVALIDARG
;
6145 /* make sure buffer is large enough for requested texture type */
6146 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
6147 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
6150 if (size
< required
)
6151 return E_NOT_SUFFICIENT_BUFFER
;
6153 /* validate requested texture type */
6154 if (analysis
->texture_type
!= type
)
6155 return DWRITE_E_UNSUPPORTEDOPERATION
;
6157 memset(bitmap
, 0, size
);
6158 glyphrunanalysis_get_texturebounds(analysis
, &runbounds
);
6159 if (IntersectRect(&runbounds
, &runbounds
, bounds
))
6161 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
6162 int src_width
= (analysis
->bounds
.right
- analysis
->bounds
.left
) * pixel_size
;
6163 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
6164 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
6168 if (!(analysis
->flags
& RUNANALYSIS_BITMAP_READY
))
6172 if (FAILED(hr
= glyphrunanalysis_render(analysis
)))
6176 src
= get_pixel_ptr(analysis
->bitmap
, type
, &runbounds
, &analysis
->bounds
);
6177 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
6179 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
6180 memcpy(dst
, src
, draw_width
);
6189 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
6190 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
6192 struct dwrite_glyphrunanalysis
*analysis
= impl_from_IDWriteGlyphRunAnalysis(iface
);
6194 TRACE("%p, %p, %p, %p, %p.\n", iface
, params
, gamma
, contrast
, cleartypelevel
);
6197 return E_INVALIDARG
;
6199 switch (analysis
->rendering_mode
)
6201 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
6202 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
6205 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
6206 *gamma
= (FLOAT
)value
/ 1000.0f
;
6208 *cleartypelevel
= 1.0f
;
6211 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
6212 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
6214 case DWRITE_RENDERING_MODE1_ALIASED
:
6215 case DWRITE_RENDERING_MODE1_NATURAL
:
6216 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
6217 *gamma
= IDWriteRenderingParams_GetGamma(params
);
6218 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
6219 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
6228 static const IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
=
6230 glyphrunanalysis_QueryInterface
,
6231 glyphrunanalysis_AddRef
,
6232 glyphrunanalysis_Release
,
6233 glyphrunanalysis_GetAlphaTextureBounds
,
6234 glyphrunanalysis_CreateAlphaTexture
,
6235 glyphrunanalysis_GetAlphaBlendParams
6238 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
6241 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
6242 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
6246 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
6247 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
6249 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
6253 FIXME("Sideways mode is not supported.\n");
6255 EnterCriticalSection(&fontface
->cs
);
6256 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
6257 LeaveCriticalSection(&fontface
->cs
);
6259 switch (measuring_mode
)
6261 case DWRITE_MEASURING_MODE_NATURAL
:
6262 return (float)advance
* emsize
/ (float)upem
;
6263 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
6264 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
6265 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
6267 WARN("Unknown measuring mode %u.\n", measuring_mode
);
6272 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
6274 struct dwrite_glyphrunanalysis
*analysis
;
6279 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
6280 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
6281 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
6282 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
6283 return E_INVALIDARG
;
6285 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6286 return E_INVALIDARG
;
6288 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
6289 return E_INVALIDARG
;
6291 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
6292 return E_INVALIDARG
;
6294 if (!(analysis
= calloc(1, sizeof(*analysis
))))
6295 return E_OUTOFMEMORY
;
6297 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
6298 analysis
->refcount
= 1;
6299 analysis
->rendering_mode
= desc
->rendering_mode
;
6301 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
6302 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
6303 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
6305 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
6307 analysis
->run
= *desc
->run
;
6308 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
6309 analysis
->glyphs
= calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
6310 analysis
->origins
= calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
6312 if (!analysis
->glyphs
|| !analysis
->origins
)
6314 free(analysis
->glyphs
);
6315 free(analysis
->origins
);
6317 analysis
->glyphs
= NULL
;
6318 analysis
->origins
= NULL
;
6320 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
6321 return E_OUTOFMEMORY
;
6324 /* check if transform is usable */
6325 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
6326 analysis
->m
= *desc
->transform
;
6327 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
6330 analysis
->run
.glyphIndices
= analysis
->glyphs
;
6331 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
6333 compute_glyph_origins(desc
->run
, desc
->measuring_mode
, desc
->origin
, desc
->transform
, analysis
->origins
);
6334 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
6336 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
6337 transform_point(&analysis
->origins
[i
], &analysis
->m
);
6340 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
6344 /* IDWriteColorGlyphRunEnumerator1 */
6345 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
6347 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
6349 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
6350 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
6351 IsEqualIID(riid
, &IID_IUnknown
))
6354 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
6358 WARN("%s not implemented.\n", debugstr_guid(riid
));
6361 return E_NOINTERFACE
;
6364 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
6366 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6367 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
6369 TRACE("%p, refcount %u.\n", iface
, refcount
);
6374 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
6376 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6377 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
6379 TRACE("%p, refcount %u.\n", iface
, refcount
);
6383 free(glyphenum
->advances
);
6384 free(glyphenum
->color_advances
);
6385 free(glyphenum
->offsets
);
6386 free(glyphenum
->color_offsets
);
6387 free(glyphenum
->glyphindices
);
6388 free(glyphenum
->glyphs
);
6389 if (glyphenum
->colr
.context
)
6390 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
6391 IDWriteFontFace5_Release(glyphenum
->fontface
);
6398 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
6400 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
6401 FLOAT origin
= 0.0f
;
6407 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
6411 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
6413 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
6414 FLOAT advance_adj
= 0.0f
;
6415 BOOL got_palette_index
;
6418 /* start with regular glyphs */
6419 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
6420 UINT32 first_glyph
= 0;
6422 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6423 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
6424 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
6425 first_glyph
= min(first_glyph
, g
);
6428 glyphenum
->glyphindices
[g
] = 1;
6429 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
6430 if (glyphenum
->color_offsets
)
6431 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
6434 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
6435 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6436 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
6437 colorrun
->paletteIndex
= 0xffff;
6438 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6439 glyphenum
->has_regular_glyphs
= FALSE
;
6443 colorrun
->glyphRun
.glyphCount
= 0;
6444 got_palette_index
= FALSE
;
6448 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
6450 glyphenum
->glyphindices
[g
] = 1;
6452 /* all glyph layers were returned */
6453 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
6454 advance_adj
+= glyphenum
->advances
[g
];
6458 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
6459 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
6460 if (!got_palette_index
) {
6461 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
6462 /* use foreground color or request one from the font */
6463 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
6464 if (colorrun
->paletteIndex
!= 0xffff)
6466 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
6467 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
6469 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
6470 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
6472 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
6473 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
6474 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
6475 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
6476 got_palette_index
= TRUE
;
6479 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
6480 /* offsets are relative to glyph origin, nothing to fix up */
6481 if (glyphenum
->color_offsets
)
6482 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
6483 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
6485 glyphenum
->color_advances
[index
-1] += advance_adj
;
6486 colorrun
->glyphRun
.glyphCount
++;
6490 advance_adj
+= glyphenum
->advances
[g
];
6493 /* reset last advance */
6494 if (colorrun
->glyphRun
.glyphCount
)
6495 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
6497 return colorrun
->glyphRun
.glyphCount
> 0;
6500 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
6502 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6504 TRACE("%p, %p.\n", iface
, has_run
);
6508 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
6509 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
6511 if (colorglyphenum_build_color_run(glyphenum
))
6514 glyphenum
->current_layer
++;
6517 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
6522 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
6523 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6525 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
6528 return E_NOT_VALID_STATE
;
6531 *run
= &glyphenum
->colorrun
;
6535 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6536 DWRITE_COLOR_GLYPH_RUN
const **run
)
6538 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6540 TRACE("%p, %p.\n", iface
, run
);
6542 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
6545 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
6546 DWRITE_COLOR_GLYPH_RUN1
const **run
)
6548 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
6550 TRACE("%p, %p.\n", iface
, run
);
6552 return colorglyphenum_get_current_run(glyphenum
, run
);
6555 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
6557 colorglyphenum_QueryInterface
,
6558 colorglyphenum_AddRef
,
6559 colorglyphenum_Release
,
6560 colorglyphenum_MoveNext
,
6561 colorglyphenum_GetCurrentRun
,
6562 colorglyphenum1_GetCurrentRun
,
6565 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
6566 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
6567 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
6569 struct dwrite_colorglyphenum
*colorglyphenum
;
6570 BOOL colorfont
, has_colored_glyph
;
6571 struct dwrite_fontface
*fontface
;
6576 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
6578 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
6579 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
6581 return DWRITE_E_NOCOLOR
;
6583 if (!(colorglyphenum
= calloc(1, sizeof(*colorglyphenum
))))
6584 return E_OUTOFMEMORY
;
6586 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
6587 colorglyphenum
->refcount
= 1;
6588 colorglyphenum
->origin_x
= originX
;
6589 colorglyphenum
->origin_y
= originY
;
6590 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
6591 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
6592 colorglyphenum
->glyphs
= NULL
;
6593 colorglyphenum
->run
= *run
;
6594 colorglyphenum
->run
.glyphIndices
= NULL
;
6595 colorglyphenum
->run
.glyphAdvances
= NULL
;
6596 colorglyphenum
->run
.glyphOffsets
= NULL
;
6597 colorglyphenum
->palette
= palette
;
6598 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
6599 colorglyphenum
->colr
.exists
= TRUE
;
6600 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
6601 colorglyphenum
->current_layer
= 0;
6602 colorglyphenum
->max_layer_num
= 0;
6604 colorglyphenum
->glyphs
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphs
));
6606 has_colored_glyph
= FALSE
;
6607 colorglyphenum
->has_regular_glyphs
= FALSE
;
6608 for (i
= 0; i
< run
->glyphCount
; i
++) {
6609 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6610 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6611 has_colored_glyph
= TRUE
;
6613 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6614 colorglyphenum
->has_regular_glyphs
= TRUE
;
6617 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6618 is supposed to proceed normally, like if font had no color info at all. */
6619 if (!has_colored_glyph
) {
6620 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6621 return DWRITE_E_NOCOLOR
;
6624 colorglyphenum
->advances
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6625 colorglyphenum
->color_advances
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6626 colorglyphenum
->glyphindices
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6627 if (run
->glyphOffsets
) {
6628 colorglyphenum
->offsets
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6629 colorglyphenum
->color_offsets
= calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6630 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6633 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6634 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6635 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6636 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6637 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6638 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6639 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6640 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6642 if (run
->glyphAdvances
)
6643 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6646 for (i
= 0; i
< run
->glyphCount
; ++i
)
6647 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6648 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6651 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6656 /* IDWriteFontFaceReference */
6657 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6659 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6661 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6662 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6663 IsEqualIID(riid
, &IID_IUnknown
))
6666 IDWriteFontFaceReference1_AddRef(iface
);
6670 WARN("%s not implemented.\n", debugstr_guid(riid
));
6674 return E_NOINTERFACE
;
6677 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6679 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6680 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6682 TRACE("%p, refcount %u.\n", iface
, refcount
);
6687 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6689 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6690 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6692 TRACE("%p, refcount %u.\n", iface
, refcount
);
6696 IDWriteFontFile_Release(reference
->file
);
6697 IDWriteFactory7_Release(reference
->factory
);
6698 free(reference
->axis_values
);
6705 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6707 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6709 TRACE("%p, %p.\n", iface
, fontface
);
6711 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6714 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6715 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6717 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6718 DWRITE_FONT_FILE_TYPE file_type
;
6719 DWRITE_FONT_FACE_TYPE face_type
;
6720 IDWriteFontFace
*fontface
;
6725 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6727 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6731 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6732 simulations
, &fontface
);
6735 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6736 IDWriteFontFace_Release(fontface
);
6742 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6744 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6745 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6748 TRACE("%p, %p.\n", iface
, ref
);
6750 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6751 reference
->simulations
== other
->simulations
;
6752 if (reference
->axis_values_count
)
6754 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6755 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6761 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6763 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6765 TRACE("%p.\n", iface
);
6767 return reference
->index
;
6770 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6772 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6774 TRACE("%p.\n", iface
);
6776 return reference
->simulations
;
6779 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6781 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6782 IDWriteFontFileLoader
*loader
;
6787 TRACE("%p, %p.\n", iface
, file
);
6789 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6793 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6797 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6798 IDWriteFontFileLoader_Release(loader
);
6803 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6805 FIXME("%p.\n", iface
);
6810 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6812 FIXME("%p.\n", iface
);
6817 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6819 FIXME("%p, %p.\n", iface
, writetime
);
6824 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6826 FIXME("%p.\n", iface
);
6828 return DWRITE_LOCALITY_LOCAL
;
6831 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6833 FIXME("%p.\n", iface
);
6838 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6839 WCHAR
const *chars
, UINT32 count
)
6841 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6846 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6847 UINT16
const *glyphs
, UINT32 count
)
6849 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6854 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6855 UINT64 offset
, UINT64 size
)
6857 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6862 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6864 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6865 IDWriteFontFace3
*fontface3
;
6868 TRACE("%p, %p.\n", iface
, fontface
);
6870 /* FIXME: created instance should likely respect given axis. */
6871 if (SUCCEEDED(hr
= IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
,
6874 hr
= IDWriteFontFace3_QueryInterface(fontface3
, &IID_IDWriteFontFace5
, (void **)fontface
);
6875 IDWriteFontFace3_Release(fontface3
);
6881 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6883 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6885 TRACE("%p.\n", iface
);
6887 return reference
->axis_values_count
;
6890 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6891 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6893 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6895 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6897 if (value_count
< reference
->axis_values_count
)
6898 return E_NOT_SUFFICIENT_BUFFER
;
6900 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6905 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6907 fontfacereference_QueryInterface
,
6908 fontfacereference_AddRef
,
6909 fontfacereference_Release
,
6910 fontfacereference_CreateFontFace
,
6911 fontfacereference_CreateFontFaceWithSimulations
,
6912 fontfacereference_Equals
,
6913 fontfacereference_GetFontFaceIndex
,
6914 fontfacereference_GetSimulations
,
6915 fontfacereference_GetFontFile
,
6916 fontfacereference_GetLocalFileSize
,
6917 fontfacereference_GetFileSize
,
6918 fontfacereference_GetFileTime
,
6919 fontfacereference_GetLocality
,
6920 fontfacereference_EnqueueFontDownloadRequest
,
6921 fontfacereference_EnqueueCharacterDownloadRequest
,
6922 fontfacereference_EnqueueGlyphDownloadRequest
,
6923 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6924 fontfacereference1_CreateFontFace
,
6925 fontfacereference1_GetFontAxisValueCount
,
6926 fontfacereference1_GetFontAxisValues
,
6929 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6930 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6931 IDWriteFontFaceReference1
**ret
)
6933 struct dwrite_fontfacereference
*object
;
6937 if (!is_simulation_valid(simulations
))
6938 return E_INVALIDARG
;
6940 if (!(object
= calloc(1, sizeof(*object
))))
6941 return E_OUTOFMEMORY
;
6943 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6944 object
->refcount
= 1;
6946 object
->factory
= factory
;
6947 IDWriteFactory7_AddRef(object
->factory
);
6948 object
->file
= file
;
6949 IDWriteFontFile_AddRef(object
->file
);
6950 object
->index
= index
;
6951 object
->simulations
= simulations
;
6952 if (axis_values_count
)
6954 if (!(object
->axis_values
= malloc(axis_values_count
* sizeof(*axis_values
))))
6956 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6957 return E_OUTOFMEMORY
;
6959 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6960 object
->axis_values_count
= axis_values_count
;
6963 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6968 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6970 TRACE_(dwrite_file
)("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6972 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6974 IDWriteFontFileStream_AddRef(iface
);
6980 WARN("%s not implemented.\n", debugstr_guid(riid
));
6981 return E_NOINTERFACE
;
6984 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6986 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6987 ULONG refcount
= InterlockedIncrement(&stream
->refcount
);
6989 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
6994 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6996 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6997 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
6999 TRACE_(dwrite_file
)("%p, refcount %u.\n", iface
, refcount
);
7003 release_inmemory_stream(stream
->data
);
7010 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
7011 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
7013 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
7015 TRACE_(dwrite_file
)("%p, %p, 0x%s, 0x%s, %p.\n", iface
, fragment_start
,
7016 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
7018 *fragment_context
= NULL
;
7020 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
7021 *fragment_start
= NULL
;
7025 *fragment_start
= (char *)stream
->data
->data
+ offset
;
7029 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
7031 TRACE_(dwrite_file
)("%p, %p.\n", iface
, fragment_context
);
7034 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
7036 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
7038 TRACE_(dwrite_file
)("%p, %p.\n", iface
, size
);
7040 *size
= stream
->data
->size
;
7045 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
7047 TRACE_(dwrite_file
)("%p, %p.\n", iface
, last_writetime
);
7049 *last_writetime
= 0;
7054 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
7055 inmemoryfilestream_QueryInterface
,
7056 inmemoryfilestream_AddRef
,
7057 inmemoryfilestream_Release
,
7058 inmemoryfilestream_ReadFileFragment
,
7059 inmemoryfilestream_ReleaseFileFragment
,
7060 inmemoryfilestream_GetFileSize
,
7061 inmemoryfilestream_GetLastWriteTime
,
7064 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
7065 REFIID riid
, void **obj
)
7067 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7069 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
7070 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
7071 IsEqualIID(riid
, &IID_IUnknown
))
7074 IDWriteInMemoryFontFileLoader_AddRef(iface
);
7078 WARN("%s not implemented.\n", debugstr_guid(riid
));
7082 return E_NOINTERFACE
;
7085 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
7087 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7088 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
7090 TRACE("%p, refcount %u.\n", iface
, refcount
);
7095 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
7097 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7098 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
7101 TRACE("%p, refcount %u.\n", iface
, refcount
);
7105 for (i
= 0; i
< loader
->count
; ++i
)
7106 release_inmemory_stream(loader
->streams
[i
]);
7107 free(loader
->streams
);
7114 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
7115 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
7117 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7118 struct dwrite_inmemory_filestream
*stream
;
7121 TRACE("%p, %p, %u, %p.\n", iface
, key
, key_size
, ret
);
7125 if (key_size
!= sizeof(DWORD
))
7126 return E_INVALIDARG
;
7128 index
= *(DWORD
*)key
;
7130 if (index
>= loader
->count
)
7131 return E_INVALIDARG
;
7133 if (!(stream
= malloc(sizeof(*stream
))))
7134 return E_OUTOFMEMORY
;
7136 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
7137 stream
->refcount
= 1;
7138 stream
->data
= loader
->streams
[index
];
7139 InterlockedIncrement(&stream
->data
->refcount
);
7141 *ret
= &stream
->IDWriteFontFileStream_iface
;
7146 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
7147 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
7149 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7150 struct dwrite_inmemory_stream_data
*stream
;
7153 TRACE("%p, %p, %p, %u, %p, %p.\n", iface
, factory
, data
, data_size
, owner
, fontfile
);
7157 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
7158 return E_OUTOFMEMORY
;
7160 if (!(stream
= malloc(sizeof(*stream
))))
7161 return E_OUTOFMEMORY
;
7163 stream
->refcount
= 1;
7164 stream
->size
= data_size
;
7165 stream
->owner
= owner
;
7166 if (stream
->owner
) {
7167 IUnknown_AddRef(stream
->owner
);
7168 stream
->data
= (void *)data
;
7171 if (!(stream
->data
= malloc(data_size
)))
7174 return E_OUTOFMEMORY
;
7176 memcpy(stream
->data
, data
, data_size
);
7179 key
= loader
->count
;
7180 loader
->streams
[loader
->count
++] = stream
;
7182 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
7183 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
7186 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
7188 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
7190 TRACE("%p.\n", iface
);
7192 return loader
->count
;
7195 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
7197 inmemoryfontfileloader_QueryInterface
,
7198 inmemoryfontfileloader_AddRef
,
7199 inmemoryfontfileloader_Release
,
7200 inmemoryfontfileloader_CreateStreamFromKey
,
7201 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
7202 inmemoryfontfileloader_GetFileCount
,
7205 HRESULT
create_inmemory_fileloader(IDWriteInMemoryFontFileLoader
**ret
)
7207 struct dwrite_inmemory_fileloader
*loader
;
7211 if (!(loader
= calloc(1, sizeof(*loader
))))
7212 return E_OUTOFMEMORY
;
7214 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
7215 loader
->refcount
= 1;
7217 *ret
= &loader
->IDWriteInMemoryFontFileLoader_iface
;
7222 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
7224 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7226 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
7227 IsEqualIID(riid
, &IID_IUnknown
))
7230 IDWriteFontResource_AddRef(iface
);
7234 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7236 return E_NOINTERFACE
;
7239 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
7241 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7242 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
7244 TRACE("%p, refcount %u.\n", iface
, refcount
);
7249 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
7251 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7252 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
7254 TRACE("%p, refcount %u.\n", iface
, refcount
);
7258 IDWriteFactory7_Release(resource
->factory
);
7259 IDWriteFontFile_Release(resource
->file
);
7266 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
7268 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7270 TRACE("%p, %p.\n", iface
, fontfile
);
7272 *fontfile
= resource
->file
;
7273 IDWriteFontFile_AddRef(*fontfile
);
7278 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
7280 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7282 TRACE("%p.\n", iface
);
7284 return resource
->face_index
;
7287 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
7289 FIXME("%p.\n", iface
);
7294 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
7295 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
7297 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
7302 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
7303 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
7305 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
7310 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
7313 FIXME("%p, %u.\n", iface
, axis
);
7315 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
7318 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
7319 IDWriteLocalizedStrings
**names
)
7321 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
7326 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
7328 FIXME("%p, %u.\n", iface
, axis
);
7333 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
7334 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
7336 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
7341 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
7343 FIXME("%p.\n", iface
);
7348 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
7349 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7350 IDWriteFontFace5
**fontface
)
7352 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7353 IDWriteFontFaceReference1
*reference
;
7356 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
7358 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7359 simulations
, axis_values
, num_values
, &reference
);
7362 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
7363 IDWriteFontFaceReference1_Release(reference
);
7369 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
7370 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
7371 IDWriteFontFaceReference1
**reference
)
7373 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
7375 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
7377 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
7378 simulations
, axis_values
, num_values
, reference
);
7381 static const IDWriteFontResourceVtbl fontresourcevtbl
=
7383 dwritefontresource_QueryInterface
,
7384 dwritefontresource_AddRef
,
7385 dwritefontresource_Release
,
7386 dwritefontresource_GetFontFile
,
7387 dwritefontresource_GetFontFaceIndex
,
7388 dwritefontresource_GetFontAxisCount
,
7389 dwritefontresource_GetDefaultFontAxisValues
,
7390 dwritefontresource_GetFontAxisRanges
,
7391 dwritefontresource_GetFontAxisAttributes
,
7392 dwritefontresource_GetAxisNames
,
7393 dwritefontresource_GetAxisValueNameCount
,
7394 dwritefontresource_GetAxisValueNames
,
7395 dwritefontresource_HasVariations
,
7396 dwritefontresource_CreateFontFace
,
7397 dwritefontresource_CreateFontFaceReference
,
7400 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
7401 IDWriteFontResource
**ret
)
7403 struct dwrite_fontresource
*resource
;
7407 if (!(resource
= calloc(1, sizeof(*resource
))))
7408 return E_OUTOFMEMORY
;
7410 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
7411 resource
->refcount
= 1;
7412 resource
->face_index
= face_index
;
7413 resource
->file
= file
;
7414 IDWriteFontFile_AddRef(resource
->file
);
7415 resource
->factory
= factory
;
7416 IDWriteFactory7_AddRef(resource
->factory
);
7418 *ret
= &resource
->IDWriteFontResource_iface
;
7423 static HRESULT WINAPI
dwritefontset_QueryInterface(IDWriteFontSet3
*iface
, REFIID riid
, void **obj
)
7425 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7427 if (IsEqualIID(riid
, &IID_IDWriteFontSet3
) ||
7428 IsEqualIID(riid
, &IID_IDWriteFontSet2
) ||
7429 IsEqualIID(riid
, &IID_IDWriteFontSet1
) ||
7430 IsEqualIID(riid
, &IID_IDWriteFontSet
))
7433 IDWriteFontSet3_AddRef(iface
);
7437 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7439 return E_NOINTERFACE
;
7442 static ULONG WINAPI
dwritefontset_AddRef(IDWriteFontSet3
*iface
)
7444 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7445 ULONG refcount
= InterlockedIncrement(&set
->refcount
);
7447 TRACE("%p, refcount %u.\n", iface
, refcount
);
7452 #define MISSING_SET_PROP ((void *)0x1)
7454 static void release_fontset_entry(struct dwrite_fontset_entry
*entry
)
7458 if (InterlockedDecrement(&entry
->refcount
) > 0)
7460 IDWriteFontFile_Release(entry
->file
);
7461 for (i
= 0; i
< ARRAY_SIZE(entry
->props
); ++i
)
7463 if (entry
->props
[i
] && entry
->props
[i
] != MISSING_SET_PROP
)
7464 IDWriteLocalizedStrings_Release(entry
->props
[i
]);
7469 static struct dwrite_fontset_entry
* addref_fontset_entry(struct dwrite_fontset_entry
*entry
)
7471 InterlockedIncrement(&entry
->refcount
);
7475 static IDWriteLocalizedStrings
* fontset_entry_get_property(struct dwrite_fontset_entry
*entry
,
7476 DWRITE_FONT_PROPERTY_ID property
)
7478 struct file_stream_desc stream_desc
= { 0 };
7479 IDWriteLocalizedStrings
*value
;
7481 assert(property
> DWRITE_FONT_PROPERTY_ID_NONE
&& property
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
);
7483 if (entry
->props
[property
] == MISSING_SET_PROP
)
7486 if ((value
= entry
->props
[property
]))
7488 IDWriteLocalizedStrings_AddRef(value
);
7492 get_filestream_from_file(entry
->file
, &stream_desc
.stream
);
7493 stream_desc
.face_type
= entry
->face_type
;
7494 stream_desc
.face_index
= entry
->face_index
;
7496 if (property
== DWRITE_FONT_PROPERTY_ID_FULL_NAME
)
7497 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_FULL_NAME
, &value
);
7498 else if (property
== DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
)
7499 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME
, &value
);
7500 else if (property
== DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
)
7501 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG
, &value
);
7502 else if (property
== DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
)
7503 opentype_get_font_info_strings(&stream_desc
, DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
, &value
);
7505 WARN("Unsupported property %u.\n", property
);
7507 if (stream_desc
.stream
)
7508 IDWriteFontFileStream_Release(stream_desc
.stream
);
7512 entry
->props
[property
] = value
;
7513 IDWriteLocalizedStrings_AddRef(value
);
7516 entry
->props
[property
] = MISSING_SET_PROP
;
7521 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7522 struct dwrite_fontset_entry
**entries
, unsigned int count
);
7524 static ULONG WINAPI
dwritefontset_Release(IDWriteFontSet3
*iface
)
7526 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7527 ULONG refcount
= InterlockedDecrement(&set
->refcount
);
7530 TRACE("%p, refcount %u.\n", iface
, refcount
);
7534 IDWriteFactory7_Release(set
->factory
);
7535 for (i
= 0; i
< set
->count
; ++i
)
7536 release_fontset_entry(set
->entries
[i
]);
7544 static UINT32 WINAPI
dwritefontset_GetFontCount(IDWriteFontSet3
*iface
)
7546 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7548 TRACE("%p.\n", iface
);
7553 static HRESULT WINAPI
dwritefontset_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7554 IDWriteFontFaceReference
**reference
)
7556 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7558 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
7562 if (index
>= set
->count
)
7563 return E_INVALIDARG
;
7565 return IDWriteFactory7_CreateFontFaceReference_(set
->factory
, set
->entries
[index
]->file
,
7566 set
->entries
[index
]->face_index
, set
->entries
[index
]->simulations
, reference
);
7569 static HRESULT WINAPI
dwritefontset_FindFontFaceReference(IDWriteFontSet3
*iface
,
7570 IDWriteFontFaceReference
*reference
, UINT32
*index
, BOOL
*exists
)
7572 FIXME("%p, %p, %p, %p.\n", iface
, reference
, index
, exists
);
7577 static HRESULT WINAPI
dwritefontset_FindFontFace(IDWriteFontSet3
*iface
, IDWriteFontFace
*fontface
,
7578 UINT32
*index
, BOOL
*exists
)
7580 FIXME("%p, %p, %p, %p.\n", iface
, fontface
, index
, exists
);
7585 static HRESULT WINAPI
dwritefontset_GetPropertyValues__(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7586 IDWriteStringList
**values
)
7588 FIXME("%p, %d, %p.\n", iface
, id
, values
);
7593 static HRESULT WINAPI
dwritefontset_GetPropertyValues_(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY_ID id
,
7594 WCHAR
const *preferred_locales
, IDWriteStringList
**values
)
7596 FIXME("%p, %d, %s, %p.\n", iface
, id
, debugstr_w(preferred_locales
), values
);
7601 static HRESULT WINAPI
dwritefontset_GetPropertyValues(IDWriteFontSet3
*iface
, UINT32 index
, DWRITE_FONT_PROPERTY_ID id
,
7602 BOOL
*exists
, IDWriteLocalizedStrings
**values
)
7604 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7606 TRACE("%p, %u, %d, %p, %p.\n", iface
, index
, id
, exists
, values
);
7608 if (!(id
> DWRITE_FONT_PROPERTY_ID_NONE
&& id
<= DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
) ||
7609 index
>= set
->count
)
7613 return E_INVALIDARG
;
7616 *values
= fontset_entry_get_property(set
->entries
[index
], id
);
7617 *exists
= !!*values
;
7622 static HRESULT WINAPI
dwritefontset_GetPropertyOccurrenceCount(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7625 FIXME("%p, %p, %p.\n", iface
, property
, count
);
7630 static BOOL
fontset_entry_is_matching(struct dwrite_fontset_entry
*entry
, DWRITE_FONT_PROPERTY
const *props
,
7633 IDWriteLocalizedStrings
*value
;
7637 for (i
= 0; i
< count
; ++i
)
7639 switch (props
[i
].propertyId
)
7641 case DWRITE_FONT_PROPERTY_ID_POSTSCRIPT_NAME
:
7642 case DWRITE_FONT_PROPERTY_ID_FULL_NAME
:
7643 case DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG
:
7644 case DWRITE_FONT_PROPERTY_ID_SUPPORTED_SCRIPT_LANGUAGE_TAG
:
7645 if (!(value
= fontset_entry_get_property(entry
, props
[i
].propertyId
)))
7648 ret
= localizedstrings_contains(value
, props
[i
].propertyValue
);
7649 IDWriteLocalizedStrings_Release(value
);
7650 if (!ret
) return FALSE
;
7652 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FAMILY_NAME
:
7653 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FAMILY_NAME
:
7654 case DWRITE_FONT_PROPERTY_ID_WEIGHT_STRETCH_STYLE_FACE_NAME
:
7655 case DWRITE_FONT_PROPERTY_ID_WIN32_FAMILY_NAME
:
7656 case DWRITE_FONT_PROPERTY_ID_SEMANTIC_TAG
:
7657 case DWRITE_FONT_PROPERTY_ID_WEIGHT
:
7658 case DWRITE_FONT_PROPERTY_ID_STRETCH
:
7659 case DWRITE_FONT_PROPERTY_ID_STYLE
:
7660 case DWRITE_FONT_PROPERTY_ID_TYPOGRAPHIC_FACE_NAME
:
7661 FIXME("Unsupported property %d.\n", props
[i
].propertyId
);
7671 static HRESULT WINAPI
dwritefontset_GetMatchingFonts_(IDWriteFontSet3
*iface
, WCHAR
const *family
, DWRITE_FONT_WEIGHT weight
,
7672 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontSet
**fontset
)
7674 FIXME("%p, %s, %d, %d, %d, %p.\n", iface
, debugstr_w(family
), weight
, stretch
, style
, fontset
);
7679 static HRESULT WINAPI
dwritefontset_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
, UINT32 count
,
7680 IDWriteFontSet
**filtered_set
)
7682 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7683 struct dwrite_fontset_entry
**entries
;
7684 unsigned int i
, matched_count
= 0;
7685 struct dwrite_fontset
*object
;
7687 TRACE("%p, %p, %u, %p.\n", iface
, props
, count
, filtered_set
);
7689 if (!props
&& count
)
7690 return E_INVALIDARG
;
7692 if (!(object
= calloc(1, sizeof(*object
))))
7693 return E_OUTOFMEMORY
;
7695 if (!(entries
= calloc(set
->count
, sizeof(*entries
))))
7698 return E_OUTOFMEMORY
;
7701 for (i
= 0; i
< set
->count
; ++i
)
7703 if (fontset_entry_is_matching(set
->entries
[i
], props
, count
))
7705 entries
[matched_count
++] = addref_fontset_entry(set
->entries
[i
]);
7715 init_fontset(object
, set
->factory
, entries
, matched_count
);
7717 *filtered_set
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7722 static HRESULT WINAPI
dwritefontset1_GetMatchingFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *property
,
7723 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontSet1
**fontset
)
7725 FIXME("%p, %p, %p, %u, %p.\n", iface
, property
, axis_values
, num_values
, fontset
);
7730 static HRESULT WINAPI
dwritefontset1_GetFirstFontResources(IDWriteFontSet3
*iface
, IDWriteFontSet1
**fontset
)
7732 FIXME("%p, %p.\n", iface
, fontset
);
7737 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts__(IDWriteFontSet3
*iface
, UINT32
const *indices
,
7738 UINT32 num_indices
, IDWriteFontSet1
**fontset
)
7740 FIXME("%p, %p, %u, %p.\n", iface
, indices
, num_indices
, fontset
);
7745 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *axis_ranges
,
7746 UINT32 num_ranges
, BOOL select_any_range
, IDWriteFontSet1
**fontset
)
7748 FIXME("%p, %p, %u, %d, %p.\n", iface
, axis_ranges
, num_ranges
, select_any_range
, fontset
);
7753 static HRESULT WINAPI
dwritefontset1_GetFilteredFonts(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7754 UINT32 num_properties
, BOOL select_any_property
, IDWriteFontSet1
**fontset
)
7756 FIXME("%p, %p, %u, %d, %p.\n", iface
, props
, num_properties
, select_any_property
, fontset
);
7761 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices_(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
const *ranges
,
7762 UINT32 num_ranges
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7764 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, ranges
, num_ranges
, select_any_range
, indices
, num_indices
, actual_num_indices
);
7769 static HRESULT WINAPI
dwritefontset1_GetFilteredFontIndices(IDWriteFontSet3
*iface
, DWRITE_FONT_PROPERTY
const *props
,
7770 UINT32 num_properties
, BOOL select_any_range
, UINT32
*indices
, UINT32 num_indices
, UINT32
*actual_num_indices
)
7772 FIXME("%p, %p, %u, %d, %p, %u, %p.\n", iface
, props
, num_properties
, select_any_range
, indices
,
7773 num_indices
, actual_num_indices
);
7778 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges_(IDWriteFontSet3
*iface
, UINT32 font_index
,
7779 DWRITE_FONT_AXIS_RANGE
*axis_ranges
, UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7781 FIXME("%p, %u, %p, %u, %p.\n", iface
, font_index
, axis_ranges
, num_ranges
, actual_num_ranges
);
7786 static HRESULT WINAPI
dwritefontset1_GetFontAxisRanges(IDWriteFontSet3
*iface
, DWRITE_FONT_AXIS_RANGE
*axis_ranges
,
7787 UINT32 num_ranges
, UINT32
*actual_num_ranges
)
7789 FIXME("%p, %p, %u, %p.\n", iface
, axis_ranges
, num_ranges
, actual_num_ranges
);
7794 static HRESULT WINAPI
dwritefontset1_GetFontFaceReference(IDWriteFontSet3
*iface
, UINT32 index
,
7795 IDWriteFontFaceReference1
**reference
)
7797 FIXME("%p, %u, %p.\n", iface
, index
, reference
);
7802 static HRESULT WINAPI
dwritefontset1_CreateFontResource(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontResource
**resource
)
7804 struct dwrite_fontset
*set
= impl_from_IDWriteFontSet3(iface
);
7806 TRACE("%p, %u, %p.\n", iface
, index
, resource
);
7810 if (index
>= set
->count
)
7811 return E_INVALIDARG
;
7813 return IDWriteFactory7_CreateFontResource(set
->factory
, set
->entries
[index
]->file
,
7814 set
->entries
[index
]->face_index
, resource
);
7817 static HRESULT WINAPI
dwritefontset1_CreateFontFace(IDWriteFontSet3
*iface
, UINT32 index
, IDWriteFontFace5
**fontface
)
7819 FIXME("%p, %u, %p.\n", iface
, index
, fontface
);
7824 static DWRITE_LOCALITY WINAPI
dwritefontset1_GetFontLocality(IDWriteFontSet3
*iface
, UINT32 index
)
7826 FIXME("%p, %u.\n", iface
, index
);
7828 return DWRITE_LOCALITY_LOCAL
;
7831 static HANDLE WINAPI
dwritefontset2_GetExpirationEvent(IDWriteFontSet3
*iface
)
7833 FIXME("%p.\n", iface
);
7838 static DWRITE_FONT_SOURCE_TYPE WINAPI
dwritefontset3_GetFontSourceType(IDWriteFontSet3
*iface
, UINT32 index
)
7840 FIXME("%p, %u.\n", iface
, index
);
7842 return DWRITE_FONT_SOURCE_TYPE_UNKNOWN
;
7845 static UINT32 WINAPI
dwritefontset3_GetFontSourceNameLength(IDWriteFontSet3
*iface
, UINT32 index
)
7847 FIXME("%p, %u.\n", iface
, index
);
7852 static HRESULT WINAPI
dwritefontset3_GetFontSourceName(IDWriteFontSet3
*iface
, UINT32 index
, WCHAR
*buffer
, UINT32 buffer_size
)
7854 FIXME("%p, %u, %p, %u.\n", iface
, index
, buffer
, buffer_size
);
7859 static const IDWriteFontSet3Vtbl fontsetvtbl
=
7861 dwritefontset_QueryInterface
,
7862 dwritefontset_AddRef
,
7863 dwritefontset_Release
,
7864 dwritefontset_GetFontCount
,
7865 dwritefontset_GetFontFaceReference
,
7866 dwritefontset_FindFontFaceReference
,
7867 dwritefontset_FindFontFace
,
7868 dwritefontset_GetPropertyValues__
,
7869 dwritefontset_GetPropertyValues_
,
7870 dwritefontset_GetPropertyValues
,
7871 dwritefontset_GetPropertyOccurrenceCount
,
7872 dwritefontset_GetMatchingFonts_
,
7873 dwritefontset_GetMatchingFonts
,
7874 dwritefontset1_GetMatchingFonts
,
7875 dwritefontset1_GetFirstFontResources
,
7876 dwritefontset1_GetFilteredFonts__
,
7877 dwritefontset1_GetFilteredFonts_
,
7878 dwritefontset1_GetFilteredFonts
,
7879 dwritefontset1_GetFilteredFontIndices_
,
7880 dwritefontset1_GetFilteredFontIndices
,
7881 dwritefontset1_GetFontAxisRanges_
,
7882 dwritefontset1_GetFontAxisRanges
,
7883 dwritefontset1_GetFontFaceReference
,
7884 dwritefontset1_CreateFontResource
,
7885 dwritefontset1_CreateFontFace
,
7886 dwritefontset1_GetFontLocality
,
7887 dwritefontset2_GetExpirationEvent
,
7888 dwritefontset3_GetFontSourceType
,
7889 dwritefontset3_GetFontSourceNameLength
,
7890 dwritefontset3_GetFontSourceName
,
7893 static HRESULT
fontset_create_entry(IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
,
7894 unsigned int face_index
, unsigned int simulations
, struct dwrite_fontset_entry
**ret
)
7896 struct dwrite_fontset_entry
*entry
;
7898 if (!(entry
= calloc(1, sizeof(*entry
))))
7899 return E_OUTOFMEMORY
;
7901 entry
->refcount
= 1;
7903 IDWriteFontFile_AddRef(entry
->file
);
7904 entry
->face_type
= face_type
;
7905 entry
->face_index
= face_index
;
7906 entry
->simulations
= simulations
;
7913 static void init_fontset(struct dwrite_fontset
*object
, IDWriteFactory7
*factory
,
7914 struct dwrite_fontset_entry
**entries
, unsigned int count
)
7916 object
->IDWriteFontSet3_iface
.lpVtbl
= &fontsetvtbl
;
7917 object
->refcount
= 1;
7918 object
->factory
= factory
;
7919 IDWriteFactory7_AddRef(object
->factory
);
7920 object
->entries
= entries
;
7921 object
->count
= count
;
7924 static HRESULT
fontset_create_from_font_data(IDWriteFactory7
*factory
, struct dwrite_font_data
**fonts
,
7925 unsigned int count
, IDWriteFontSet1
**ret
)
7927 struct dwrite_fontset_entry
**entries
= NULL
;
7928 struct dwrite_fontset
*object
;
7931 if (!(object
= calloc(1, sizeof(*object
))))
7932 return E_OUTOFMEMORY
;
7936 entries
= calloc(count
, sizeof(*entries
));
7938 /* FIXME: set available properties too */
7940 for (i
= 0; i
< count
; ++i
)
7942 fontset_create_entry(fonts
[i
]->file
, fonts
[i
]->face_type
, fonts
[i
]->face_index
,
7943 fonts
[i
]->simulations
, &entries
[i
]);
7946 init_fontset(object
, factory
, entries
, count
);
7948 *ret
= (IDWriteFontSet1
*)&object
->IDWriteFontSet3_iface
;
7953 static HRESULT
fontset_builder_create_fontset(IDWriteFactory7
*factory
, struct dwrite_fontset_entry
**src_entries
,
7954 unsigned int count
, IDWriteFontSet
**ret
)
7956 struct dwrite_fontset_entry
**entries
= NULL
;
7957 struct dwrite_fontset
*object
;
7960 if (!(object
= calloc(1, sizeof(*object
))))
7961 return E_OUTOFMEMORY
;
7965 entries
= calloc(count
, sizeof(*entries
));
7967 for (i
= 0; i
< count
; ++i
)
7968 entries
[i
] = addref_fontset_entry(src_entries
[i
]);
7970 init_fontset(object
, factory
, entries
, count
);
7972 *ret
= (IDWriteFontSet
*)&object
->IDWriteFontSet3_iface
;
7977 static HRESULT WINAPI
dwritefontsetbuilder_QueryInterface(IDWriteFontSetBuilder2
*iface
,
7978 REFIID riid
, void **obj
)
7980 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
7982 if (IsEqualIID(riid
, &IID_IDWriteFontSetBuilder2
) ||
7983 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder1
) ||
7984 IsEqualIID(riid
, &IID_IDWriteFontSetBuilder
) ||
7985 IsEqualIID(riid
, &IID_IUnknown
))
7988 IDWriteFontSetBuilder2_AddRef(iface
);
7992 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
7994 return E_NOINTERFACE
;
7997 static ULONG WINAPI
dwritefontsetbuilder_AddRef(IDWriteFontSetBuilder2
*iface
)
7999 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8000 ULONG refcount
= InterlockedIncrement(&builder
->refcount
);
8002 TRACE("%p, refcount %u.\n", iface
, refcount
);
8007 static ULONG WINAPI
dwritefontsetbuilder_Release(IDWriteFontSetBuilder2
*iface
)
8009 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8010 ULONG refcount
= InterlockedDecrement(&builder
->refcount
);
8013 TRACE("%p, refcount %u.\n", iface
, refcount
);
8017 IDWriteFactory7_Release(builder
->factory
);
8018 for (i
= 0; i
< builder
->count
; ++i
)
8019 release_fontset_entry(builder
->entries
[i
]);
8020 free(builder
->entries
);
8027 static HRESULT
fontset_builder_add_entry(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
,
8028 DWRITE_FONT_FACE_TYPE face_type
, unsigned int face_index
, unsigned int simulations
)
8030 struct dwrite_fontset_entry
*entry
;
8033 if (!dwrite_array_reserve((void **)&builder
->entries
, &builder
->capacity
, builder
->count
+ 1,
8034 sizeof(*builder
->entries
)))
8036 return E_OUTOFMEMORY
;
8039 if (FAILED(hr
= fontset_create_entry(file
, face_type
, face_index
, simulations
, &entry
)))
8042 builder
->entries
[builder
->count
++] = entry
;
8047 static HRESULT
fontset_builder_add_file(struct dwrite_fontset_builder
*builder
, IDWriteFontFile
*file
)
8049 DWRITE_FONT_FILE_TYPE filetype
;
8050 DWRITE_FONT_FACE_TYPE facetype
;
8051 unsigned int i
, face_count
;
8052 BOOL supported
= FALSE
;
8055 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &filetype
, &facetype
, &face_count
)))
8059 return DWRITE_E_FILEFORMAT
;
8061 for (i
= 0; i
< face_count
; ++i
)
8063 if (FAILED(hr
= fontset_builder_add_entry(builder
, file
, facetype
, i
, DWRITE_FONT_SIMULATIONS_NONE
)))
8070 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference_(IDWriteFontSetBuilder2
*iface
,
8071 IDWriteFontFaceReference
*ref
, DWRITE_FONT_PROPERTY
const *props
, UINT32 prop_count
)
8073 FIXME("%p, %p, %p, %u.\n", iface
, ref
, props
, prop_count
);
8078 static HRESULT WINAPI
dwritefontsetbuilder_AddFontFaceReference(IDWriteFontSetBuilder2
*iface
,
8079 IDWriteFontFaceReference
*ref
)
8081 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8082 unsigned int face_count
, face_index
, simulations
;
8083 DWRITE_FONT_FILE_TYPE file_type
;
8084 DWRITE_FONT_FACE_TYPE face_type
;
8085 IDWriteFontFile
*file
;
8089 TRACE("%p, %p.\n", iface
, ref
);
8091 if (FAILED(hr
= IDWriteFontFaceReference_GetFontFile(ref
, &file
))) return hr
;
8092 if (FAILED(hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
)))
8097 hr
= DWRITE_E_FILEFORMAT
;
8101 face_index
= IDWriteFontFaceReference_GetFontFaceIndex(ref
);
8102 simulations
= IDWriteFontFaceReference_GetSimulations(ref
);
8103 hr
= fontset_builder_add_entry(builder
, file
, face_type
, face_index
, simulations
);
8106 IDWriteFontFile_Release(file
);
8111 static HRESULT WINAPI
dwritefontsetbuilder_AddFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
*fontset
)
8113 FIXME("%p, %p.\n", iface
, fontset
);
8118 static HRESULT WINAPI
dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
*iface
, IDWriteFontSet
**fontset
)
8120 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8122 TRACE("%p, %p.\n", iface
, fontset
);
8124 return fontset_builder_create_fontset(builder
->factory
, builder
->entries
, builder
->count
, fontset
);
8127 static HRESULT WINAPI
dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
)
8129 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8131 TRACE("%p, %p.\n", iface
, file
);
8133 return fontset_builder_add_file(builder
, file
);
8136 static HRESULT WINAPI
dwritefontsetbuilder2_AddFont(IDWriteFontSetBuilder2
*iface
, IDWriteFontFile
*file
,
8137 unsigned int face_index
, DWRITE_FONT_SIMULATIONS simulations
, const DWRITE_FONT_AXIS_VALUE
*axis_values
,
8138 unsigned int num_values
, const DWRITE_FONT_AXIS_RANGE
*axis_ranges
, unsigned int num_ranges
,
8139 const DWRITE_FONT_PROPERTY
*props
, unsigned int num_properties
)
8141 FIXME("%p, %p, %u, %#x, %p, %u, %p, %u, %p, %u.\n", iface
, file
, face_index
, simulations
, axis_values
, num_values
,
8142 axis_ranges
, num_ranges
, props
, num_properties
);
8147 static HRESULT WINAPI
dwritefontsetbuilder2_AddFontFile(IDWriteFontSetBuilder2
*iface
, const WCHAR
*filepath
)
8149 struct dwrite_fontset_builder
*builder
= impl_from_IDWriteFontSetBuilder2(iface
);
8150 IDWriteFontFile
*file
;
8153 TRACE("%p, %s.\n", iface
, debugstr_w(filepath
));
8155 if (FAILED(hr
= IDWriteFactory7_CreateFontFileReference(builder
->factory
, filepath
, NULL
, &file
)))
8158 hr
= fontset_builder_add_file(builder
, file
);
8159 IDWriteFontFile_Release(file
);
8163 static const IDWriteFontSetBuilder2Vtbl fontsetbuildervtbl
=
8165 dwritefontsetbuilder_QueryInterface
,
8166 dwritefontsetbuilder_AddRef
,
8167 dwritefontsetbuilder_Release
,
8168 dwritefontsetbuilder_AddFontFaceReference_
,
8169 dwritefontsetbuilder_AddFontFaceReference
,
8170 dwritefontsetbuilder_AddFontSet
,
8171 dwritefontsetbuilder_CreateFontSet
,
8172 dwritefontsetbuilder1_AddFontFile
,
8173 dwritefontsetbuilder2_AddFont
,
8174 dwritefontsetbuilder2_AddFontFile
,
8177 HRESULT
create_fontset_builder(IDWriteFactory7
*factory
, IDWriteFontSetBuilder2
**ret
)
8179 struct dwrite_fontset_builder
*builder
;
8183 if (!(builder
= calloc(1, sizeof(*builder
))))
8184 return E_OUTOFMEMORY
;
8186 builder
->IDWriteFontSetBuilder2_iface
.lpVtbl
= &fontsetbuildervtbl
;
8187 builder
->refcount
= 1;
8188 builder
->factory
= factory
;
8189 IDWriteFactory7_AddRef(builder
->factory
);
8191 *ret
= &builder
->IDWriteFontSetBuilder2_iface
;