4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2017 Nikolay Sivov for CodeWeavers
6 * Copyright 2014 Aric Stewart for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "dwrite_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
31 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
33 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
34 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
35 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
36 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
37 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
38 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
39 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
40 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
42 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
44 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
45 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
46 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
48 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
49 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
50 static const WCHAR semiW
[] = {'s','e','m','i',0};
51 static const WCHAR extW
[] = {'e','x','t',0};
52 static const WCHAR thinW
[] = {'t','h','i','n',0};
53 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
54 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
55 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
56 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
57 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
58 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
59 static const WCHAR boldW
[] = {'B','o','l','d',0};
60 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
61 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
62 static const WCHAR demiW
[] = {'d','e','m','i',0};
63 static const WCHAR spaceW
[] = {' ',0};
64 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
66 struct dwrite_font_propvec
{
72 struct dwrite_font_data
76 DWRITE_FONT_STYLE style
;
77 DWRITE_FONT_STRETCH stretch
;
78 DWRITE_FONT_WEIGHT weight
;
80 FONTSIGNATURE fontsig
;
81 UINT32 flags
; /* enum font_flags */
82 struct dwrite_font_propvec propvec
;
84 DWRITE_FONT_METRICS1 metrics
;
85 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
+ 1];
86 IDWriteLocalizedStrings
*family_names
;
87 IDWriteLocalizedStrings
*names
;
89 /* data needed to create fontface instance */
90 DWRITE_FONT_FACE_TYPE face_type
;
91 IDWriteFontFile
*file
;
100 /* used to mark font as tested when scanning for simulation candidate */
101 BOOL bold_sim_tested
: 1;
102 BOOL oblique_sim_tested
: 1;
105 struct dwrite_fontfamily_data
109 IDWriteLocalizedStrings
*familyname
;
111 struct dwrite_font_data
**fonts
;
115 BOOL has_normal_face
: 1;
116 BOOL has_oblique_face
: 1;
117 BOOL has_italic_face
: 1;
120 struct dwrite_fontcollection
122 IDWriteFontCollection3 IDWriteFontCollection3_iface
;
125 IDWriteFactory7
*factory
;
126 struct dwrite_fontfamily_data
**family_data
;
131 struct dwrite_fontfamily
133 IDWriteFontFamily2 IDWriteFontFamily2_iface
;
134 IDWriteFontList2 IDWriteFontList2_iface
;
137 struct dwrite_fontfamily_data
*data
;
138 struct dwrite_fontcollection
*collection
;
141 struct dwrite_fontlist
143 IDWriteFontList2 IDWriteFontList2_iface
;
146 struct dwrite_font_data
**fonts
;
148 struct dwrite_fontfamily
*family
;
152 IDWriteFont3 IDWriteFont3_iface
;
155 DWRITE_FONT_STYLE style
;
156 struct dwrite_font_data
*data
;
157 struct dwrite_fontfamily
*family
;
160 enum runanalysis_flags
{
161 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
162 RUNANALYSIS_BITMAP_READY
= 1 << 1,
163 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
166 struct dwrite_glyphrunanalysis
{
167 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
170 DWRITE_RENDERING_MODE1 rendering_mode
;
171 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
172 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
175 D2D_POINT_2F
*origins
;
180 UINT32 max_glyph_bitmap_size
;
183 struct dwrite_colorglyphenum
185 IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface
;
188 FLOAT origin_x
; /* original run origin */
191 IDWriteFontFace5
*fontface
; /* for convenience */
192 DWRITE_COLOR_GLYPH_RUN1 colorrun
; /* returned with GetCurrentRun() */
193 DWRITE_GLYPH_RUN run
; /* base run */
194 UINT32 palette
; /* palette index to get layer color from */
195 FLOAT
*advances
; /* original or measured advances for base glyphs */
196 FLOAT
*color_advances
; /* returned color run points to this */
197 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
198 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
199 UINT16
*glyphindices
; /* returned color run points to this */
200 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
201 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
202 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
203 UINT16 max_layer_num
; /* max number of layers for this run */
204 struct dwrite_fonttable colr
; /* used to access layers */
207 #define GLYPH_BLOCK_SHIFT 8
208 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
209 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
210 #define GLYPH_MAX 65536
212 struct dwrite_fontfile
{
213 IDWriteFontFile IDWriteFontFile_iface
;
216 IDWriteFontFileLoader
*loader
;
219 IDWriteFontFileStream
*stream
;
222 struct dwrite_fontfacereference
224 IDWriteFontFaceReference1 IDWriteFontFaceReference1_iface
;
227 IDWriteFontFile
*file
;
230 DWRITE_FONT_AXIS_VALUE
*axis_values
;
231 UINT32 axis_values_count
;
232 IDWriteFactory7
*factory
;
235 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
;
237 struct dwrite_fontresource
239 IDWriteFontResource IDWriteFontResource_iface
;
242 IDWriteFontFile
*file
;
244 IDWriteFactory7
*factory
;
247 static void dwrite_grab_font_table(void *context
, UINT32 table
, const BYTE
**data
, UINT32
*size
, void **data_context
)
249 struct dwrite_fontface
*fontface
= context
;
252 if (FAILED(IDWriteFontFace5_TryGetFontTable(&fontface
->IDWriteFontFace5_iface
, table
, (const void **)data
,
253 size
, data_context
, &exists
)) || !exists
)
257 *data_context
= NULL
;
261 static void dwrite_release_font_table(void *context
, void *data_context
)
263 struct dwrite_fontface
*fontface
= context
;
264 IDWriteFontFace5_ReleaseFontTable(&fontface
->IDWriteFontFace5_iface
, data_context
);
267 static UINT16
dwrite_get_font_upem(void *context
)
269 struct dwrite_fontface
*fontface
= context
;
270 return fontface
->metrics
.designUnitsPerEm
;
273 static const struct shaping_font_ops dwrite_font_ops
=
275 dwrite_grab_font_table
,
276 dwrite_release_font_table
,
277 dwrite_get_font_upem
,
280 struct scriptshaping_cache
*fontface_get_shaping_cache(struct dwrite_fontface
*fontface
)
282 if (fontface
->shaping_cache
)
283 return fontface
->shaping_cache
;
285 return fontface
->shaping_cache
= create_scriptshaping_cache(fontface
, &dwrite_font_ops
);
288 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace5(IDWriteFontFace5
*iface
)
290 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
293 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
295 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
298 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
300 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
303 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily2(IDWriteFontFamily2
*iface
)
305 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily2_iface
);
308 static inline struct dwrite_fontfamily
*impl_family_from_IDWriteFontList2(IDWriteFontList2
*iface
)
310 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontList2_iface
);
313 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection3(IDWriteFontCollection3
*iface
)
315 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection3_iface
);
318 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
320 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
323 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator1(IDWriteColorGlyphRunEnumerator1
*iface
)
325 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator1_iface
);
328 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList2(IDWriteFontList2
*iface
)
330 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList2_iface
);
333 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference1(IDWriteFontFaceReference1
*iface
)
335 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference1_iface
);
338 static struct dwrite_fontresource
*impl_from_IDWriteFontResource(IDWriteFontResource
*iface
)
340 return CONTAINING_RECORD(iface
, struct dwrite_fontresource
, IDWriteFontResource_iface
);
343 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
345 static const DWRITE_GLYPH_METRICS nil
;
346 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
348 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
349 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
353 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
355 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
358 /* start new block */
359 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
361 return E_OUTOFMEMORY
;
364 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
368 const void* get_fontface_table(IDWriteFontFace5
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
372 if (table
->data
|| !table
->exists
)
375 table
->exists
= FALSE
;
376 hr
= IDWriteFontFace5_TryGetFontTable(fontface
, tag
, (const void **)&table
->data
, &table
->size
, &table
->context
,
378 if (FAILED(hr
) || !table
->exists
) {
379 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
386 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
387 struct dwrite_font_propvec
*vec
)
389 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
390 vec
->style
= style
* 7.0f
;
391 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
394 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
396 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
399 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
401 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
404 static const struct dwrite_fonttable
*get_fontface_vdmx(struct dwrite_fontface
*fontface
)
406 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
407 return &fontface
->vdmx
;
410 static const struct dwrite_fonttable
*get_fontface_gasp(struct dwrite_fontface
*fontface
)
412 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_GASP_TAG
, &fontface
->gasp
);
413 return &fontface
->gasp
;
416 static const struct dwrite_fonttable
*get_fontface_cpal(struct dwrite_fontface
*fontface
)
418 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
419 return &fontface
->cpal
;
422 static void addref_font_data(struct dwrite_font_data
*data
)
424 InterlockedIncrement(&data
->ref
);
427 static void release_font_data(struct dwrite_font_data
*data
)
431 if (InterlockedDecrement(&data
->ref
) > 0)
434 for (i
= 0; i
< ARRAY_SIZE(data
->info_strings
); ++i
)
436 if (data
->info_strings
[i
])
437 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
440 IDWriteLocalizedStrings_Release(data
->names
);
442 if (data
->family_names
)
443 IDWriteLocalizedStrings_Release(data
->family_names
);
445 IDWriteFontFile_Release(data
->file
);
446 heap_free(data
->facename
);
450 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
454 if (InterlockedDecrement(&data
->refcount
) > 0)
457 for (i
= 0; i
< data
->count
; ++i
)
458 release_font_data(data
->fonts
[i
]);
459 heap_free(data
->fonts
);
460 IDWriteLocalizedStrings_Release(data
->familyname
);
464 void fontface_detach_from_cache(IDWriteFontFace5
*iface
)
466 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
467 fontface
->cached
= NULL
;
470 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace5
*iface
, REFIID riid
, void **obj
)
472 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
474 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
476 if (IsEqualIID(riid
, &IID_IDWriteFontFace5
) ||
477 IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
478 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
479 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
480 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
481 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
482 IsEqualIID(riid
, &IID_IUnknown
))
485 if (InterlockedIncrement(&fontface
->refcount
) == 1)
487 InterlockedDecrement(&fontface
->refcount
);
494 WARN("%s not implemented.\n", debugstr_guid(riid
));
497 return E_NOINTERFACE
;
500 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace5
*iface
)
502 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
503 ULONG refcount
= InterlockedIncrement(&fontface
->refcount
);
505 TRACE("%p, refcount %u.\n", iface
, refcount
);
510 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace5
*iface
)
512 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
513 ULONG refcount
= InterlockedDecrement(&fontface
->refcount
);
515 TRACE("%p, refcount %u.\n", iface
, refcount
);
521 if (fontface
->cached
)
523 factory_lock(fontface
->factory
);
524 list_remove(&fontface
->cached
->entry
);
525 factory_unlock(fontface
->factory
);
526 heap_free(fontface
->cached
);
528 release_scriptshaping_cache(fontface
->shaping_cache
);
529 if (fontface
->cmap
.context
)
530 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cmap
.context
);
531 if (fontface
->vdmx
.context
)
532 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->vdmx
.context
);
533 if (fontface
->gasp
.context
)
534 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->gasp
.context
);
535 if (fontface
->cpal
.context
)
536 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->cpal
.context
);
537 if (fontface
->colr
.context
)
538 IDWriteFontFace5_ReleaseFontTable(iface
, fontface
->colr
.context
);
539 for (i
= 0; i
< fontface
->file_count
; i
++)
541 if (fontface
->files
[i
])
542 IDWriteFontFile_Release(fontface
->files
[i
]);
544 if (fontface
->stream
)
545 IDWriteFontFileStream_Release(fontface
->stream
);
546 heap_free(fontface
->files
);
548 IDWriteLocalizedStrings_Release(fontface
->names
);
549 if (fontface
->family_names
)
550 IDWriteLocalizedStrings_Release(fontface
->family_names
);
551 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
553 if (fontface
->info_strings
[i
])
554 IDWriteLocalizedStrings_Release(fontface
->info_strings
[i
]);
557 for (i
= 0; i
< ARRAY_SIZE(fontface
->glyphs
); i
++)
558 heap_free(fontface
->glyphs
[i
]);
560 freetype_notify_cacheremove(iface
);
562 IDWriteFactory7_Release(fontface
->factory
);
569 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace5
*iface
)
571 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
573 TRACE("%p.\n", iface
);
575 return fontface
->type
;
578 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace5
*iface
, UINT32
*number_of_files
,
579 IDWriteFontFile
**fontfiles
)
581 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
584 TRACE("%p, %p, %p.\n", iface
, number_of_files
, fontfiles
);
586 if (fontfiles
== NULL
)
588 *number_of_files
= fontface
->file_count
;
592 if (*number_of_files
< fontface
->file_count
)
595 for (i
= 0; i
< fontface
->file_count
; i
++)
597 IDWriteFontFile_AddRef(fontface
->files
[i
]);
598 fontfiles
[i
] = fontface
->files
[i
];
604 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace5
*iface
)
606 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
608 TRACE("%p.\n", iface
);
610 return fontface
->index
;
613 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace5
*iface
)
615 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
617 TRACE("%p.\n", iface
);
619 return fontface
->simulations
;
622 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace5
*iface
)
624 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
626 TRACE("%p.\n", iface
);
628 return !!(fontface
->flags
& FONT_IS_SYMBOL
);
631 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS
*metrics
)
633 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
635 TRACE("%p, %p.\n", iface
, metrics
);
637 memcpy(metrics
, &fontface
->metrics
, sizeof(*metrics
));
640 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace5
*iface
)
642 TRACE("%p.\n", iface
);
644 return freetype_get_glyphcount(iface
);
647 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5
*iface
,
648 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
650 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
654 TRACE("%p, %p, %u, %p, %d.\n", iface
, glyphs
, glyph_count
, ret
, is_sideways
);
660 FIXME("sideways metrics are not supported.\n");
662 for (i
= 0; i
< glyph_count
; i
++) {
663 DWRITE_GLYPH_METRICS metrics
;
665 hr
= get_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
667 freetype_get_design_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
668 hr
= set_cached_glyph_metrics(fontface
, glyphs
[i
], &metrics
);
678 static HRESULT
fontface_get_glyphs(struct dwrite_fontface
*fontface
, UINT32
const *codepoints
,
679 UINT32 count
, UINT16
*glyphs
)
685 memset(glyphs
, 0, count
* sizeof(*glyphs
));
689 freetype_get_glyphs(&fontface
->IDWriteFontFace5_iface
, fontface
->charmap
, codepoints
, count
, glyphs
);
693 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace5
*iface
, UINT32
const *codepoints
,
694 UINT32 count
, UINT16
*glyphs
)
696 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
698 TRACE("%p, %p, %u, %p.\n", iface
, codepoints
, count
, glyphs
);
700 return fontface_get_glyphs(fontface
, codepoints
, count
, glyphs
);
703 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace5
*iface
, UINT32 table_tag
,
704 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
706 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
707 struct file_stream_desc stream_desc
;
709 TRACE("%p, %s, %p, %p, %p, %p.\n", iface
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
711 stream_desc
.stream
= fontface
->stream
;
712 stream_desc
.face_type
= fontface
->type
;
713 stream_desc
.face_index
= fontface
->index
;
714 return opentype_try_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
717 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace5
*iface
, void *table_context
)
719 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
721 TRACE("%p, %p.\n", iface
, table_context
);
723 IDWriteFontFileStream_ReleaseFileFragment(fontface
->stream
, table_context
);
726 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace5
*iface
, FLOAT emSize
,
727 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
728 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
730 TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface
, emSize
, glyphs
, advances
, offsets
,
731 count
, is_sideways
, is_rtl
, sink
);
733 if (!glyphs
|| !sink
)
737 FIXME("sideways mode is not supported.\n");
739 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
742 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
743 float ppem
, unsigned int gasp
)
745 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
749 case DWRITE_MEASURING_MODE_NATURAL
:
751 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
752 mode
= DWRITE_RENDERING_MODE_NATURAL
;
754 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
757 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
758 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
760 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
761 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
770 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
771 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
773 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
777 TRACE("%p, %.8e, %.8e, %d, %p, %p.\n", iface
, emSize
, ppdip
, measuring
, params
, mode
);
780 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
784 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
785 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
788 ppem
= emSize
* ppdip
;
790 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
791 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
795 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), ppem
);
796 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, flags
);
800 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
801 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
803 DWRITE_FONT_METRICS1 metrics1
;
804 HRESULT hr
= IDWriteFontFace5_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
805 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
809 static inline int round_metric(FLOAT metric
)
811 return (int)floorf(metric
+ 0.5f
);
814 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
816 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
819 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
822 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT ppdip
,
823 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
824 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
826 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
827 UINT32 adjustment
= fontface_get_horz_metric_adjustment(fontface
);
828 DWRITE_MEASURING_MODE mode
;
833 TRACE("%p, %.8e, %.8e, %p, %d, %p, %u, %p, %d.\n", iface
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
834 glyph_count
, metrics
, is_sideways
);
836 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
837 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
839 size
= emSize
* ppdip
;
840 scale
= size
/ fontface
->metrics
.designUnitsPerEm
;
841 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
843 for (i
= 0; i
< glyph_count
; i
++) {
844 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
845 DWRITE_GLYPH_METRICS design
;
848 hr
= IDWriteFontFace5_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
852 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
854 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
856 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* fontface
->metrics
.designUnitsPerEm
/ size
);
858 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
859 SCALE_METRIC(leftSideBearing
);
860 SCALE_METRIC(rightSideBearing
);
861 SCALE_METRIC(topSideBearing
);
862 SCALE_METRIC(advanceHeight
);
863 SCALE_METRIC(bottomSideBearing
);
864 SCALE_METRIC(verticalOriginY
);
871 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace5
*iface
, DWRITE_FONT_METRICS1
*metrics
)
873 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
875 TRACE("%p, %p.\n", iface
, metrics
);
877 *metrics
= fontface
->metrics
;
880 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace5
*iface
, FLOAT em_size
,
881 FLOAT pixels_per_dip
, const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
883 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
884 const DWRITE_FONT_METRICS1
*design
= &fontface
->metrics
;
885 UINT16 ascent
, descent
;
888 TRACE("%p, %.8e, %.8e, %p, %p.\n", iface
, em_size
, pixels_per_dip
, m
, metrics
);
890 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
891 memset(metrics
, 0, sizeof(*metrics
));
895 em_size
*= pixels_per_dip
;
896 if (m
&& m
->m22
!= 0.0f
)
897 em_size
*= fabs(m
->m22
);
899 scale
= em_size
/ design
->designUnitsPerEm
;
900 if (!opentype_get_vdmx_size(get_fontface_vdmx(fontface
), em_size
, &ascent
, &descent
))
902 ascent
= round_metric(design
->ascent
* scale
);
903 descent
= round_metric(design
->descent
* scale
);
906 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
907 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
908 metrics
->ascent
= round_metric(ascent
/ scale
);
909 metrics
->descent
= round_metric(descent
/ scale
);
911 SCALE_METRIC(lineGap
);
912 SCALE_METRIC(capHeight
);
913 SCALE_METRIC(xHeight
);
914 SCALE_METRIC(underlinePosition
);
915 SCALE_METRIC(underlineThickness
);
916 SCALE_METRIC(strikethroughPosition
);
917 SCALE_METRIC(strikethroughThickness
);
918 SCALE_METRIC(glyphBoxLeft
);
919 SCALE_METRIC(glyphBoxTop
);
920 SCALE_METRIC(glyphBoxRight
);
921 SCALE_METRIC(glyphBoxBottom
);
922 SCALE_METRIC(subscriptPositionX
);
923 SCALE_METRIC(subscriptPositionY
);
924 SCALE_METRIC(subscriptSizeX
);
925 SCALE_METRIC(subscriptSizeY
);
926 SCALE_METRIC(superscriptPositionX
);
927 SCALE_METRIC(superscriptPositionY
);
928 SCALE_METRIC(superscriptSizeX
);
929 SCALE_METRIC(superscriptSizeY
);
931 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
937 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace5
*iface
, DWRITE_CARET_METRICS
*metrics
)
939 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
941 TRACE("%p, %p.\n", iface
, metrics
);
943 *metrics
= fontface
->caret
;
946 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace5
*iface
, UINT32 max_count
,
947 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
949 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
951 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
954 if (max_count
&& !ranges
)
957 get_fontface_table(iface
, MS_CMAP_TAG
, &fontface
->cmap
);
958 return opentype_cmap_get_unicode_ranges(&fontface
->cmap
, max_count
, ranges
, count
);
961 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace5
*iface
)
963 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
965 TRACE("%p.\n", iface
);
967 return !!(fontface
->flags
& FONT_IS_MONOSPACED
);
970 static int fontface_get_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
971 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
973 unsigned int adjustment
= fontface_get_horz_metric_adjustment(fontface
);
978 FIXME("Sideways mode is not supported.\n");
980 switch (measuring_mode
)
982 case DWRITE_MEASURING_MODE_NATURAL
:
983 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, fontface
->metrics
.designUnitsPerEm
,
984 glyph
, measuring_mode
, &has_contours
);
986 advance
+= adjustment
;
989 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
990 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
995 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
)))
996 FIXME("Transform is not supported.\n");
998 advance
= freetype_get_glyph_advance(&fontface
->IDWriteFontFace5_iface
, emsize
, glyph
, measuring_mode
,
1001 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
+ adjustment
);
1003 advance
= round_metric(advance
* fontface
->metrics
.designUnitsPerEm
/ emsize
);
1007 WARN("Unknown measuring mode %u.\n", measuring_mode
);
1012 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace5
*iface
,
1013 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
1015 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1018 TRACE("%p, %u, %p, %p, %d.\n", iface
, glyph_count
, glyphs
, advances
, is_sideways
);
1021 FIXME("sideways mode not supported\n");
1023 for (i
= 0; i
< glyph_count
; ++i
)
1025 advances
[i
] = fontface_get_design_advance(fontface
, DWRITE_MEASURING_MODE_NATURAL
,
1026 fontface
->metrics
.designUnitsPerEm
, 1.0f
, NULL
, glyphs
[i
], is_sideways
);
1032 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace5
*iface
,
1033 float em_size
, float ppdip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
1034 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
1036 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1037 DWRITE_MEASURING_MODE measuring_mode
;
1040 TRACE("%p, %.8e, %.8e, %p, %d, %d, %u, %p, %p.\n", iface
, em_size
, ppdip
, transform
,
1041 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
1043 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
1044 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1045 return E_INVALIDARG
;
1048 if (em_size
== 0.0f
) {
1049 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
1053 measuring_mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
1054 for (i
= 0; i
< glyph_count
; ++i
)
1056 advances
[i
] = fontface_get_design_advance(fontface
, measuring_mode
, em_size
, ppdip
, transform
,
1057 glyphs
[i
], is_sideways
);
1063 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace5
*iface
, UINT32 count
,
1064 const UINT16
*indices
, INT32
*adjustments
)
1066 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1069 TRACE("%p, %u, %p, %p.\n", iface
, count
, indices
, adjustments
);
1071 if (!(indices
|| adjustments
) || !count
)
1072 return E_INVALIDARG
;
1074 if (!indices
|| count
== 1) {
1075 memset(adjustments
, 0, count
*sizeof(INT32
));
1076 return E_INVALIDARG
;
1079 if (!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
))
1081 memset(adjustments
, 0, count
*sizeof(INT32
));
1085 for (i
= 0; i
< count
-1; i
++)
1086 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1087 adjustments
[count
-1] = 0;
1092 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace5
*iface
)
1094 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1096 TRACE("%p.\n", iface
);
1098 return !!(fontface
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1101 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
,
1102 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1103 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1105 DWRITE_GRID_FIT_MODE gridfitmode
;
1106 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
,
1107 is_sideways
, threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1110 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace5
*iface
, UINT32 glyph_count
,
1111 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
1113 FIXME("%p, %u, %p, %p: stub\n", iface
, glyph_count
, nominal_indices
, vertical_indices
);
1118 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace5
*iface
)
1120 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1122 TRACE("%p.\n", iface
);
1124 return !!(fontface
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1127 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace5
*iface
)
1129 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1131 TRACE("%p.\n", iface
);
1133 return !!(fontface
->flags
& FONT_IS_COLORED
);
1136 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace5
*iface
)
1138 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1140 TRACE("%p.\n", iface
);
1142 return opentype_get_cpal_palettecount(get_fontface_cpal(fontface
));
1145 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace5
*iface
)
1147 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1149 TRACE("%p.\n", iface
);
1151 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(fontface
));
1154 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace5
*iface
, UINT32 palette_index
,
1155 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1157 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1159 TRACE("%p, %u, %u, %u, %p.\n", iface
, palette_index
, first_entry_index
, entry_count
, entries
);
1161 return opentype_get_cpal_entries(get_fontface_cpal(fontface
), palette_index
, first_entry_index
, entry_count
, entries
);
1164 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
,
1165 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1166 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1167 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1169 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1173 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1174 measuringmode
, params
, renderingmode
, gridfitmode
);
1177 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1180 FIXME("sideways mode not supported\n");
1182 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1184 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1185 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1187 IDWriteRenderingParams2
*params2
;
1190 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1192 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1193 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1194 IDWriteRenderingParams2_Release(params2
);
1197 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1200 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1202 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1204 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1205 if (emSize
>= emthreshold
)
1206 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1208 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, flags
);
1211 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1212 if (emSize
>= emthreshold
)
1213 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1214 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1215 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1217 *gridfitmode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1218 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1224 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace5
*iface
, IDWriteFontFaceReference
**ref
)
1226 FIXME("%p, %p: stub\n", iface
, ref
);
1231 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace5
*iface
, DWRITE_PANOSE
*panose
)
1233 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1235 TRACE("%p, %p.\n", iface
, panose
);
1237 *panose
= fontface
->panose
;
1240 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace5
*iface
)
1242 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1244 TRACE("%p.\n", iface
);
1246 return fontface
->weight
;
1249 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace5
*iface
)
1251 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1253 TRACE("%p.\n", iface
);
1255 return fontface
->stretch
;
1258 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace5
*iface
)
1260 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1262 TRACE("%p.\n", iface
);
1264 return fontface
->style
;
1267 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1269 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1271 TRACE("%p, %p.\n", iface
, names
);
1273 return clone_localizedstrings(fontface
->family_names
, names
);
1276 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace5
*iface
, IDWriteLocalizedStrings
**names
)
1278 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1280 TRACE("%p, %p.\n", iface
, names
);
1282 return clone_localizedstrings(fontface
->names
, names
);
1285 static HRESULT
get_font_info_strings(const struct file_stream_desc
*stream_desc
, IDWriteFontFile
*file
,
1286 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings_cache
,
1287 IDWriteLocalizedStrings
**ret
, BOOL
*exists
)
1294 if (stringid
> DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG
1295 || stringid
<= DWRITE_INFORMATIONAL_STRING_NONE
)
1300 if (!strings_cache
[stringid
])
1302 struct file_stream_desc desc
= *stream_desc
;
1305 hr
= get_filestream_from_file(file
, &desc
.stream
);
1307 opentype_get_font_info_strings(&desc
, stringid
, &strings_cache
[stringid
]);
1309 if (!stream_desc
->stream
&& desc
.stream
)
1310 IDWriteFontFileStream_Release(desc
.stream
);
1313 if (SUCCEEDED(hr
) && strings_cache
[stringid
])
1315 hr
= clone_localizedstrings(strings_cache
[stringid
], ret
);
1323 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace5
*iface
,
1324 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1326 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1327 struct file_stream_desc stream_desc
;
1329 TRACE("%p, %u, %p, %p.\n", iface
, stringid
, strings
, exists
);
1331 stream_desc
.stream
= fontface
->stream
;
1332 stream_desc
.face_index
= fontface
->index
;
1333 stream_desc
.face_type
= fontface
->type
;
1334 return get_font_info_strings(&stream_desc
, NULL
, stringid
, fontface
->info_strings
, strings
, exists
);
1337 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace5
*iface
, UINT32 ch
)
1339 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1342 TRACE("%p, %#x.\n", iface
, ch
);
1345 if (FAILED(fontface_get_glyphs(fontface
, &ch
, 1, &index
)))
1351 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace5
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1352 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1353 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1355 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1359 TRACE("%p, %.8e, %.8e, %.8e, %p, %d, %d, %d, %p, %p, %p.\n", iface
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1360 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1363 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1366 FIXME("sideways mode not supported\n");
1368 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1370 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1371 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1373 IDWriteRenderingParams3
*params3
;
1376 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1378 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1379 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1380 IDWriteRenderingParams3_Release(params3
);
1383 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1386 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1388 flags
= opentype_get_gasp_flags(get_fontface_gasp(fontface
), emSize
);
1390 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1391 if (emSize
>= emthreshold
)
1392 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1394 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, flags
);
1397 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1398 if (emSize
>= emthreshold
)
1399 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1400 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1401 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1403 *gridfit_mode
= flags
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
) ?
1404 DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1410 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace5
*iface
, UINT32 ch
)
1412 FIXME("%p, %#x: stub\n", iface
, ch
);
1417 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace5
*iface
, UINT16 glyph
)
1419 FIXME("%p, %u: stub\n", iface
, glyph
);
1424 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace5
*iface
, WCHAR
const *text
,
1425 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1427 FIXME("%p, %s:%u, %d %p: stub\n", iface
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1432 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace5
*iface
, UINT16
const *glyphs
,
1433 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1435 FIXME("%p, %p, %u, %d, %p: stub\n", iface
, glyphs
, count
, enqueue_if_not
, are_local
);
1440 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace5
*iface
, UINT16 glyph
,
1441 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1443 FIXME("%p, %u, %u, %u, %p: stub\n", iface
, glyph
, ppem_first
, ppem_last
, formats
);
1448 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace5
*iface
)
1450 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1452 TRACE("%p.\n", iface
);
1454 return fontface
->glyph_image_formats
;
1457 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace5
*iface
, UINT16 glyph
,
1458 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1460 FIXME("%p, %u, %u, %d, %p, %p: stub\n", iface
, glyph
, ppem
, format
, data
, context
);
1465 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace5
*iface
, void *context
)
1467 FIXME("%p, %p: stub\n", iface
, context
);
1470 static UINT32 WINAPI
dwritefontface5_GetFontAxisValueCount(IDWriteFontFace5
*iface
)
1472 FIXME("%p: stub\n", iface
);
1477 static HRESULT WINAPI
dwritefontface5_GetFontAxisValues(IDWriteFontFace5
*iface
, DWRITE_FONT_AXIS_VALUE
*axis_values
,
1480 FIXME("%p, %p, %u: stub\n", iface
, axis_values
, value_count
);
1485 static BOOL WINAPI
dwritefontface5_HasVariations(IDWriteFontFace5
*iface
)
1487 FIXME("%p: stub\n", iface
);
1492 static HRESULT WINAPI
dwritefontface5_GetFontResource(IDWriteFontFace5
*iface
, IDWriteFontResource
**resource
)
1494 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace5(iface
);
1496 TRACE("%p, %p.\n", iface
, resource
);
1498 return IDWriteFactory7_CreateFontResource(fontface
->factory
, fontface
->files
[0], fontface
->index
, resource
);
1501 static const IDWriteFontFace5Vtbl dwritefontfacevtbl
=
1503 dwritefontface_QueryInterface
,
1504 dwritefontface_AddRef
,
1505 dwritefontface_Release
,
1506 dwritefontface_GetType
,
1507 dwritefontface_GetFiles
,
1508 dwritefontface_GetIndex
,
1509 dwritefontface_GetSimulations
,
1510 dwritefontface_IsSymbolFont
,
1511 dwritefontface_GetMetrics
,
1512 dwritefontface_GetGlyphCount
,
1513 dwritefontface_GetDesignGlyphMetrics
,
1514 dwritefontface_GetGlyphIndices
,
1515 dwritefontface_TryGetFontTable
,
1516 dwritefontface_ReleaseFontTable
,
1517 dwritefontface_GetGlyphRunOutline
,
1518 dwritefontface_GetRecommendedRenderingMode
,
1519 dwritefontface_GetGdiCompatibleMetrics
,
1520 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1521 dwritefontface1_GetMetrics
,
1522 dwritefontface1_GetGdiCompatibleMetrics
,
1523 dwritefontface1_GetCaretMetrics
,
1524 dwritefontface1_GetUnicodeRanges
,
1525 dwritefontface1_IsMonospacedFont
,
1526 dwritefontface1_GetDesignGlyphAdvances
,
1527 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1528 dwritefontface1_GetKerningPairAdjustments
,
1529 dwritefontface1_HasKerningPairs
,
1530 dwritefontface1_GetRecommendedRenderingMode
,
1531 dwritefontface1_GetVerticalGlyphVariants
,
1532 dwritefontface1_HasVerticalGlyphVariants
,
1533 dwritefontface2_IsColorFont
,
1534 dwritefontface2_GetColorPaletteCount
,
1535 dwritefontface2_GetPaletteEntryCount
,
1536 dwritefontface2_GetPaletteEntries
,
1537 dwritefontface2_GetRecommendedRenderingMode
,
1538 dwritefontface3_GetFontFaceReference
,
1539 dwritefontface3_GetPanose
,
1540 dwritefontface3_GetWeight
,
1541 dwritefontface3_GetStretch
,
1542 dwritefontface3_GetStyle
,
1543 dwritefontface3_GetFamilyNames
,
1544 dwritefontface3_GetFaceNames
,
1545 dwritefontface3_GetInformationalStrings
,
1546 dwritefontface3_HasCharacter
,
1547 dwritefontface3_GetRecommendedRenderingMode
,
1548 dwritefontface3_IsCharacterLocal
,
1549 dwritefontface3_IsGlyphLocal
,
1550 dwritefontface3_AreCharactersLocal
,
1551 dwritefontface3_AreGlyphsLocal
,
1552 dwritefontface4_GetGlyphImageFormats_
,
1553 dwritefontface4_GetGlyphImageFormats
,
1554 dwritefontface4_GetGlyphImageData
,
1555 dwritefontface4_ReleaseGlyphImageData
,
1556 dwritefontface5_GetFontAxisValueCount
,
1557 dwritefontface5_GetFontAxisValues
,
1558 dwritefontface5_HasVariations
,
1559 dwritefontface5_GetFontResource
,
1562 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace5
**fontface
)
1564 struct dwrite_font_data
*data
= font
->data
;
1565 struct fontface_desc desc
;
1566 struct list
*cached_list
;
1571 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1572 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1576 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1579 desc
.factory
= font
->family
->collection
->factory
;
1580 desc
.face_type
= data
->face_type
;
1581 desc
.files
= &data
->file
;
1582 desc
.files_number
= 1;
1583 desc
.index
= data
->face_index
;
1584 desc
.simulations
= data
->simulations
;
1585 desc
.font_data
= data
;
1586 hr
= create_fontface(&desc
, cached_list
, fontface
);
1588 IDWriteFontFileStream_Release(desc
.stream
);
1592 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1594 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1596 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1598 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1599 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1600 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1601 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1602 IsEqualIID(riid
, &IID_IUnknown
))
1605 IDWriteFont3_AddRef(iface
);
1609 WARN("%s not implemented.\n", debugstr_guid(riid
));
1612 return E_NOINTERFACE
;
1615 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1617 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1618 ULONG ref
= InterlockedIncrement(&This
->ref
);
1619 TRACE("(%p)->(%d)\n", This
, ref
);
1623 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1625 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1626 ULONG ref
= InterlockedDecrement(&This
->ref
);
1628 TRACE("(%p)->(%d)\n", This
, ref
);
1631 IDWriteFontFamily2_Release(&This
->family
->IDWriteFontFamily2_iface
);
1632 release_font_data(This
->data
);
1639 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1641 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1642 TRACE("(%p)->(%p)\n", This
, family
);
1644 *family
= (IDWriteFontFamily
*)This
->family
;
1645 IDWriteFontFamily_AddRef(*family
);
1649 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1651 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1652 TRACE("(%p)\n", This
);
1653 return This
->data
->weight
;
1656 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1658 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1659 TRACE("(%p)\n", This
);
1660 return This
->data
->stretch
;
1663 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1665 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1666 TRACE("(%p)\n", This
);
1670 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1672 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1674 TRACE("%p.\n", iface
);
1676 return !!(font
->data
->flags
& FONT_IS_SYMBOL
);
1679 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1681 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1683 TRACE("%p, %p.\n", iface
, names
);
1685 return clone_localizedstrings(font
->data
->names
, names
);
1688 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1689 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1691 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1692 struct dwrite_font_data
*data
= font
->data
;
1693 struct file_stream_desc stream_desc
;
1695 TRACE("%p, %d, %p, %p.\n", iface
, stringid
, strings
, exists
);
1697 /* Stream will be created if necessary. */
1698 stream_desc
.stream
= NULL
;
1699 stream_desc
.face_index
= data
->face_index
;
1700 stream_desc
.face_type
= data
->face_type
;
1701 return get_font_info_strings(&stream_desc
, data
->file
, stringid
, data
->info_strings
, strings
, exists
);
1704 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1706 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1707 TRACE("(%p)\n", This
);
1708 return This
->data
->simulations
;
1711 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1713 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1715 TRACE("(%p)->(%p)\n", This
, metrics
);
1716 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1719 static HRESULT
font_has_character(struct dwrite_font
*font
, UINT32 ch
, BOOL
*exists
)
1721 IDWriteFontFace5
*fontface
;
1727 hr
= get_fontface_from_font(font
, &fontface
);
1732 hr
= IDWriteFontFace5_GetGlyphIndices(fontface
, &ch
, 1, &index
);
1733 IDWriteFontFace5_Release(fontface
);
1737 *exists
= index
!= 0;
1741 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
1743 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1745 TRACE("(%p)->(%#x %p)\n", This
, ch
, exists
);
1747 return font_has_character(This
, ch
, exists
);
1750 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1752 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1754 TRACE("%p, %p.\n", iface
, fontface
);
1756 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
1759 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1761 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1762 TRACE("(%p)->(%p)\n", This
, metrics
);
1763 *metrics
= This
->data
->metrics
;
1766 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1768 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1769 TRACE("(%p)->(%p)\n", This
, panose
);
1770 *panose
= This
->data
->panose
;
1773 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1775 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1776 IDWriteFontFace5
*fontface
;
1779 TRACE("%p, %u, %p, %p.\n", iface
, max_count
, ranges
, count
);
1781 hr
= get_fontface_from_font(font
, &fontface
);
1785 hr
= IDWriteFontFace5_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1786 IDWriteFontFace5_Release(fontface
);
1790 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1792 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1794 TRACE("%p.\n", iface
);
1796 return !!(font
->data
->flags
& FONT_IS_MONOSPACED
);
1799 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1801 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1803 TRACE("%p.\n", iface
);
1805 return !!(font
->data
->flags
& FONT_IS_COLORED
);
1808 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1810 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1812 TRACE("%p, %p.\n", iface
, fontface
);
1814 return get_fontface_from_font(font
, (IDWriteFontFace5
**)fontface
);
1817 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1819 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1820 FIXME("(%p)->(%p): stub\n", This
, font
);
1824 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1826 struct dwrite_font
*font
= impl_from_IDWriteFont3(iface
);
1828 TRACE("%p, %p.\n", iface
, reference
);
1830 return IDWriteFactory5_CreateFontFaceReference_((IDWriteFactory5
*)font
->family
->collection
->factory
,
1831 font
->data
->file
, font
->data
->face_index
, font
->data
->simulations
, reference
);
1834 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1836 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1839 TRACE("(%p)->(%#x)\n", This
, ch
);
1841 return font_has_character(This
, ch
, &ret
) == S_OK
&& ret
;
1844 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1846 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1847 FIXME("(%p): stub\n", This
);
1848 return DWRITE_LOCALITY_LOCAL
;
1851 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1852 dwritefont_QueryInterface
,
1855 dwritefont_GetFontFamily
,
1856 dwritefont_GetWeight
,
1857 dwritefont_GetStretch
,
1858 dwritefont_GetStyle
,
1859 dwritefont_IsSymbolFont
,
1860 dwritefont_GetFaceNames
,
1861 dwritefont_GetInformationalStrings
,
1862 dwritefont_GetSimulations
,
1863 dwritefont_GetMetrics
,
1864 dwritefont_HasCharacter
,
1865 dwritefont_CreateFontFace
,
1866 dwritefont1_GetMetrics
,
1867 dwritefont1_GetPanose
,
1868 dwritefont1_GetUnicodeRanges
,
1869 dwritefont1_IsMonospacedFont
,
1870 dwritefont2_IsColorFont
,
1871 dwritefont3_CreateFontFace
,
1873 dwritefont3_GetFontFaceReference
,
1874 dwritefont3_HasCharacter
,
1875 dwritefont3_GetLocality
1878 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
1882 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
1883 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
1886 struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
1890 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
1891 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace5_iface
);
1894 static struct dwrite_fontfacereference
*unsafe_impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
1898 if (iface
->lpVtbl
!= (IDWriteFontFaceReferenceVtbl
*)&fontfacereferencevtbl
)
1900 return CONTAINING_RECORD((IDWriteFontFaceReference1
*)iface
, struct dwrite_fontfacereference
,
1901 IDWriteFontFaceReference1_iface
);
1904 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
1906 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1907 *lf
= font
->data
->lf
;
1910 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
1912 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1916 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
1918 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1919 *fontsig
= font
->data
->fontsig
;
1923 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
1925 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1926 *fontsig
= fontface
->fontsig
;
1930 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
1932 struct dwrite_font
*This
;
1936 This
= heap_alloc(sizeof(*This
));
1938 return E_OUTOFMEMORY
;
1940 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1942 This
->family
= family
;
1943 IDWriteFontFamily2_AddRef(&family
->IDWriteFontFamily2_iface
);
1944 This
->data
= family
->data
->fonts
[index
];
1945 This
->style
= This
->data
->style
;
1946 addref_font_data(This
->data
);
1948 *font
= &This
->IDWriteFont3_iface
;
1953 /* IDWriteFontList2 */
1954 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
1956 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1958 if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
1959 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1960 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1961 IsEqualIID(riid
, &IID_IUnknown
))
1964 IDWriteFontList2_AddRef(iface
);
1968 WARN("%s not implemented.\n", debugstr_guid(riid
));
1971 return E_NOINTERFACE
;
1974 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList2
*iface
)
1976 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
1977 ULONG refcount
= InterlockedIncrement(&fontlist
->refcount
);
1979 TRACE("%p, refcount %u.\n", iface
, refcount
);
1984 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList2
*iface
)
1986 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
1987 ULONG refcount
= InterlockedDecrement(&fontlist
->refcount
);
1989 TRACE("%p, refcount %u.\n", iface
, refcount
);
1995 for (i
= 0; i
< fontlist
->font_count
; i
++)
1996 release_font_data(fontlist
->fonts
[i
]);
1997 IDWriteFontFamily2_Release(&fontlist
->family
->IDWriteFontFamily2_iface
);
1998 heap_free(fontlist
->fonts
);
1999 heap_free(fontlist
);
2005 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList2
*iface
, IDWriteFontCollection
**collection
)
2007 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2008 return IDWriteFontFamily2_GetFontCollection(&fontlist
->family
->IDWriteFontFamily2_iface
, collection
);
2011 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList2
*iface
)
2013 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2015 TRACE("%p.\n", iface
);
2017 return fontlist
->font_count
;
2020 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2022 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2024 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2028 if (fontlist
->font_count
== 0)
2031 if (index
>= fontlist
->font_count
)
2032 return E_INVALIDARG
;
2034 return create_font(fontlist
->family
, index
, (IDWriteFont3
**)font
);
2037 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2039 FIXME("%p, %u.\n", iface
, index
);
2041 return DWRITE_LOCALITY_LOCAL
;
2044 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2046 struct dwrite_fontlist
*fontlist
= impl_from_IDWriteFontList2(iface
);
2048 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2052 if (fontlist
->font_count
== 0)
2055 if (index
>= fontlist
->font_count
)
2058 return create_font(fontlist
->family
, index
, font
);
2061 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2062 IDWriteFontFaceReference
**reference
)
2067 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2071 hr
= IDWriteFontList2_GetFont(iface
, index
, &font
);
2075 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2076 IDWriteFont3_Release(font
);
2081 static HRESULT WINAPI
dwritefontlist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2083 FIXME("%p, %p.\n", iface
, fontset
);
2088 static const IDWriteFontList2Vtbl dwritefontlistvtbl
=
2090 dwritefontlist_QueryInterface
,
2091 dwritefontlist_AddRef
,
2092 dwritefontlist_Release
,
2093 dwritefontlist_GetFontCollection
,
2094 dwritefontlist_GetFontCount
,
2095 dwritefontlist_GetFont
,
2096 dwritefontlist1_GetFontLocality
,
2097 dwritefontlist1_GetFont
,
2098 dwritefontlist1_GetFontFaceReference
,
2099 dwritefontlist2_GetFontSet
,
2102 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily2
*iface
, REFIID riid
, void **obj
)
2104 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2106 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2108 if (IsEqualIID(riid
, &IID_IDWriteFontFamily2
) ||
2109 IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
2110 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
2111 IsEqualIID(riid
, &IID_IUnknown
))
2115 else if (IsEqualIID(riid
, &IID_IDWriteFontList2
) ||
2116 IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
2117 IsEqualIID(riid
, &IID_IDWriteFontList
))
2119 *obj
= &family
->IDWriteFontList2_iface
;
2123 WARN("%s not implemented.\n", debugstr_guid(riid
));
2125 return E_NOINTERFACE
;
2128 IUnknown_AddRef((IUnknown
*)*obj
);
2132 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily2
*iface
)
2134 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2135 ULONG refcount
= InterlockedIncrement(&family
->refcount
);
2137 TRACE("%p, %u.\n", iface
, refcount
);
2142 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily2
*iface
)
2144 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2145 ULONG refcount
= InterlockedDecrement(&family
->refcount
);
2147 TRACE("%p, %u.\n", iface
, refcount
);
2151 IDWriteFontCollection3_Release(&family
->collection
->IDWriteFontCollection3_iface
);
2152 release_fontfamily_data(family
->data
);
2159 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily2
*iface
, IDWriteFontCollection
**collection
)
2161 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2163 TRACE("%p, %p.\n", iface
, collection
);
2165 *collection
= (IDWriteFontCollection
*)family
->collection
;
2166 IDWriteFontCollection_AddRef(*collection
);
2170 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily2
*iface
)
2172 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2174 TRACE("%p.\n", iface
);
2176 return family
->data
->count
;
2179 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont
**font
)
2181 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2183 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2187 if (!family
->data
->count
)
2190 if (index
>= family
->data
->count
)
2191 return E_INVALIDARG
;
2193 return create_font(family
, index
, (IDWriteFont3
**)font
);
2196 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily2
*iface
, IDWriteLocalizedStrings
**names
)
2198 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2200 TRACE("%p, %p.\n", iface
, names
);
2202 return clone_localizedstrings(family
->data
->familyname
, names
);
2205 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2206 const struct dwrite_font_propvec
*req
)
2208 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2209 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2210 FLOAT cur_req_prod
, next_req_prod
;
2212 if (next_to_req
< cur_to_req
)
2215 if (next_to_req
> cur_to_req
)
2218 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2219 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2221 if (next_req_prod
> cur_req_prod
)
2224 if (next_req_prod
< cur_req_prod
)
2227 if (next
->stretch
> cur
->stretch
)
2229 if (next
->stretch
< cur
->stretch
)
2232 if (next
->style
> cur
->style
)
2234 if (next
->style
< cur
->style
)
2237 if (next
->weight
> cur
->weight
)
2239 if (next
->weight
< cur
->weight
)
2242 /* full match, no reason to prefer new variant */
2246 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2247 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2249 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2250 struct dwrite_font_propvec req
;
2253 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, font
);
2255 if (!family
->data
->count
)
2258 return DWRITE_E_NOFONT
;
2261 init_font_prop_vec(weight
, stretch
, style
, &req
);
2264 for (i
= 1; i
< family
->data
->count
; ++i
)
2266 if (is_better_font_match(&family
->data
->fonts
[i
]->propvec
, &family
->data
->fonts
[match
]->propvec
, &req
))
2270 return create_font(family
, match
, (IDWriteFont3
**)font
);
2273 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2275 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2277 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2280 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2282 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2285 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2287 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2292 for (j
= 0; j
< b
; j
++) {
2293 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2294 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2295 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2296 fonts
->fonts
[j
+1] = s
;
2307 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily2
*iface
, DWRITE_FONT_WEIGHT weight
,
2308 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2310 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2311 matching_filter_func func
= NULL
;
2312 struct dwrite_font_propvec req
;
2313 struct dwrite_fontlist
*fonts
;
2316 TRACE("%p, %d, %d, %d, %p.\n", iface
, weight
, stretch
, style
, ret
);
2320 fonts
= heap_alloc(sizeof(*fonts
));
2322 return E_OUTOFMEMORY
;
2324 /* Allocate as many as family has, not all of them will be necessary used. */
2325 fonts
->fonts
= heap_calloc(family
->data
->count
, sizeof(*fonts
->fonts
));
2326 if (!fonts
->fonts
) {
2328 return E_OUTOFMEMORY
;
2331 fonts
->IDWriteFontList2_iface
.lpVtbl
= &dwritefontlistvtbl
;
2332 fonts
->refcount
= 1;
2333 fonts
->family
= family
;
2334 IDWriteFontFamily2_AddRef(&fonts
->family
->IDWriteFontFamily2_iface
);
2335 fonts
->font_count
= 0;
2337 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2338 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2339 if (family
->data
->has_normal_face
|| family
->data
->has_italic_face
)
2340 func
= is_font_acceptable_for_normal
;
2342 else /* requested oblique or italic */ {
2343 if (family
->data
->has_oblique_face
|| family
->data
->has_italic_face
)
2344 func
= is_font_acceptable_for_oblique_italic
;
2347 for (i
= 0; i
< family
->data
->count
; ++i
)
2349 if (!func
|| func(family
->data
->fonts
[i
]))
2351 fonts
->fonts
[fonts
->font_count
] = family
->data
->fonts
[i
];
2352 addref_font_data(family
->data
->fonts
[i
]);
2353 fonts
->font_count
++;
2357 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2358 init_font_prop_vec(weight
, stretch
, style
, &req
);
2359 matchingfonts_sort(fonts
, &req
);
2361 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList2_iface
;
2365 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily2
*iface
, UINT32 index
)
2367 FIXME("%p, %u.\n", iface
, index
);
2369 return DWRITE_LOCALITY_LOCAL
;
2372 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2374 struct dwrite_fontfamily
*family
= impl_from_IDWriteFontFamily2(iface
);
2376 TRACE("%p, %u, %p.\n", iface
, index
, font
);
2380 if (!family
->data
->count
)
2383 if (index
>= family
->data
->count
)
2386 return create_font(family
, index
, font
);
2389 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily2
*iface
, UINT32 index
,
2390 IDWriteFontFaceReference
**reference
)
2395 TRACE("%p, %u, %p.\n", iface
, index
, reference
);
2399 hr
= IDWriteFontFamily2_GetFont(iface
, index
, &font
);
2403 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2404 IDWriteFont3_Release(font
);
2409 static HRESULT WINAPI
dwritefontfamily2_GetMatchingFonts(IDWriteFontFamily2
*iface
,
2410 DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
, IDWriteFontList2
**fontlist
)
2412 FIXME("%p, %p, %u, %p.\n", iface
, axis_values
, num_values
, fontlist
);
2417 static HRESULT WINAPI
dwritefontfamily2_GetFontSet(IDWriteFontFamily2
*iface
, IDWriteFontSet1
**fontset
)
2419 FIXME("%p, %p.\n", iface
, fontset
);
2424 static const IDWriteFontFamily2Vtbl fontfamilyvtbl
=
2426 dwritefontfamily_QueryInterface
,
2427 dwritefontfamily_AddRef
,
2428 dwritefontfamily_Release
,
2429 dwritefontfamily_GetFontCollection
,
2430 dwritefontfamily_GetFontCount
,
2431 dwritefontfamily_GetFont
,
2432 dwritefontfamily_GetFamilyNames
,
2433 dwritefontfamily_GetFirstMatchingFont
,
2434 dwritefontfamily_GetMatchingFonts
,
2435 dwritefontfamily1_GetFontLocality
,
2436 dwritefontfamily1_GetFont
,
2437 dwritefontfamily1_GetFontFaceReference
,
2438 dwritefontfamily2_GetMatchingFonts
,
2439 dwritefontfamily2_GetFontSet
,
2442 static HRESULT WINAPI
dwritefontfamilylist_QueryInterface(IDWriteFontList2
*iface
, REFIID riid
, void **obj
)
2444 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2445 return dwritefontfamily_QueryInterface(&family
->IDWriteFontFamily2_iface
, riid
, obj
);
2448 static ULONG WINAPI
dwritefontfamilylist_AddRef(IDWriteFontList2
*iface
)
2450 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2451 return dwritefontfamily_AddRef(&family
->IDWriteFontFamily2_iface
);
2454 static ULONG WINAPI
dwritefontfamilylist_Release(IDWriteFontList2
*iface
)
2456 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2457 return dwritefontfamily_Release(&family
->IDWriteFontFamily2_iface
);
2460 static HRESULT WINAPI
dwritefontfamilylist_GetFontCollection(IDWriteFontList2
*iface
,
2461 IDWriteFontCollection
**collection
)
2463 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2464 return dwritefontfamily_GetFontCollection(&family
->IDWriteFontFamily2_iface
, collection
);
2467 static UINT32 WINAPI
dwritefontfamilylist_GetFontCount(IDWriteFontList2
*iface
)
2469 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2470 return dwritefontfamily_GetFontCount(&family
->IDWriteFontFamily2_iface
);
2473 static HRESULT WINAPI
dwritefontfamilylist_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont
**font
)
2475 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2476 return dwritefontfamily_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2479 static DWRITE_LOCALITY WINAPI
dwritefontfamilylist1_GetFontLocality(IDWriteFontList2
*iface
, UINT32 index
)
2481 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2482 return dwritefontfamily1_GetFontLocality(&family
->IDWriteFontFamily2_iface
, index
);
2485 static HRESULT WINAPI
dwritefontfamilylist1_GetFont(IDWriteFontList2
*iface
, UINT32 index
, IDWriteFont3
**font
)
2487 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2488 return dwritefontfamily1_GetFont(&family
->IDWriteFontFamily2_iface
, index
, font
);
2491 static HRESULT WINAPI
dwritefontfamilylist1_GetFontFaceReference(IDWriteFontList2
*iface
, UINT32 index
,
2492 IDWriteFontFaceReference
**reference
)
2494 struct dwrite_fontfamily
*family
= impl_family_from_IDWriteFontList2(iface
);
2495 return dwritefontfamily1_GetFontFaceReference(&family
->IDWriteFontFamily2_iface
, index
, reference
);
2498 static HRESULT WINAPI
dwritefontfamilylist2_GetFontSet(IDWriteFontList2
*iface
, IDWriteFontSet1
**fontset
)
2500 FIXME("%p, %p.\n", iface
, fontset
);
2505 static const IDWriteFontList2Vtbl fontfamilylistvtbl
=
2507 dwritefontfamilylist_QueryInterface
,
2508 dwritefontfamilylist_AddRef
,
2509 dwritefontfamilylist_Release
,
2510 dwritefontfamilylist_GetFontCollection
,
2511 dwritefontfamilylist_GetFontCount
,
2512 dwritefontfamilylist_GetFont
,
2513 dwritefontfamilylist1_GetFontLocality
,
2514 dwritefontfamilylist1_GetFont
,
2515 dwritefontfamilylist1_GetFontFaceReference
,
2516 dwritefontfamilylist2_GetFontSet
,
2519 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
,
2520 struct dwrite_fontfamily
**family
)
2522 struct dwrite_fontfamily
*object
;
2526 object
= heap_alloc(sizeof(*object
));
2528 return E_OUTOFMEMORY
;
2530 object
->IDWriteFontFamily2_iface
.lpVtbl
= &fontfamilyvtbl
;
2531 object
->IDWriteFontList2_iface
.lpVtbl
= &fontfamilylistvtbl
;
2532 object
->refcount
= 1;
2533 object
->collection
= collection
;
2534 IDWriteFontCollection3_AddRef(&collection
->IDWriteFontCollection3_iface
);
2535 object
->data
= collection
->family_data
[index
];
2536 InterlockedIncrement(&object
->data
->refcount
);
2543 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2546 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, &obj
) == S_OK
;
2549 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2551 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2553 TRACE("%p, %s, %p.\n", collection
, debugstr_guid(riid
), obj
);
2555 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2556 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2557 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2558 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2559 IsEqualIID(riid
, &IID_IUnknown
))
2562 IDWriteFontCollection3_AddRef(iface
);
2568 if (IsEqualIID(riid
, &IID_issystemcollection
))
2571 WARN("%s not implemented.\n", debugstr_guid(riid
));
2573 return E_NOINTERFACE
;
2576 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection3
*iface
, REFIID riid
, void **obj
)
2578 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
2580 if (IsEqualIID(riid
, &IID_IDWriteFontCollection3
) ||
2581 IsEqualIID(riid
, &IID_IDWriteFontCollection2
) ||
2582 IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2583 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2584 IsEqualIID(riid
, &IID_IUnknown
))
2587 IDWriteFontCollection3_AddRef(iface
);
2591 WARN("%s not implemented.\n", debugstr_guid(riid
));
2595 return E_NOINTERFACE
;
2598 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection3
*iface
)
2600 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2601 ULONG refcount
= InterlockedIncrement(&collection
->refcount
);
2603 TRACE("%p, refcount %d.\n", collection
, refcount
);
2608 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection3
*iface
)
2610 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2611 ULONG refcount
= InterlockedDecrement(&collection
->refcount
);
2614 TRACE("%p, refcount %d.\n", iface
, refcount
);
2618 factory_detach_fontcollection(collection
->factory
, iface
);
2619 for (i
= 0; i
< collection
->count
; ++i
)
2620 release_fontfamily_data(collection
->family_data
[i
]);
2621 heap_free(collection
->family_data
);
2622 heap_free(collection
);
2628 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection3
*iface
)
2630 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2632 TRACE("%p.\n", iface
);
2634 return collection
->count
;
2637 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2638 IDWriteFontFamily
**ret
)
2640 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2641 struct dwrite_fontfamily
*family
;
2644 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2648 if (index
>= collection
->count
)
2651 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2652 *ret
= (IDWriteFontFamily
*)&family
->IDWriteFontFamily2_iface
;
2657 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2661 for (i
= 0; i
< collection
->count
; ++i
)
2663 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2664 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2667 for (j
= 0; j
< count
; j
++) {
2669 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, ARRAY_SIZE(buffer
));
2670 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2678 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection3
*iface
, const WCHAR
*name
,
2679 UINT32
*index
, BOOL
*exists
)
2681 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2683 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_w(name
), index
, exists
);
2685 *index
= collection_find_family(collection
, name
);
2686 *exists
= *index
!= ~0u;
2690 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2692 UINT32 left_key_size
, right_key_size
;
2693 const void *left_key
, *right_key
;
2699 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2703 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2707 if (left_key_size
!= right_key_size
)
2710 return !memcmp(left_key
, right_key
, left_key_size
);
2713 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection3
*iface
, IDWriteFontFace
*face
,
2716 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2717 struct dwrite_fontfamily
*family
;
2718 BOOL found_font
= FALSE
;
2719 IDWriteFontFile
*file
;
2720 UINT32 face_index
, count
;
2724 TRACE("%p, %p, %p.\n", iface
, face
, font
);
2729 return E_INVALIDARG
;
2732 hr
= IDWriteFontFace_GetFiles(face
, &count
, &file
);
2735 face_index
= IDWriteFontFace_GetIndex(face
);
2738 for (i
= 0; i
< collection
->count
; ++i
)
2740 struct dwrite_fontfamily_data
*family_data
= collection
->family_data
[i
];
2742 for (j
= 0; j
< family_data
->count
; ++j
)
2744 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2746 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2755 IDWriteFontFile_Release(file
);
2758 return DWRITE_E_NOFONT
;
2760 hr
= create_fontfamily(collection
, i
, &family
);
2764 hr
= create_font(family
, j
, (IDWriteFont3
**)font
);
2765 IDWriteFontFamily2_Release(&family
->IDWriteFontFamily2_iface
);
2769 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet
**fontset
)
2771 FIXME("%p, %p.\n", iface
, fontset
);
2776 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection3
*iface
, UINT32 index
,
2777 IDWriteFontFamily1
**ret
)
2779 struct dwrite_fontcollection
*collection
= impl_from_IDWriteFontCollection3(iface
);
2780 struct dwrite_fontfamily
*family
;
2783 TRACE("%p, %u, %p.\n", iface
, index
, ret
);
2787 if (index
>= collection
->count
)
2790 if (SUCCEEDED(hr
= create_fontfamily(collection
, index
, &family
)))
2791 *ret
= (IDWriteFontFamily1
*)&family
->IDWriteFontFamily2_iface
;
2796 static HRESULT WINAPI
dwritefontcollection2_GetFontFamily(IDWriteFontCollection3
*iface
,
2797 UINT32 index
, IDWriteFontFamily2
**family
)
2799 FIXME("%p, %u, %p.\n", iface
, index
, family
);
2804 static HRESULT WINAPI
dwritefontcollection2_GetMatchingFonts(IDWriteFontCollection3
*iface
,
2805 const WCHAR
*familyname
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
2806 IDWriteFontList2
**fontlist
)
2808 FIXME("%p, %s, %p, %u, %p.\n", iface
, debugstr_w(familyname
), axis_values
, num_values
, fontlist
);
2813 static DWRITE_FONT_FAMILY_MODEL WINAPI
dwritefontcollection2_GetFontFamilyModel(IDWriteFontCollection3
*iface
)
2815 FIXME("%p.\n", iface
);
2817 return DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE
;
2820 static HRESULT WINAPI
dwritefontcollection2_GetFontSet(IDWriteFontCollection3
*iface
, IDWriteFontSet1
**fontset
)
2822 FIXME("%p, %p.\n", iface
, fontset
);
2827 static HANDLE WINAPI
dwritefontcollection3_GetExpirationEvent(IDWriteFontCollection3
*iface
)
2829 FIXME("%p.\n", iface
);
2834 static const IDWriteFontCollection3Vtbl fontcollectionvtbl
=
2836 dwritefontcollection_QueryInterface
,
2837 dwritefontcollection_AddRef
,
2838 dwritefontcollection_Release
,
2839 dwritefontcollection_GetFontFamilyCount
,
2840 dwritefontcollection_GetFontFamily
,
2841 dwritefontcollection_FindFamilyName
,
2842 dwritefontcollection_GetFontFromFontFace
,
2843 dwritefontcollection1_GetFontSet
,
2844 dwritefontcollection1_GetFontFamily
,
2845 dwritefontcollection2_GetFontFamily
,
2846 dwritefontcollection2_GetMatchingFonts
,
2847 dwritefontcollection2_GetFontFamilyModel
,
2848 dwritefontcollection2_GetFontSet
,
2849 dwritefontcollection3_GetExpirationEvent
,
2852 static const IDWriteFontCollection3Vtbl systemfontcollectionvtbl
=
2854 dwritesystemfontcollection_QueryInterface
,
2855 dwritefontcollection_AddRef
,
2856 dwritefontcollection_Release
,
2857 dwritefontcollection_GetFontFamilyCount
,
2858 dwritefontcollection_GetFontFamily
,
2859 dwritefontcollection_FindFamilyName
,
2860 dwritefontcollection_GetFontFromFontFace
,
2861 dwritefontcollection1_GetFontSet
,
2862 dwritefontcollection1_GetFontFamily
,
2863 dwritefontcollection2_GetFontFamily
,
2864 dwritefontcollection2_GetMatchingFonts
,
2865 dwritefontcollection2_GetFontFamilyModel
,
2866 dwritefontcollection2_GetFontSet
,
2867 dwritefontcollection3_GetExpirationEvent
,
2870 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2872 if (!dwrite_array_reserve((void **)&family_data
->fonts
, &family_data
->size
, family_data
->count
+ 1,
2873 sizeof(*family_data
->fonts
)))
2875 return E_OUTOFMEMORY
;
2878 family_data
->fonts
[family_data
->count
++] = font_data
;
2879 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2880 family_data
->has_normal_face
= 1;
2881 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2882 family_data
->has_oblique_face
= 1;
2884 family_data
->has_italic_face
= 1;
2888 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
,
2889 struct dwrite_fontfamily_data
*family
)
2891 if (!dwrite_array_reserve((void **)&collection
->family_data
, &collection
->size
, collection
->count
+ 1,
2892 sizeof(*collection
->family_data
)))
2894 return E_OUTOFMEMORY
;
2897 collection
->family_data
[collection
->count
++] = family
;
2901 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2903 collection
->IDWriteFontCollection3_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2904 collection
->refcount
= 1;
2905 collection
->count
= 0;
2906 collection
->size
= 0;
2907 collection
->family_data
= NULL
;
2912 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2914 IDWriteFontFileLoader
*loader
;
2921 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2925 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2929 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2930 IDWriteFontFileLoader_Release(loader
);
2937 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2939 BOOL exists
= FALSE
;
2944 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2945 if (FAILED(hr
) || !exists
)
2948 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2951 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2955 while (isspaceW(*in
))
2959 if (!(len
= strlenW(in
)))
2962 while (isspaceW(in
[len
-1]))
2965 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2974 INT len
; /* token length */
2975 INT fulllen
; /* full length including following separators */
2978 static inline BOOL
is_name_separator_char(WCHAR ch
)
2980 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2983 struct name_pattern
{
2984 const WCHAR
*part1
; /* NULL indicates end of list */
2985 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2988 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2990 const struct name_pattern
*pattern
;
2991 struct name_token
*token
;
2994 while ((pattern
= &patterns
[i
++])->part1
) {
2995 int len_part1
= strlenW(pattern
->part1
);
2996 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2998 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2999 if (len_part2
== 0) {
3000 /* simple case with single part pattern */
3001 if (token
->len
!= len_part1
)
3004 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
3005 if (match
) *match
= *token
;
3006 list_remove(&token
->entry
);
3012 struct name_token
*next_token
;
3013 struct list
*next_entry
;
3015 /* pattern parts are stored in reading order, tokens list is reversed */
3016 if (token
->len
< len_part2
)
3019 /* it's possible to have combined string as a token, like ExtraCondensed */
3020 if (token
->len
== len_part1
+ len_part2
) {
3021 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
3024 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
3027 /* combined string match */
3028 if (match
) *match
= *token
;
3029 list_remove(&token
->entry
);
3034 /* now it's only possible to have two tokens matched to respective pattern parts */
3035 if (token
->len
!= len_part2
)
3038 next_entry
= list_next(tokens
, &token
->entry
);
3040 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
3041 if (next_token
->len
!= len_part1
)
3044 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
3047 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
3050 /* both parts matched, remove tokens */
3052 match
->ptr
= next_token
->ptr
;
3053 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
3055 list_remove(&token
->entry
);
3056 list_remove(&next_token
->entry
);
3057 heap_free(next_token
);
3072 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
3074 static const WCHAR itaW
[] = {'i','t','a',0};
3075 static const WCHAR italW
[] = {'i','t','a','l',0};
3076 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
3077 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
3079 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
3080 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
3081 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
3082 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
3084 static const struct name_pattern italic_patterns
[] = {
3093 static const struct name_pattern oblique_patterns
[] = {
3102 /* italic patterns first */
3103 if (match_pattern_list(tokens
, italic_patterns
, match
))
3104 return DWRITE_FONT_STYLE_ITALIC
;
3106 /* oblique patterns */
3107 if (match_pattern_list(tokens
, oblique_patterns
, match
))
3108 return DWRITE_FONT_STYLE_OBLIQUE
;
3113 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
3114 struct name_token
*match
)
3116 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
3117 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
3118 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
3119 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
3120 static const WCHAR wideW
[] = {'w','i','d','e',0};
3121 static const WCHAR condW
[] = {'c','o','n','d',0};
3123 static const struct name_pattern ultracondensed_patterns
[] = {
3124 { extraW
, compressedW
},
3125 { extW
, compressedW
},
3126 { ultraW
, compressedW
},
3127 { ultraW
, condensedW
},
3132 static const struct name_pattern extracondensed_patterns
[] = {
3134 { extraW
, condensedW
},
3135 { extW
, condensedW
},
3141 static const struct name_pattern semicondensed_patterns
[] = {
3144 { semiW
, condensedW
},
3149 static const struct name_pattern semiexpanded_patterns
[] = {
3151 { semiW
, expandedW
},
3152 { semiW
, extendedW
},
3156 static const struct name_pattern extraexpanded_patterns
[] = {
3157 { extraW
, expandedW
},
3158 { extW
, expandedW
},
3159 { extraW
, extendedW
},
3160 { extW
, extendedW
},
3164 static const struct name_pattern ultraexpanded_patterns
[] = {
3165 { ultraW
, expandedW
},
3166 { ultraW
, extendedW
},
3170 static const struct name_pattern condensed_patterns
[] = {
3176 static const struct name_pattern expanded_patterns
[] = {
3182 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
3183 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
3185 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
3186 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
3188 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
3189 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
3191 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
3192 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
3194 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
3195 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
3197 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
3198 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
3200 if (match_pattern_list(tokens
, condensed_patterns
, match
))
3201 return DWRITE_FONT_STRETCH_CONDENSED
;
3203 if (match_pattern_list(tokens
, expanded_patterns
, match
))
3204 return DWRITE_FONT_STRETCH_EXPANDED
;
3209 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
3210 struct name_token
*match
)
3212 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
3213 static const WCHAR nordW
[] = {'n','o','r','d',0};
3215 static const struct name_pattern thin_patterns
[] = {
3222 static const struct name_pattern extralight_patterns
[] = {
3229 static const struct name_pattern semilight_patterns
[] = {
3234 static const struct name_pattern demibold_patterns
[] = {
3240 static const struct name_pattern extrabold_patterns
[] = {
3247 static const struct name_pattern extrablack_patterns
[] = {
3254 static const struct name_pattern bold_patterns
[] = {
3259 static const struct name_pattern thin2_patterns
[] = {
3264 static const struct name_pattern light_patterns
[] = {
3269 static const struct name_pattern medium_patterns
[] = {
3274 static const struct name_pattern black_patterns
[] = {
3281 static const struct name_pattern demibold2_patterns
[] = {
3286 static const struct name_pattern extrabold2_patterns
[] = {
3291 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
3292 matching pattern. */
3294 if (match_pattern_list(tokens
, thin_patterns
, match
))
3295 return DWRITE_FONT_WEIGHT_THIN
;
3297 if (match_pattern_list(tokens
, extralight_patterns
, match
))
3298 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
3300 if (match_pattern_list(tokens
, semilight_patterns
, match
))
3301 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
3303 if (match_pattern_list(tokens
, demibold_patterns
, match
))
3304 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3306 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
3307 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3309 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
3310 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
3312 if (match_pattern_list(tokens
, bold_patterns
, match
))
3313 return DWRITE_FONT_WEIGHT_BOLD
;
3315 if (match_pattern_list(tokens
, thin2_patterns
, match
))
3316 return DWRITE_FONT_WEIGHT_THIN
;
3318 if (match_pattern_list(tokens
, light_patterns
, match
))
3319 return DWRITE_FONT_WEIGHT_LIGHT
;
3321 if (match_pattern_list(tokens
, medium_patterns
, match
))
3322 return DWRITE_FONT_WEIGHT_MEDIUM
;
3324 if (match_pattern_list(tokens
, black_patterns
, match
))
3325 return DWRITE_FONT_WEIGHT_BLACK
;
3327 if (match_pattern_list(tokens
, black_patterns
, match
))
3328 return DWRITE_FONT_WEIGHT_BLACK
;
3330 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3331 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3333 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3334 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3336 /* FIXME: use abbreviated names to extract weight */
3341 struct knownweight_entry
{
3343 DWRITE_FONT_WEIGHT weight
;
3346 static int compare_knownweights(const void *a
, const void* b
)
3348 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3349 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3352 if (target
> entry
->weight
)
3354 else if (target
< entry
->weight
)
3360 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3362 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3363 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3364 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3365 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3366 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3367 const struct knownweight_entry
*ptr
;
3369 static const struct knownweight_entry knownweights
[] = {
3370 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3371 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3372 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3373 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3374 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3375 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3376 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3377 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3378 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3379 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3382 ptr
= bsearch(&weight
, knownweights
, ARRAY_SIZE(knownweights
), sizeof(knownweights
[0]),
3383 compare_knownweights
);
3389 strcpyW(nameW
, ptr
->nameW
);
3393 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3395 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3396 strW
[name
->len
] = 0;
3399 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3400 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3402 static const WCHAR bookW
[] = {'B','o','o','k',0};
3403 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3404 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3405 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3406 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3408 static const WCHAR
*regular_patterns
[] = {
3417 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3421 len
= strlenW(facenameW
);
3423 /* remove rightmost regular variant from face name */
3424 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3425 int pattern_len
= strlenW(ptr
);
3428 if (pattern_len
> len
)
3431 src
= facenameW
+ len
- pattern_len
;
3432 while (src
>= facenameW
) {
3433 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3434 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3435 len
= strlenW(facenameW
);
3447 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3455 struct name_token
*token
= heap_alloc(sizeof(*token
));
3460 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3466 /* skip separators */
3467 while (is_name_separator_char(*ptr
)) {
3472 list_add_head(tokens
, &token
->entry
);
3476 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3478 struct name_token
*token
, *token2
;
3479 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3482 list_remove(&token
->entry
);
3484 /* don't include last separator */
3485 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3486 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3494 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3496 struct name_token stretch_name
, weight_name
, style_name
;
3497 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3498 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3499 const WCHAR
*regular_ptr
= NULL
;
3500 DWRITE_FONT_STRETCH stretch
;
3501 DWRITE_FONT_WEIGHT weight
;
3505 /* remove leading and trailing spaces from family and face name */
3506 trim_spaces(familyW
, familynameW
);
3507 len
= trim_spaces(faceW
, facenameW
);
3509 /* remove rightmost regular variant from face name */
3510 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3512 /* append face name to family name, FIXME check if face name is a substring of family name */
3514 strcatW(familynameW
, spaceW
);
3515 strcatW(familynameW
, facenameW
);
3518 /* tokenize with " .-_" */
3519 fontname_tokenize(&tokens
, familynameW
);
3521 /* extract and resolve style */
3522 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3524 /* extract stretch */
3525 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3527 /* extract weight */
3528 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3530 /* resolve weight */
3531 if (weight
!= font
->weight
) {
3532 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3533 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3534 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3535 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3536 !(abs(weight
- font
->weight
) <= 150 &&
3537 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3538 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3539 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3541 font
->weight
= weight
;
3545 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3546 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3547 stretch itself is normal (extracted stretch is never normal). */
3548 if (stretch
!= font
->stretch
) {
3549 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3550 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3551 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3553 font
->stretch
= stretch
;
3557 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3559 /* get final combined string from what's left in token list, list is released */
3560 fontname_tokens_to_str(&tokens
, finalW
);
3562 if (!strcmpW(familyW
, finalW
))
3565 /* construct face name */
3566 strcpyW(familyW
, finalW
);
3568 /* resolved weight name */
3569 if (weight_name
.ptr
)
3570 font_name_token_to_str(&weight_name
, weightW
);
3571 /* ignore normal weight */
3572 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3574 /* for known weight values use appropriate names */
3575 else if (is_known_weight_value(font
->weight
, weightW
)) {
3577 /* use Wnnn format as a fallback in case weight is not one of known values */
3579 static const WCHAR fmtW
[] = {'W','%','d',0};
3580 sprintfW(weightW
, fmtW
, font
->weight
);
3583 /* resolved stretch name */
3584 if (stretch_name
.ptr
)
3585 font_name_token_to_str(&stretch_name
, stretchW
);
3586 /* ignore normal stretch */
3587 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3589 /* use predefined stretch names */
3591 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3592 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3593 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3594 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3595 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3596 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3598 static const WCHAR
*stretchnamesW
[] = {
3599 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3604 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3610 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3613 /* resolved style name */
3615 font_name_token_to_str(&style_name
, styleW
);
3616 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3618 /* use predefined names */
3620 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3621 strcpyW(styleW
, italicW
);
3623 strcpyW(styleW
, obliqueW
);
3626 /* use Regular match if it was found initially */
3627 if (!*weightW
&& !*stretchW
&& !*styleW
)
3628 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3632 strcpyW(faceW
, stretchW
);
3635 strcatW(faceW
, spaceW
);
3636 strcatW(faceW
, weightW
);
3640 strcatW(faceW
, spaceW
);
3641 strcatW(faceW
, styleW
);
3645 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3649 static HRESULT
init_font_data(const struct fontface_desc
*desc
, struct dwrite_font_data
**ret
)
3651 struct file_stream_desc stream_desc
;
3652 struct dwrite_font_props props
;
3653 struct dwrite_font_data
*data
;
3654 WCHAR familyW
[255], faceW
[255];
3659 data
= heap_alloc_zero(sizeof(*data
));
3661 return E_OUTOFMEMORY
;
3664 data
->file
= desc
->files
[0];
3665 data
->face_index
= desc
->index
;
3666 data
->face_type
= desc
->face_type
;
3667 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3668 data
->bold_sim_tested
= 0;
3669 data
->oblique_sim_tested
= 0;
3670 IDWriteFontFile_AddRef(data
->file
);
3672 stream_desc
.stream
= desc
->stream
;
3673 stream_desc
.face_type
= desc
->face_type
;
3674 stream_desc
.face_index
= desc
->index
;
3675 opentype_get_font_properties(&stream_desc
, &props
);
3676 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3677 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3679 /* get family name from font file */
3680 hr
= opentype_get_font_familyname(&stream_desc
, &data
->family_names
);
3682 WARN("unable to get family name from font\n");
3683 release_font_data(data
);
3687 data
->style
= props
.style
;
3688 data
->stretch
= props
.stretch
;
3689 data
->weight
= props
.weight
;
3690 data
->panose
= props
.panose
;
3691 data
->fontsig
= props
.fontsig
;
3692 data
->lf
= props
.lf
;
3693 data
->flags
= props
.flags
;
3695 fontstrings_get_en_string(data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
3696 fontstrings_get_en_string(data
->names
, faceW
, ARRAY_SIZE(faceW
));
3697 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3698 set_en_localizedstring(data
->family_names
, familyW
);
3699 set_en_localizedstring(data
->names
, faceW
);
3702 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3708 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3709 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3711 struct dwrite_font_data
*data
;
3715 data
= heap_alloc_zero(sizeof(*data
));
3717 return E_OUTOFMEMORY
;
3721 data
->simulations
|= sim
;
3722 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3723 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3724 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3725 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3726 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3728 IDWriteFontFile_AddRef(data
->file
);
3729 IDWriteLocalizedStrings_AddRef(data
->family_names
);
3731 create_localizedstrings(&data
->names
);
3732 add_localizedstring(data
->names
, enusW
, facenameW
);
3734 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3740 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3742 struct dwrite_fontfamily_data
*data
;
3744 data
= heap_alloc_zero(sizeof(*data
));
3746 return E_OUTOFMEMORY
;
3749 data
->familyname
= familyname
;
3750 IDWriteLocalizedStrings_AddRef(familyname
);
3757 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3759 size_t i
, j
, heaviest
;
3761 for (i
= 0; i
< family
->count
; ++i
)
3763 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3766 if (family
->fonts
[i
]->bold_sim_tested
)
3769 family
->fonts
[i
]->bold_sim_tested
= 1;
3770 for (j
= i
; j
< family
->count
; ++j
)
3772 if (family
->fonts
[j
]->bold_sim_tested
)
3775 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3776 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3777 if (family
->fonts
[j
]->weight
> weight
) {
3778 weight
= family
->fonts
[j
]->weight
;
3781 family
->fonts
[j
]->bold_sim_tested
= 1;
3785 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3786 static const struct name_pattern weightsim_patterns
[] = {
3801 WCHAR facenameW
[255], initialW
[255];
3802 struct dwrite_font_data
*boldface
;
3805 /* add Bold simulation based on heaviest face data */
3807 /* Simulated face name should only contain Bold as weight term,
3808 so remove existing regular and weight terms. */
3809 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, ARRAY_SIZE(initialW
));
3810 facename_remove_regular_term(initialW
, -1);
3812 /* remove current weight pattern */
3813 fontname_tokenize(&tokens
, initialW
);
3814 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3815 fontname_tokens_to_str(&tokens
, facenameW
);
3817 /* Bold suffix for new name */
3819 strcatW(facenameW
, spaceW
);
3820 strcatW(facenameW
, boldW
);
3822 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3823 boldface
->bold_sim_tested
= 1;
3824 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
3825 fontfamily_add_font(family
, boldface
);
3831 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3835 for (i
= 0; i
< family
->count
; ++i
)
3837 UINT32 regular
= ~0u, oblique
= ~0u;
3838 struct dwrite_font_data
*obliqueface
;
3839 WCHAR facenameW
[255];
3841 if (family
->fonts
[i
]->oblique_sim_tested
)
3844 family
->fonts
[i
]->oblique_sim_tested
= 1;
3845 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3847 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3850 /* find regular style with same weight/stretch values */
3851 for (j
= i
; j
< family
->count
; ++j
)
3853 if (family
->fonts
[j
]->oblique_sim_tested
)
3856 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3857 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3859 family
->fonts
[j
]->oblique_sim_tested
= 1;
3860 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3863 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3867 if (regular
!= ~0u && oblique
!= ~0u)
3871 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3875 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3879 /* add oblique simulation based on this regular face */
3881 /* remove regular term if any, append 'Oblique' */
3882 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, ARRAY_SIZE(facenameW
));
3883 facename_remove_regular_term(facenameW
, -1);
3886 strcatW(facenameW
, spaceW
);
3887 strcatW(facenameW
, obliqueW
);
3889 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3890 obliqueface
->oblique_sim_tested
= 1;
3891 obliqueface
->lf
.lfItalic
= 1;
3892 fontfamily_add_font(family
, obliqueface
);
3897 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3898 const WCHAR
*replacement_name
)
3900 UINT32 i
= collection_find_family(collection
, replacement_name
);
3901 struct dwrite_fontfamily_data
*target
;
3902 IDWriteLocalizedStrings
*strings
;
3905 /* replacement does not exist */
3909 hr
= create_localizedstrings(&strings
);
3913 /* add a new family with target name, reuse font data from replacement */
3914 add_localizedstring(strings
, enusW
, target_name
);
3915 hr
= init_fontfamily_data(strings
, &target
);
3917 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3920 for (i
= 0; i
< replacement
->count
; ++i
)
3922 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3923 addref_font_data(replacement
->fonts
[i
]);
3926 fontcollection_add_family(collection
, target
);
3927 fontstrings_get_en_string(replacement
->familyname
, nameW
, ARRAY_SIZE(nameW
));
3928 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3930 IDWriteLocalizedStrings_Release(strings
);
3934 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3935 system font collections. */
3936 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3938 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3943 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3946 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3951 max_namelen
++; /* returned value doesn't include room for '\0' */
3952 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3953 data
= heap_alloc(max_datalen
);
3955 datalen
= max_datalen
;
3956 namelen
= max_namelen
;
3957 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3958 if (collection_find_family(collection
, name
) == ~0u) {
3959 if (type
== REG_MULTI_SZ
) {
3960 WCHAR
*replacement
= data
;
3961 while (*replacement
) {
3962 if (fontcollection_add_replacement(collection
, name
, replacement
))
3964 replacement
+= strlenW(replacement
) + 1;
3967 else if (type
== REG_SZ
)
3968 fontcollection_add_replacement(collection
, name
, data
);
3971 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3973 datalen
= max_datalen
;
3974 namelen
= max_namelen
;
3982 HRESULT
create_font_collection(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
3983 IDWriteFontCollection3
**ret
)
3985 struct fontfile_enum
{
3987 IDWriteFontFile
*file
;
3989 struct fontfile_enum
*fileenum
, *fileenum2
;
3990 struct dwrite_fontcollection
*collection
;
3991 struct list scannedfiles
;
3992 BOOL current
= FALSE
;
3998 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3999 if (!collection
) return E_OUTOFMEMORY
;
4001 hr
= init_font_collection(collection
, is_system
);
4003 heap_free(collection
);
4007 *ret
= &collection
->IDWriteFontCollection3_iface
;
4009 TRACE("building font collection:\n");
4011 list_init(&scannedfiles
);
4012 while (hr
== S_OK
) {
4013 DWRITE_FONT_FACE_TYPE face_type
;
4014 DWRITE_FONT_FILE_TYPE file_type
;
4015 BOOL supported
, same
= FALSE
;
4016 IDWriteFontFileStream
*stream
;
4017 IDWriteFontFile
*file
;
4021 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
4022 if (FAILED(hr
) || !current
)
4025 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
4029 /* check if we've scanned this file already */
4030 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
4031 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
4036 IDWriteFontFile_Release(file
);
4040 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4041 IDWriteFontFile_Release(file
);
4045 /* Unsupported formats are skipped. */
4046 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4047 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4048 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4049 IDWriteFontFileStream_Release(stream
);
4050 IDWriteFontFile_Release(file
);
4055 /* add to scanned list */
4056 fileenum
= heap_alloc(sizeof(*fileenum
));
4057 fileenum
->file
= file
;
4058 list_add_tail(&scannedfiles
, &fileenum
->entry
);
4060 for (i
= 0; i
< face_count
; ++i
)
4062 struct dwrite_font_data
*font_data
;
4063 struct fontface_desc desc
;
4067 desc
.factory
= factory
;
4068 desc
.face_type
= face_type
;
4070 desc
.stream
= stream
;
4071 desc
.files_number
= 1;
4073 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4074 desc
.font_data
= NULL
;
4076 /* Allocate an initialize new font data structure. */
4077 hr
= init_font_data(&desc
, &font_data
);
4080 /* move to next one */
4085 fontstrings_get_en_string(font_data
->family_names
, familyW
, ARRAY_SIZE(familyW
));
4087 /* ignore dot named faces */
4088 if (familyW
[0] == '.')
4090 WARN("Ignoring face %s\n", debugstr_w(familyW
));
4091 release_font_data(font_data
);
4095 index
= collection_find_family(collection
, familyW
);
4097 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
4099 struct dwrite_fontfamily_data
*family_data
;
4101 /* create and init new family */
4102 hr
= init_fontfamily_data(font_data
->family_names
, &family_data
);
4104 /* add font to family, family - to collection */
4105 hr
= fontfamily_add_font(family_data
, font_data
);
4107 hr
= fontcollection_add_family(collection
, family_data
);
4110 release_fontfamily_data(family_data
);
4118 IDWriteFontFileStream_Release(stream
);
4121 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
4122 IDWriteFontFile_Release(fileenum
->file
);
4123 list_remove(&fileenum
->entry
);
4124 heap_free(fileenum
);
4127 for (i
= 0; i
< collection
->count
; ++i
)
4129 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4130 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4134 fontcollection_add_replacements(collection
);
4136 collection
->factory
= factory
;
4137 IDWriteFactory7_AddRef(factory
);
4142 struct system_fontfile_enumerator
4144 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
4147 IDWriteFactory7
*factory
;
4152 DWORD filename_size
;
4155 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
4157 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
4160 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
4162 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
4163 IDWriteFontFileEnumerator_AddRef(iface
);
4168 WARN("%s not implemented.\n", debugstr_guid(riid
));
4172 return E_NOINTERFACE
;
4175 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
4177 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4178 return InterlockedIncrement(&enumerator
->ref
);
4181 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
4183 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4184 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
4188 IDWriteFactory7_Release(enumerator
->factory
);
4189 RegCloseKey(enumerator
->hkey
);
4190 heap_free(enumerator
->filename
);
4191 heap_free(enumerator
);
4197 static HRESULT
create_local_file_reference(IDWriteFactory7
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
4201 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
4202 if (!strchrW(filename
, '\\')) {
4203 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
4204 WCHAR fullpathW
[MAX_PATH
];
4206 GetWindowsDirectoryW(fullpathW
, ARRAY_SIZE(fullpathW
));
4207 strcatW(fullpathW
, fontsW
);
4208 strcatW(fullpathW
, filename
);
4210 hr
= IDWriteFactory7_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
4213 hr
= IDWriteFactory7_CreateFontFileReference(factory
, filename
, NULL
, file
);
4218 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
4220 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4224 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
4227 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
4230 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
4232 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
4233 WCHAR name_buf
[256], *name
= name_buf
;
4234 DWORD name_count
, max_name_count
= ARRAY_SIZE(name_buf
), type
, data_size
;
4239 enumerator
->index
++;
4241 /* iterate until we find next string value */
4244 name_count
= max_name_count
;
4245 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
4247 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
4248 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
4249 if (r
== ERROR_MORE_DATA
) {
4250 if (name_count
>= max_name_count
) {
4251 if (name
!= name_buf
) heap_free(name
);
4252 max_name_count
*= 2;
4253 name
= heap_alloc(max_name_count
* sizeof(*name
));
4254 if (!name
) return E_OUTOFMEMORY
;
4256 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
4257 heap_free(enumerator
->filename
);
4258 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
4259 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4260 if (!enumerator
->filename
) {
4266 } while (r
== ERROR_MORE_DATA
);
4268 if (r
!= ERROR_SUCCESS
) {
4269 enumerator
->filename
[0] = 0;
4272 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
4273 if (type
== REG_SZ
&& *name
!= '@') {
4277 enumerator
->index
++;
4279 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
4282 if (name
!= name_buf
) heap_free(name
);
4286 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
4288 systemfontfileenumerator_QueryInterface
,
4289 systemfontfileenumerator_AddRef
,
4290 systemfontfileenumerator_Release
,
4291 systemfontfileenumerator_MoveNext
,
4292 systemfontfileenumerator_GetCurrentFontFile
4295 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory7
*factory
, IDWriteFontFileEnumerator
**ret
)
4297 struct system_fontfile_enumerator
*enumerator
;
4298 static const WCHAR fontslistW
[] = {
4299 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4300 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4301 'F','o','n','t','s',0
4306 enumerator
= heap_alloc(sizeof(*enumerator
));
4308 return E_OUTOFMEMORY
;
4310 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
4311 enumerator
->ref
= 1;
4312 enumerator
->factory
= factory
;
4313 enumerator
->index
= -1;
4314 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
4315 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
4316 if (!enumerator
->filename
) {
4317 heap_free(enumerator
);
4318 return E_OUTOFMEMORY
;
4321 IDWriteFactory7_AddRef(factory
);
4323 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
))
4325 ERR("failed to open fonts list key\n");
4326 IDWriteFactory7_Release(factory
);
4327 heap_free(enumerator
->filename
);
4328 heap_free(enumerator
);
4332 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4337 HRESULT
get_system_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection1
**collection
)
4339 IDWriteFontFileEnumerator
*enumerator
;
4344 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4348 TRACE("building system font collection for factory %p\n", factory
);
4349 hr
= create_font_collection(factory
, enumerator
, TRUE
, (IDWriteFontCollection3
**)collection
);
4350 IDWriteFontFileEnumerator_Release(enumerator
);
4354 static HRESULT
eudc_collection_add_family(IDWriteFactory7
*factory
, struct dwrite_fontcollection
*collection
,
4355 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4357 static const WCHAR defaultfontW
[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t','E','U','D','C','F','o','n','t',0};
4358 static const WCHAR emptyW
[] = {0};
4359 struct dwrite_fontfamily_data
*family_data
;
4360 IDWriteLocalizedStrings
*names
;
4361 DWRITE_FONT_FACE_TYPE face_type
;
4362 DWRITE_FONT_FILE_TYPE file_type
;
4363 IDWriteFontFileStream
*stream
;
4364 IDWriteFontFile
*file
;
4365 UINT32 face_count
, i
;
4369 /* create font file from this path */
4370 hr
= create_local_file_reference(factory
, pathW
, &file
);
4374 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4375 IDWriteFontFile_Release(file
);
4379 /* Unsupported formats are skipped. */
4380 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4381 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4382 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4383 IDWriteFontFileStream_Release(stream
);
4384 IDWriteFontFile_Release(file
);
4388 /* create and init new family */
4390 /* Family names are added for non-specific locale, represented with empty string.
4391 Default family appears with empty family name. */
4392 create_localizedstrings(&names
);
4393 if (!strcmpiW(keynameW
, defaultfontW
))
4394 add_localizedstring(names
, emptyW
, emptyW
);
4396 add_localizedstring(names
, emptyW
, keynameW
);
4398 hr
= init_fontfamily_data(names
, &family_data
);
4399 IDWriteLocalizedStrings_Release(names
);
4401 IDWriteFontFile_Release(file
);
4405 /* fill with faces */
4406 for (i
= 0; i
< face_count
; i
++) {
4407 struct dwrite_font_data
*font_data
;
4408 struct fontface_desc desc
;
4410 /* alloc and init new font data structure */
4411 desc
.factory
= factory
;
4412 desc
.face_type
= face_type
;
4415 desc
.stream
= stream
;
4416 desc
.files_number
= 1;
4417 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4418 desc
.font_data
= NULL
;
4420 hr
= init_font_data(&desc
, &font_data
);
4424 /* add font to family */
4425 hr
= fontfamily_add_font(family_data
, font_data
);
4427 release_font_data(font_data
);
4430 /* add family to collection */
4431 hr
= fontcollection_add_family(collection
, family_data
);
4433 release_fontfamily_data(family_data
);
4434 IDWriteFontFileStream_Release(stream
);
4435 IDWriteFontFile_Release(file
);
4440 HRESULT
get_eudc_fontcollection(IDWriteFactory7
*factory
, IDWriteFontCollection3
**ret
)
4442 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4443 struct dwrite_fontcollection
*collection
;
4444 static const WCHAR emptyW
[] = {0};
4445 WCHAR eudckeypathW
[16];
4453 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4457 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4458 if (!collection
) return E_OUTOFMEMORY
;
4460 hr
= init_font_collection(collection
, FALSE
);
4462 heap_free(collection
);
4466 *ret
= &collection
->IDWriteFontCollection3_iface
;
4467 collection
->factory
= factory
;
4468 IDWriteFactory7_AddRef(factory
);
4470 /* return empty collection if EUDC fonts are not configured */
4471 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4472 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4475 retval
= ERROR_SUCCESS
;
4477 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4478 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4479 DWORD type
, path_len
, name_len
;
4481 path_len
= ARRAY_SIZE(pathW
);
4482 name_len
= ARRAY_SIZE(keynameW
);
4483 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4484 if (retval
|| type
!= REG_SZ
)
4487 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4489 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4491 RegCloseKey(eudckey
);
4493 /* try to add global default if not defined for specific codepage */
4495 hr
= IDWriteFontCollection3_FindFamilyName(&collection
->IDWriteFontCollection3_iface
, emptyW
,
4497 if (FAILED(hr
) || !exists
) {
4498 static const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4499 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4501 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4504 /* EUDC collection offers simulated faces too */
4505 for (i
= 0; i
< collection
->count
; ++i
)
4507 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4508 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4514 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4516 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4518 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4520 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4523 IDWriteFontFile_AddRef(iface
);
4527 WARN("%s not implemented.\n", debugstr_guid(riid
));
4530 return E_NOINTERFACE
;
4533 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4535 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4536 ULONG ref
= InterlockedIncrement(&This
->ref
);
4537 TRACE("(%p)->(%d)\n", This
, ref
);
4541 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4543 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4544 ULONG ref
= InterlockedDecrement(&This
->ref
);
4546 TRACE("(%p)->(%d)\n", This
, ref
);
4550 IDWriteFontFileLoader_Release(This
->loader
);
4551 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4552 heap_free(This
->reference_key
);
4559 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4561 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4562 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4563 *fontFileReferenceKey
= This
->reference_key
;
4564 *fontFileReferenceKeySize
= This
->key_size
;
4569 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4571 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4572 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4573 *fontFileLoader
= This
->loader
;
4574 IDWriteFontFileLoader_AddRef(This
->loader
);
4579 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4580 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4582 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4583 IDWriteFontFileStream
*stream
;
4586 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, is_supported
, file_type
, face_type
, face_count
);
4588 *is_supported
= FALSE
;
4589 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4591 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4594 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4598 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4600 /* TODO: Further Analysis */
4601 IDWriteFontFileStream_Release(stream
);
4605 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4606 dwritefontfile_QueryInterface
,
4607 dwritefontfile_AddRef
,
4608 dwritefontfile_Release
,
4609 dwritefontfile_GetReferenceKey
,
4610 dwritefontfile_GetLoader
,
4611 dwritefontfile_Analyze
,
4614 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4615 IDWriteFontFile
**ret
)
4617 struct dwrite_fontfile
*file
;
4622 file
= heap_alloc(sizeof(*file
));
4623 key
= heap_alloc(key_size
);
4624 if (!file
|| !key
) {
4627 return E_OUTOFMEMORY
;
4630 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4632 IDWriteFontFileLoader_AddRef(loader
);
4633 file
->loader
= loader
;
4634 file
->stream
= NULL
;
4635 file
->reference_key
= key
;
4636 memcpy(file
->reference_key
, reference_key
, key_size
);
4637 file
->key_size
= key_size
;
4639 *ret
= &file
->IDWriteFontFile_iface
;
4644 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace5
**ret
)
4646 struct file_stream_desc stream_desc
;
4647 struct dwrite_font_data
*font_data
;
4648 struct dwrite_fontface
*fontface
;
4654 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4656 return E_OUTOFMEMORY
;
4658 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4659 if (!fontface
->files
) {
4660 heap_free(fontface
);
4661 return E_OUTOFMEMORY
;
4664 fontface
->IDWriteFontFace5_iface
.lpVtbl
= &dwritefontfacevtbl
;
4665 fontface
->refcount
= 1;
4666 fontface
->type
= desc
->face_type
;
4667 fontface
->file_count
= desc
->files_number
;
4668 fontface
->cmap
.exists
= TRUE
;
4669 fontface
->vdmx
.exists
= TRUE
;
4670 fontface
->gasp
.exists
= TRUE
;
4671 fontface
->cpal
.exists
= TRUE
;
4672 fontface
->colr
.exists
= TRUE
;
4673 fontface
->index
= desc
->index
;
4674 fontface
->simulations
= desc
->simulations
;
4675 fontface
->factory
= desc
->factory
;
4676 IDWriteFactory7_AddRef(fontface
->factory
);
4678 for (i
= 0; i
< fontface
->file_count
; i
++) {
4679 fontface
->files
[i
] = desc
->files
[i
];
4680 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4682 fontface
->stream
= desc
->stream
;
4683 IDWriteFontFileStream_AddRef(fontface
->stream
);
4685 stream_desc
.stream
= fontface
->stream
;
4686 stream_desc
.face_type
= desc
->face_type
;
4687 stream_desc
.face_index
= desc
->index
;
4688 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4689 opentype_get_font_typo_metrics(&stream_desc
, &fontface
->typo_metrics
.ascent
, &fontface
->typo_metrics
.descent
);
4690 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4691 /* TODO: test what happens if caret is already slanted */
4692 if (fontface
->caret
.slopeRise
== 1) {
4693 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4694 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4698 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace5_iface
);
4699 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace5_iface
))
4700 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4701 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace5_iface
))
4702 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4703 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace5_iface
);
4705 /* Font properties are reused from font object when 'normal' face creation path is used:
4706 collection -> family -> matching font -> fontface.
4708 If face is created directly from factory we have to go through properties resolution.
4710 if (desc
->font_data
)
4712 font_data
= desc
->font_data
;
4713 addref_font_data(font_data
);
4717 hr
= init_font_data(desc
, &font_data
);
4720 IDWriteFontFace5_Release(&fontface
->IDWriteFontFace5_iface
);
4725 fontface
->weight
= font_data
->weight
;
4726 fontface
->style
= font_data
->style
;
4727 fontface
->stretch
= font_data
->stretch
;
4728 fontface
->panose
= font_data
->panose
;
4729 fontface
->fontsig
= font_data
->fontsig
;
4730 fontface
->lf
= font_data
->lf
;
4731 fontface
->flags
|= font_data
->flags
& (FONT_IS_SYMBOL
| FONT_IS_MONOSPACED
| FONT_IS_COLORED
);
4732 fontface
->names
= font_data
->names
;
4733 if (fontface
->names
)
4734 IDWriteLocalizedStrings_AddRef(fontface
->names
);
4735 fontface
->family_names
= font_data
->family_names
;
4736 if (fontface
->family_names
)
4737 IDWriteLocalizedStrings_AddRef(fontface
->family_names
);
4738 memcpy(fontface
->info_strings
, font_data
->info_strings
, sizeof(fontface
->info_strings
));
4739 for (i
= 0; i
< ARRAY_SIZE(fontface
->info_strings
); ++i
)
4741 if (fontface
->info_strings
[i
])
4742 IDWriteLocalizedStrings_AddRef(fontface
->info_strings
[i
]);
4744 release_font_data(font_data
);
4746 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace5_iface
);
4748 *ret
= &fontface
->IDWriteFontFace5_iface
;
4753 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4760 struct local_cached_stream
4763 IDWriteFontFileStream
*stream
;
4764 struct local_refkey
*key
;
4768 struct dwrite_localfontfilestream
4770 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4773 struct local_cached_stream
*entry
;
4774 const void *file_ptr
;
4778 struct dwrite_localfontfileloader
{
4779 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4782 struct list streams
;
4783 CRITICAL_SECTION cs
;
4786 static struct dwrite_localfontfileloader local_fontfile_loader
;
4788 struct dwrite_inmemory_stream_data
4796 struct dwrite_inmemory_filestream
4798 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4801 struct dwrite_inmemory_stream_data
*data
;
4804 struct dwrite_inmemory_fileloader
4806 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
4809 struct dwrite_inmemory_stream_data
**streams
;
4814 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4816 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4819 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4821 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4824 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
4826 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
4829 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4831 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
4834 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
4836 if (InterlockedDecrement(&stream
->ref
) == 0) {
4838 IUnknown_Release(stream
->owner
);
4840 heap_free(stream
->data
);
4845 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4847 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4849 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4851 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
4852 IsEqualIID(riid
, &IID_IUnknown
))
4855 if (InterlockedIncrement(&This
->ref
) == 1) {
4856 InterlockedDecrement(&This
->ref
);
4863 WARN("%s not implemented.\n", debugstr_guid(riid
));
4866 return E_NOINTERFACE
;
4869 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4871 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4872 ULONG ref
= InterlockedIncrement(&This
->ref
);
4873 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4877 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4879 list_remove(&stream
->entry
);
4880 heap_free(stream
->key
);
4884 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4886 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4887 ULONG ref
= InterlockedDecrement(&This
->ref
);
4889 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4892 UnmapViewOfFile(This
->file_ptr
);
4894 EnterCriticalSection(&local_fontfile_loader
.cs
);
4895 release_cached_stream(This
->entry
);
4896 LeaveCriticalSection(&local_fontfile_loader
.cs
);
4904 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
4905 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4907 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4909 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
4910 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4912 *fragment_context
= NULL
;
4914 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4915 *fragment_start
= NULL
;
4919 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4923 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4925 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4926 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4929 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4931 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4932 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4937 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4939 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4942 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4944 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4945 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4946 *last_writetime
= li
.QuadPart
;
4951 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4953 localfontfilestream_QueryInterface
,
4954 localfontfilestream_AddRef
,
4955 localfontfilestream_Release
,
4956 localfontfilestream_ReadFileFragment
,
4957 localfontfilestream_ReleaseFileFragment
,
4958 localfontfilestream_GetFileSize
,
4959 localfontfilestream_GetLastWriteTime
4962 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4964 struct dwrite_localfontfilestream
*This
;
4968 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4970 return E_OUTOFMEMORY
;
4972 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4975 This
->file_ptr
= file_ptr
;
4977 This
->entry
= entry
;
4979 *ret
= &This
->IDWriteFontFileStream_iface
;
4983 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4985 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4987 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4989 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
4990 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
4991 IsEqualIID(riid
, &IID_IUnknown
))
4994 IDWriteLocalFontFileLoader_AddRef(iface
);
4998 WARN("%s not implemented.\n", debugstr_guid(riid
));
5001 return E_NOINTERFACE
;
5004 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
5006 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5007 ULONG ref
= InterlockedIncrement(&This
->ref
);
5008 TRACE("(%p)->(%d)\n", This
, ref
);
5012 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
5014 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5015 ULONG ref
= InterlockedDecrement(&This
->ref
);
5017 TRACE("(%p)->(%d)\n", This
, ref
);
5022 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
5024 const struct local_refkey
*refkey
= key
;
5025 struct local_cached_stream
*stream
;
5026 IDWriteFontFileStream
*filestream
;
5027 HANDLE file
, mapping
;
5034 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5035 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
5036 if (file
== INVALID_HANDLE_VALUE
) {
5037 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
5041 GetFileSizeEx(file
, &size
);
5042 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
5047 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
5048 CloseHandle(mapping
);
5050 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
5054 stream
= heap_alloc(sizeof(*stream
));
5056 UnmapViewOfFile(file_ptr
);
5057 return E_OUTOFMEMORY
;
5060 stream
->key
= heap_alloc(key_size
);
5062 UnmapViewOfFile(file_ptr
);
5064 return E_OUTOFMEMORY
;
5067 stream
->key_size
= key_size
;
5068 memcpy(stream
->key
, key
, key_size
);
5070 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
5072 UnmapViewOfFile(file_ptr
);
5073 heap_free(stream
->key
);
5078 stream
->stream
= filestream
;
5085 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
5086 UINT32 key_size
, IDWriteFontFileStream
**ret
)
5088 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5089 const struct local_refkey
*refkey
= key
;
5090 struct local_cached_stream
*stream
;
5093 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, ret
);
5094 TRACE("name: %s\n", debugstr_w(refkey
->name
));
5096 EnterCriticalSection(&This
->cs
);
5100 /* search cache first */
5101 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
5102 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
5103 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
5108 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
) {
5109 list_add_head(&This
->streams
, &stream
->entry
);
5110 *ret
= stream
->stream
;
5113 LeaveCriticalSection(&This
->cs
);
5118 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
5120 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5121 const struct local_refkey
*refkey
= key
;
5123 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
5125 *length
= strlenW(refkey
->name
);
5129 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
5131 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5132 const struct local_refkey
*refkey
= key
;
5134 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
5136 if (length
< strlenW(refkey
->name
))
5137 return E_INVALIDARG
;
5139 strcpyW(path
, refkey
->name
);
5143 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
5144 UINT32 key_size
, FILETIME
*writetime
)
5146 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
5147 const struct local_refkey
*refkey
= key
;
5149 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, writetime
);
5151 *writetime
= refkey
->writetime
;
5155 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
5156 localfontfileloader_QueryInterface
,
5157 localfontfileloader_AddRef
,
5158 localfontfileloader_Release
,
5159 localfontfileloader_CreateStreamFromKey
,
5160 localfontfileloader_GetFilePathLengthFromKey
,
5161 localfontfileloader_GetFilePathFromKey
,
5162 localfontfileloader_GetLastWriteTimeFromKey
5165 void init_local_fontfile_loader(void)
5167 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
5168 local_fontfile_loader
.ref
= 1;
5169 list_init(&local_fontfile_loader
.streams
);
5170 InitializeCriticalSection(&local_fontfile_loader
.cs
);
5171 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
5174 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
5176 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
5179 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
5181 struct local_refkey
*refkey
;
5184 return E_INVALIDARG
;
5186 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
5189 refkey
= heap_alloc(*size
);
5191 return E_OUTOFMEMORY
;
5194 refkey
->writetime
= *writetime
;
5196 WIN32_FILE_ATTRIBUTE_DATA info
;
5198 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
5199 refkey
->writetime
= info
.ftLastWriteTime
;
5201 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
5203 strcpyW(refkey
->name
, path
);
5210 /* IDWriteGlyphRunAnalysis */
5211 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
5213 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5215 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5217 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
5218 IsEqualIID(riid
, &IID_IUnknown
))
5221 IDWriteGlyphRunAnalysis_AddRef(iface
);
5225 WARN("%s not implemented.\n", debugstr_guid(riid
));
5228 return E_NOINTERFACE
;
5231 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
5233 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5234 ULONG ref
= InterlockedIncrement(&This
->ref
);
5235 TRACE("(%p)->(%u)\n", This
, ref
);
5239 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
5241 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5242 ULONG ref
= InterlockedDecrement(&This
->ref
);
5244 TRACE("(%p)->(%u)\n", This
, ref
);
5247 if (This
->run
.fontFace
)
5248 IDWriteFontFace_Release(This
->run
.fontFace
);
5249 heap_free(This
->glyphs
);
5250 heap_free(This
->origins
);
5251 heap_free(This
->bitmap
);
5258 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
5262 case DWRITE_RENDERING_MODE1_NATURAL
:
5263 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5264 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5271 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
5273 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
5276 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
5278 struct dwrite_glyphbitmap glyph_bitmap
;
5279 IDWriteFontFace4
*fontface
;
5283 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
5284 *bounds
= analysis
->bounds
;
5288 if (analysis
->run
.isSideways
)
5289 FIXME("sideways runs are not supported.\n");
5291 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5293 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5295 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5296 glyph_bitmap
.fontface
= fontface
;
5297 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5298 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5299 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5300 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5301 glyph_bitmap
.m
= &analysis
->m
;
5303 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5304 RECT
*bbox
= &glyph_bitmap
.bbox
;
5307 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5308 freetype_get_glyph_bbox(&glyph_bitmap
);
5310 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5311 (bbox
->bottom
- bbox
->top
);
5312 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5313 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5315 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5316 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5319 IDWriteFontFace4_Release(fontface
);
5321 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5322 *bounds
= analysis
->bounds
;
5325 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5327 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5329 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
5331 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5332 SetRectEmpty(bounds
);
5333 return E_INVALIDARG
;
5336 if (type
!= This
->texture_type
) {
5337 SetRectEmpty(bounds
);
5341 glyphrunanalysis_get_texturebounds(This
, bounds
);
5345 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5347 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5348 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5349 (runbounds
->left
- bounds
->left
) * 3;
5351 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5352 runbounds
->left
- bounds
->left
;
5355 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5357 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5358 struct dwrite_glyphbitmap glyph_bitmap
;
5359 IDWriteFontFace4
*fontface
;
5360 D2D_POINT_2F origin
;
5365 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5367 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5371 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5372 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5374 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5375 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5376 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5377 IDWriteFontFace4_Release(fontface
);
5378 return E_OUTOFMEMORY
;
5381 origin
.x
= origin
.y
= 0.0f
;
5383 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5384 glyph_bitmap
.fontface
= fontface
;
5385 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5386 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5387 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5388 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5389 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5390 glyph_bitmap
.m
= &analysis
->m
;
5391 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5392 IDWriteFontFace4_Release(fontface
);
5393 return E_OUTOFMEMORY
;
5396 bbox
= &glyph_bitmap
.bbox
;
5398 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5399 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5400 int x
, y
, width
, height
;
5403 glyph_bitmap
.glyph
= analysis
->run
.glyphIndices
[i
];
5404 freetype_get_glyph_bbox(&glyph_bitmap
);
5406 if (IsRectEmpty(bbox
))
5409 width
= bbox
->right
- bbox
->left
;
5410 height
= bbox
->bottom
- bbox
->top
;
5412 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5413 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5414 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5416 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5418 /* blit to analysis bitmap */
5419 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5422 /* convert 1bpp to 8bpp/24bpp */
5423 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5424 for (y
= 0; y
< height
; y
++) {
5425 for (x
= 0; x
< width
; x
++)
5426 if (src
[x
/ 8] & masks
[x
% 8])
5427 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5428 src
+= glyph_bitmap
.pitch
;
5429 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5433 for (y
= 0; y
< height
; y
++) {
5434 for (x
= 0; x
< width
; x
++)
5435 if (src
[x
/ 8] & masks
[x
% 8])
5436 dst
[x
] = DWRITE_ALPHA_MAX
;
5437 src
+= glyph_bitmap
.pitch
;
5438 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5443 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5444 for (y
= 0; y
< height
; y
++) {
5445 for (x
= 0; x
< width
; x
++)
5446 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5447 src
+= glyph_bitmap
.pitch
;
5448 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5452 for (y
= 0; y
< height
; y
++) {
5453 for (x
= 0; x
< width
; x
++)
5455 src
+= glyph_bitmap
.pitch
;
5456 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5461 heap_free(glyph_bitmap
.buf
);
5463 IDWriteFontFace4_Release(fontface
);
5465 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5467 /* we don't need this anymore */
5468 heap_free(analysis
->glyphs
);
5469 heap_free(analysis
->origins
);
5470 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5472 analysis
->glyphs
= NULL
;
5473 analysis
->origins
= NULL
;
5474 analysis
->run
.glyphIndices
= NULL
;
5475 analysis
->run
.fontFace
= NULL
;
5480 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5481 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5483 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5487 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5489 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5490 return E_INVALIDARG
;
5492 /* make sure buffer is large enough for requested texture type */
5493 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5494 if (This
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5497 if (size
< required
)
5498 return E_NOT_SUFFICIENT_BUFFER
;
5500 /* validate requested texture type */
5501 if (This
->texture_type
!= type
)
5502 return DWRITE_E_UNSUPPORTEDOPERATION
;
5504 memset(bitmap
, 0, size
);
5505 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5506 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5507 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5508 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5509 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5510 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5514 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5517 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5521 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5522 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5524 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5525 memcpy(dst
, src
, draw_width
);
5534 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5535 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5537 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5539 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5542 return E_INVALIDARG
;
5544 switch (This
->rendering_mode
)
5546 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5547 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5550 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5551 *gamma
= (FLOAT
)value
/ 1000.0f
;
5553 *cleartypelevel
= 1.0f
;
5556 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5557 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5559 case DWRITE_RENDERING_MODE1_ALIASED
:
5560 case DWRITE_RENDERING_MODE1_NATURAL
:
5561 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5562 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5563 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5564 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5573 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5574 glyphrunanalysis_QueryInterface
,
5575 glyphrunanalysis_AddRef
,
5576 glyphrunanalysis_Release
,
5577 glyphrunanalysis_GetAlphaTextureBounds
,
5578 glyphrunanalysis_CreateAlphaTexture
,
5579 glyphrunanalysis_GetAlphaBlendParams
5582 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5585 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5586 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5590 float fontface_get_scaled_design_advance(struct dwrite_fontface
*fontface
, DWRITE_MEASURING_MODE measuring_mode
,
5591 float emsize
, float ppdip
, const DWRITE_MATRIX
*transform
, UINT16 glyph
, BOOL is_sideways
)
5593 unsigned int upem
= fontface
->metrics
.designUnitsPerEm
;
5597 FIXME("Sideways mode is not supported.\n");
5599 advance
= fontface_get_design_advance(fontface
, measuring_mode
, emsize
, ppdip
, transform
, glyph
, is_sideways
);
5601 switch (measuring_mode
)
5603 case DWRITE_MEASURING_MODE_NATURAL
:
5604 return (float)advance
* emsize
/ (float)upem
;
5605 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5606 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5607 return ppdip
> 0.0f
? floorf(advance
* emsize
* ppdip
/ upem
+ 0.5f
) / ppdip
: 0.0f
;
5609 WARN("Unknown measuring mode %u.\n", measuring_mode
);
5614 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5616 struct dwrite_glyphrunanalysis
*analysis
;
5617 struct dwrite_fontface
*fontface
;
5618 D2D_POINT_2F origin
;
5624 /* Check rendering, antialiasing, measuring, and grid fitting modes. */
5625 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5626 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5627 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5628 return E_INVALIDARG
;
5630 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5631 return E_INVALIDARG
;
5633 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5634 return E_INVALIDARG
;
5636 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5637 return E_INVALIDARG
;
5639 analysis
= heap_alloc(sizeof(*analysis
));
5641 return E_OUTOFMEMORY
;
5643 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5645 analysis
->rendering_mode
= desc
->rendering_mode
;
5647 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5648 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5649 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5651 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5653 analysis
->flags
= 0;
5654 analysis
->bitmap
= NULL
;
5655 analysis
->max_glyph_bitmap_size
= 0;
5656 SetRectEmpty(&analysis
->bounds
);
5657 analysis
->run
= *desc
->run
;
5658 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5659 analysis
->glyphs
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->glyphs
));
5660 analysis
->origins
= heap_calloc(desc
->run
->glyphCount
, sizeof(*analysis
->origins
));
5662 if (!analysis
->glyphs
|| !analysis
->origins
) {
5663 heap_free(analysis
->glyphs
);
5664 heap_free(analysis
->origins
);
5666 analysis
->glyphs
= NULL
;
5667 analysis
->origins
= NULL
;
5669 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5670 return E_OUTOFMEMORY
;
5673 /* check if transform is usable */
5674 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5675 analysis
->m
= *desc
->transform
;
5676 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5679 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5681 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5682 analysis
->run
.glyphAdvances
= NULL
;
5683 analysis
->run
.glyphOffsets
= NULL
;
5685 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5687 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5689 fontface
= unsafe_impl_from_IDWriteFontFace(desc
->run
->fontFace
);
5691 origin
.x
= desc
->origin
.x
;
5692 origin
.y
= desc
->origin
.y
;
5693 for (i
= 0; i
< desc
->run
->glyphCount
; ++i
)
5697 /* Use nominal advances if not provided by caller. */
5698 if (desc
->run
->glyphAdvances
)
5699 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
];
5701 advance
= rtl_factor
* fontface_get_scaled_design_advance(fontface
, desc
->measuring_mode
,
5702 desc
->run
->fontEmSize
, 1.0f
, desc
->transform
, desc
->run
->glyphIndices
[i
], desc
->run
->isSideways
);
5704 analysis
->origins
[i
] = origin
;
5705 if (desc
->run
->bidiLevel
& 1)
5707 if (desc
->run
->isSideways
)
5708 analysis
->origins
[i
].y
+= advance
;
5710 analysis
->origins
[i
].x
+= advance
;
5713 /* Offsets are optional, appled to pre-transformed origin. */
5714 if (desc
->run
->glyphOffsets
) {
5715 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
;
5716 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
;
5718 if (desc
->run
->isSideways
) {
5719 analysis
->origins
[i
].x
+= ascenderoffset
;
5720 analysis
->origins
[i
].y
+= advanceoffset
;
5723 analysis
->origins
[i
].x
+= advanceoffset
;
5724 analysis
->origins
[i
].y
+= ascenderoffset
;
5728 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5729 transform_point(analysis
->origins
+ i
, &analysis
->m
);
5731 if (desc
->run
->isSideways
)
5732 origin
.y
+= advance
;
5734 origin
.x
+= advance
;
5737 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5741 /* IDWriteColorGlyphRunEnumerator1 */
5742 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator1
*iface
, REFIID riid
, void **ppv
)
5744 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
5746 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator1
) ||
5747 IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5748 IsEqualIID(riid
, &IID_IUnknown
))
5751 IDWriteColorGlyphRunEnumerator1_AddRef(iface
);
5755 WARN("%s not implemented.\n", debugstr_guid(riid
));
5758 return E_NOINTERFACE
;
5761 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator1
*iface
)
5763 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
5764 ULONG refcount
= InterlockedIncrement(&glyphenum
->refcount
);
5766 TRACE("%p, refcount %u.\n", iface
, refcount
);
5771 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator1
*iface
)
5773 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
5774 ULONG refcount
= InterlockedDecrement(&glyphenum
->refcount
);
5776 TRACE("%p, refcount %u.\n", iface
, refcount
);
5780 heap_free(glyphenum
->advances
);
5781 heap_free(glyphenum
->color_advances
);
5782 heap_free(glyphenum
->offsets
);
5783 heap_free(glyphenum
->color_offsets
);
5784 heap_free(glyphenum
->glyphindices
);
5785 heap_free(glyphenum
->glyphs
);
5786 if (glyphenum
->colr
.context
)
5787 IDWriteFontFace5_ReleaseFontTable(glyphenum
->fontface
, glyphenum
->colr
.context
);
5788 IDWriteFontFace5_Release(glyphenum
->fontface
);
5789 heap_free(glyphenum
);
5795 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5797 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5798 FLOAT origin
= 0.0f
;
5804 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5808 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5810 DWRITE_COLOR_GLYPH_RUN1
*colorrun
= &glyphenum
->colorrun
;
5811 FLOAT advance_adj
= 0.0f
;
5812 BOOL got_palette_index
;
5815 /* start with regular glyphs */
5816 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5817 UINT32 first_glyph
= 0;
5819 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5820 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5821 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5822 first_glyph
= min(first_glyph
, g
);
5825 glyphenum
->glyphindices
[g
] = 1;
5826 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5827 if (glyphenum
->color_offsets
)
5828 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5831 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5832 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5833 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5834 colorrun
->paletteIndex
= 0xffff;
5835 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5836 glyphenum
->has_regular_glyphs
= FALSE
;
5840 colorrun
->glyphRun
.glyphCount
= 0;
5841 got_palette_index
= FALSE
;
5845 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5847 glyphenum
->glyphindices
[g
] = 1;
5849 /* all glyph layers were returned */
5850 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5851 advance_adj
+= glyphenum
->advances
[g
];
5855 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5856 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5857 if (!got_palette_index
) {
5858 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5859 /* use foreground color or request one from the font */
5860 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5861 if (colorrun
->paletteIndex
!= 0xffff)
5863 HRESULT hr
= IDWriteFontFace5_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
,
5864 colorrun
->paletteIndex
, 1, &colorrun
->runColor
);
5866 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5867 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5869 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5870 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5871 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5872 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5873 got_palette_index
= TRUE
;
5876 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5877 /* offsets are relative to glyph origin, nothing to fix up */
5878 if (glyphenum
->color_offsets
)
5879 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5880 opentype_colr_next_glyph(&glyphenum
->colr
, glyphenum
->glyphs
+ g
);
5882 glyphenum
->color_advances
[index
-1] += advance_adj
;
5883 colorrun
->glyphRun
.glyphCount
++;
5887 advance_adj
+= glyphenum
->advances
[g
];
5890 /* reset last advance */
5891 if (colorrun
->glyphRun
.glyphCount
)
5892 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5894 return colorrun
->glyphRun
.glyphCount
> 0;
5897 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator1
*iface
, BOOL
*has_run
)
5899 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
5901 TRACE("%p, %p.\n", iface
, has_run
);
5905 glyphenum
->colorrun
.glyphRun
.glyphCount
= 0;
5906 while (glyphenum
->current_layer
< glyphenum
->max_layer_num
)
5908 if (colorglyphenum_build_color_run(glyphenum
))
5911 glyphenum
->current_layer
++;
5914 *has_run
= glyphenum
->colorrun
.glyphRun
.glyphCount
> 0;
5919 static HRESULT
colorglyphenum_get_current_run(const struct dwrite_colorglyphenum
*glyphenum
,
5920 DWRITE_COLOR_GLYPH_RUN1
const **run
)
5922 if (glyphenum
->colorrun
.glyphRun
.glyphCount
== 0)
5925 return E_NOT_VALID_STATE
;
5928 *run
= &glyphenum
->colorrun
;
5932 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
5933 DWRITE_COLOR_GLYPH_RUN
const **run
)
5935 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
5937 TRACE("%p, %p.\n", iface
, run
);
5939 return colorglyphenum_get_current_run(glyphenum
, (DWRITE_COLOR_GLYPH_RUN1
const **)run
);
5942 static HRESULT WINAPI
colorglyphenum1_GetCurrentRun(IDWriteColorGlyphRunEnumerator1
*iface
,
5943 DWRITE_COLOR_GLYPH_RUN1
const **run
)
5945 struct dwrite_colorglyphenum
*glyphenum
= impl_from_IDWriteColorGlyphRunEnumerator1(iface
);
5947 TRACE("%p, %p.\n", iface
, run
);
5949 return colorglyphenum_get_current_run(glyphenum
, run
);
5952 static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl
=
5954 colorglyphenum_QueryInterface
,
5955 colorglyphenum_AddRef
,
5956 colorglyphenum_Release
,
5957 colorglyphenum_MoveNext
,
5958 colorglyphenum_GetCurrentRun
,
5959 colorglyphenum1_GetCurrentRun
,
5962 HRESULT
create_colorglyphenum(float originX
, float originY
, const DWRITE_GLYPH_RUN
*run
,
5963 const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
, DWRITE_MEASURING_MODE measuring_mode
,
5964 const DWRITE_MATRIX
*transform
, unsigned int palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5966 struct dwrite_colorglyphenum
*colorglyphenum
;
5967 BOOL colorfont
, has_colored_glyph
;
5968 struct dwrite_fontface
*fontface
;
5973 fontface
= unsafe_impl_from_IDWriteFontFace(run
->fontFace
);
5975 colorfont
= IDWriteFontFace5_IsColorFont(&fontface
->IDWriteFontFace5_iface
) &&
5976 IDWriteFontFace5_GetColorPaletteCount(&fontface
->IDWriteFontFace5_iface
) > palette
;
5978 return DWRITE_E_NOCOLOR
;
5980 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5981 if (!colorglyphenum
)
5982 return E_OUTOFMEMORY
;
5984 colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
.lpVtbl
= &colorglyphenumvtbl
;
5985 colorglyphenum
->refcount
= 1;
5986 colorglyphenum
->origin_x
= originX
;
5987 colorglyphenum
->origin_y
= originY
;
5988 colorglyphenum
->fontface
= &fontface
->IDWriteFontFace5_iface
;
5989 IDWriteFontFace5_AddRef(colorglyphenum
->fontface
);
5990 colorglyphenum
->glyphs
= NULL
;
5991 colorglyphenum
->run
= *run
;
5992 colorglyphenum
->run
.glyphIndices
= NULL
;
5993 colorglyphenum
->run
.glyphAdvances
= NULL
;
5994 colorglyphenum
->run
.glyphOffsets
= NULL
;
5995 colorglyphenum
->palette
= palette
;
5996 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5997 colorglyphenum
->colr
.exists
= TRUE
;
5998 get_fontface_table(&fontface
->IDWriteFontFace5_iface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5999 colorglyphenum
->current_layer
= 0;
6000 colorglyphenum
->max_layer_num
= 0;
6002 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
6004 has_colored_glyph
= FALSE
;
6005 colorglyphenum
->has_regular_glyphs
= FALSE
;
6006 for (i
= 0; i
< run
->glyphCount
; i
++) {
6007 if (opentype_get_colr_glyph(&colorglyphenum
->colr
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
6008 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
6009 has_colored_glyph
= TRUE
;
6011 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
6012 colorglyphenum
->has_regular_glyphs
= TRUE
;
6015 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
6016 is supposed to proceed normally, like if font had no color info at all. */
6017 if (!has_colored_glyph
) {
6018 IDWriteColorGlyphRunEnumerator1_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
);
6019 return DWRITE_E_NOCOLOR
;
6022 colorglyphenum
->advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->advances
));
6023 colorglyphenum
->color_advances
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_advances
));
6024 colorglyphenum
->glyphindices
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->glyphindices
));
6025 if (run
->glyphOffsets
) {
6026 colorglyphenum
->offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->offsets
));
6027 colorglyphenum
->color_offsets
= heap_calloc(run
->glyphCount
, sizeof(*colorglyphenum
->color_offsets
));
6028 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
6031 colorglyphenum
->colorrun
.glyphRun
.fontFace
= run
->fontFace
;
6032 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
6033 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
6034 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
6035 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
6036 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
6037 colorglyphenum
->colorrun
.measuringMode
= measuring_mode
;
6038 colorglyphenum
->colorrun
.glyphImageFormat
= DWRITE_GLYPH_IMAGE_FORMATS_NONE
; /* FIXME */
6040 if (run
->glyphAdvances
)
6041 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
6044 for (i
= 0; i
< run
->glyphCount
; ++i
)
6045 colorglyphenum
->advances
[i
] = fontface_get_scaled_design_advance(fontface
, measuring_mode
,
6046 run
->fontEmSize
, 1.0f
, transform
, run
->glyphIndices
[i
], run
->isSideways
);
6049 *ret
= (IDWriteColorGlyphRunEnumerator
*)&colorglyphenum
->IDWriteColorGlyphRunEnumerator1_iface
;
6054 /* IDWriteFontFaceReference */
6055 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference1
*iface
, REFIID riid
, void **obj
)
6057 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6059 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference1
) ||
6060 IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) ||
6061 IsEqualIID(riid
, &IID_IUnknown
))
6064 IDWriteFontFaceReference1_AddRef(iface
);
6068 WARN("%s not implemented.\n", debugstr_guid(riid
));
6072 return E_NOINTERFACE
;
6075 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference1
*iface
)
6077 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6078 ULONG refcount
= InterlockedIncrement(&reference
->refcount
);
6080 TRACE("%p, refcount %u.\n", iface
, refcount
);
6085 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference1
*iface
)
6087 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6088 ULONG refcount
= InterlockedDecrement(&reference
->refcount
);
6090 TRACE("%p, refcount %u.\n", iface
, refcount
);
6094 IDWriteFontFile_Release(reference
->file
);
6095 IDWriteFactory7_Release(reference
->factory
);
6096 heap_free(reference
->axis_values
);
6097 heap_free(reference
);
6103 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace3
**fontface
)
6105 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6107 TRACE("%p, %p.\n", iface
, fontface
);
6109 return IDWriteFontFaceReference1_CreateFontFaceWithSimulations(iface
, reference
->simulations
, fontface
);
6112 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference1
*iface
,
6113 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
6115 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6116 DWRITE_FONT_FILE_TYPE file_type
;
6117 DWRITE_FONT_FACE_TYPE face_type
;
6118 IDWriteFontFace
*fontface
;
6123 TRACE("%p, %#x, %p.\n", iface
, simulations
, ret
);
6125 hr
= IDWriteFontFile_Analyze(reference
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
6129 hr
= IDWriteFactory7_CreateFontFace(reference
->factory
, face_type
, 1, &reference
->file
, reference
->index
,
6130 simulations
, &fontface
);
6133 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
6134 IDWriteFontFace_Release(fontface
);
6140 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference1
*iface
, IDWriteFontFaceReference
*ref
)
6142 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6143 struct dwrite_fontfacereference
*other
= unsafe_impl_from_IDWriteFontFaceReference(ref
);
6146 TRACE("%p, %p.\n", iface
, ref
);
6148 ret
= is_same_fontfile(reference
->file
, other
->file
) && reference
->index
== other
->index
&&
6149 reference
->simulations
== other
->simulations
;
6150 if (reference
->axis_values_count
)
6152 ret
&= reference
->axis_values_count
== other
->axis_values_count
&&
6153 !memcmp(reference
->axis_values
, other
->axis_values
, reference
->axis_values_count
* sizeof(*reference
->axis_values
));
6159 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference1
*iface
)
6161 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6163 TRACE("%p.\n", iface
);
6165 return reference
->index
;
6168 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference1
*iface
)
6170 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6172 TRACE("%p.\n", iface
);
6174 return reference
->simulations
;
6177 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference1
*iface
, IDWriteFontFile
**file
)
6179 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6180 IDWriteFontFileLoader
*loader
;
6185 TRACE("%p, %p.\n", iface
, file
);
6187 hr
= IDWriteFontFile_GetReferenceKey(reference
->file
, &key
, &key_size
);
6191 hr
= IDWriteFontFile_GetLoader(reference
->file
, &loader
);
6195 hr
= IDWriteFactory7_CreateCustomFontFileReference(reference
->factory
, key
, key_size
, loader
, file
);
6196 IDWriteFontFileLoader_Release(loader
);
6201 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference1
*iface
)
6203 FIXME("%p.\n", iface
);
6208 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference1
*iface
)
6210 FIXME("%p.\n", iface
);
6215 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference1
*iface
, FILETIME
*writetime
)
6217 FIXME("%p, %p.\n", iface
, writetime
);
6222 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference1
*iface
)
6224 FIXME("%p.\n", iface
);
6226 return DWRITE_LOCALITY_LOCAL
;
6229 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference1
*iface
)
6231 FIXME("%p.\n", iface
);
6236 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference1
*iface
,
6237 WCHAR
const *chars
, UINT32 count
)
6239 FIXME("%p, %s, %u.\n", iface
, debugstr_wn(chars
, count
), count
);
6244 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference1
*iface
,
6245 UINT16
const *glyphs
, UINT32 count
)
6247 FIXME("%p, %p, %u.\n", iface
, glyphs
, count
);
6252 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference1
*iface
,
6253 UINT64 offset
, UINT64 size
)
6255 FIXME("%p, 0x%s, 0x%s.\n", iface
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
6260 static HRESULT WINAPI
fontfacereference1_CreateFontFace(IDWriteFontFaceReference1
*iface
, IDWriteFontFace5
**fontface
)
6262 FIXME("%p, %p.\n", iface
, fontface
);
6267 static UINT32 WINAPI
fontfacereference1_GetFontAxisValueCount(IDWriteFontFaceReference1
*iface
)
6269 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6271 TRACE("%p.\n", iface
);
6273 return reference
->axis_values_count
;
6276 static HRESULT WINAPI
fontfacereference1_GetFontAxisValues(IDWriteFontFaceReference1
*iface
,
6277 DWRITE_FONT_AXIS_VALUE
*axis_values
, UINT32 value_count
)
6279 struct dwrite_fontfacereference
*reference
= impl_from_IDWriteFontFaceReference1(iface
);
6281 TRACE("%p, %p, %u.\n", iface
, axis_values
, value_count
);
6283 if (value_count
< reference
->axis_values_count
)
6284 return E_NOT_SUFFICIENT_BUFFER
;
6286 memcpy(axis_values
, reference
->axis_values
, value_count
* sizeof(*axis_values
));
6291 static const IDWriteFontFaceReference1Vtbl fontfacereferencevtbl
=
6293 fontfacereference_QueryInterface
,
6294 fontfacereference_AddRef
,
6295 fontfacereference_Release
,
6296 fontfacereference_CreateFontFace
,
6297 fontfacereference_CreateFontFaceWithSimulations
,
6298 fontfacereference_Equals
,
6299 fontfacereference_GetFontFaceIndex
,
6300 fontfacereference_GetSimulations
,
6301 fontfacereference_GetFontFile
,
6302 fontfacereference_GetLocalFileSize
,
6303 fontfacereference_GetFileSize
,
6304 fontfacereference_GetFileTime
,
6305 fontfacereference_GetLocality
,
6306 fontfacereference_EnqueueFontDownloadRequest
,
6307 fontfacereference_EnqueueCharacterDownloadRequest
,
6308 fontfacereference_EnqueueGlyphDownloadRequest
,
6309 fontfacereference_EnqueueFileFragmentDownloadRequest
,
6310 fontfacereference1_CreateFontFace
,
6311 fontfacereference1_GetFontAxisValueCount
,
6312 fontfacereference1_GetFontAxisValues
,
6315 HRESULT
create_fontfacereference(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 index
,
6316 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 axis_values_count
,
6317 IDWriteFontFaceReference1
**ret
)
6319 struct dwrite_fontfacereference
*object
;
6323 if (!is_simulation_valid(simulations
))
6324 return E_INVALIDARG
;
6326 object
= heap_alloc_zero(sizeof(*object
));
6328 return E_OUTOFMEMORY
;
6330 object
->IDWriteFontFaceReference1_iface
.lpVtbl
= &fontfacereferencevtbl
;
6331 object
->refcount
= 1;
6333 object
->factory
= factory
;
6334 IDWriteFactory7_AddRef(object
->factory
);
6335 object
->file
= file
;
6336 IDWriteFontFile_AddRef(object
->file
);
6337 object
->index
= index
;
6338 object
->simulations
= simulations
;
6339 if (axis_values_count
)
6341 if (!(object
->axis_values
= heap_alloc(axis_values_count
* sizeof(*axis_values
))))
6343 IDWriteFontFaceReference1_Release(&object
->IDWriteFontFaceReference1_iface
);
6344 return E_OUTOFMEMORY
;
6346 memcpy(object
->axis_values
, axis_values
, axis_values_count
* sizeof(*axis_values
));
6347 object
->axis_values_count
= axis_values_count
;
6350 *ret
= &object
->IDWriteFontFaceReference1_iface
;
6355 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6357 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6359 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6361 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6363 IDWriteFontFileStream_AddRef(iface
);
6369 WARN("%s not implemented.\n", debugstr_guid(riid
));
6370 return E_NOINTERFACE
;
6373 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6375 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6376 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6377 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6381 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6383 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6384 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6386 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6389 release_inmemory_stream(stream
->data
);
6396 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6397 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6399 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6401 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6402 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6404 *fragment_context
= NULL
;
6406 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6407 *fragment_start
= NULL
;
6411 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6415 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6417 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6419 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6422 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6424 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6426 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6428 *size
= stream
->data
->size
;
6433 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6435 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6437 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6439 *last_writetime
= 0;
6444 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6445 inmemoryfilestream_QueryInterface
,
6446 inmemoryfilestream_AddRef
,
6447 inmemoryfilestream_Release
,
6448 inmemoryfilestream_ReadFileFragment
,
6449 inmemoryfilestream_ReleaseFileFragment
,
6450 inmemoryfilestream_GetFileSize
,
6451 inmemoryfilestream_GetLastWriteTime
,
6454 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6455 REFIID riid
, void **obj
)
6457 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6459 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6461 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6462 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6463 IsEqualIID(riid
, &IID_IUnknown
))
6466 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6470 WARN("%s not implemented.\n", debugstr_guid(riid
));
6474 return E_NOINTERFACE
;
6477 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6479 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6480 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6481 TRACE("(%p)->(%u)\n", loader
, ref
);
6485 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6487 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6488 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6491 TRACE("(%p)->(%u)\n", loader
, ref
);
6494 for (i
= 0; i
< loader
->count
; ++i
)
6495 release_inmemory_stream(loader
->streams
[i
]);
6496 heap_free(loader
->streams
);
6503 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6504 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6506 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6507 struct dwrite_inmemory_filestream
*stream
;
6510 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6514 if (key_size
!= sizeof(DWORD
))
6515 return E_INVALIDARG
;
6517 index
= *(DWORD
*)key
;
6519 if (index
>= loader
->count
)
6520 return E_INVALIDARG
;
6522 if (!(stream
= heap_alloc(sizeof(*stream
))))
6523 return E_OUTOFMEMORY
;
6525 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6527 stream
->data
= loader
->streams
[index
];
6528 InterlockedIncrement(&stream
->data
->ref
);
6530 *ret
= &stream
->IDWriteFontFileStream_iface
;
6535 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6536 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6538 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6539 struct dwrite_inmemory_stream_data
*stream
;
6542 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6546 if (!dwrite_array_reserve((void **)&loader
->streams
, &loader
->size
, loader
->count
+ 1, sizeof(*loader
->streams
)))
6547 return E_OUTOFMEMORY
;
6549 if (!(stream
= heap_alloc(sizeof(*stream
))))
6550 return E_OUTOFMEMORY
;
6553 stream
->size
= data_size
;
6554 stream
->owner
= owner
;
6555 if (stream
->owner
) {
6556 IUnknown_AddRef(stream
->owner
);
6557 stream
->data
= (void *)data
;
6560 if (!(stream
->data
= heap_alloc(data_size
))) {
6562 return E_OUTOFMEMORY
;
6564 memcpy(stream
->data
, data
, data_size
);
6567 key
= loader
->count
;
6568 loader
->streams
[loader
->count
++] = stream
;
6570 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6571 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6574 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6576 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6578 TRACE("%p.\n", iface
);
6580 return loader
->count
;
6583 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6585 inmemoryfontfileloader_QueryInterface
,
6586 inmemoryfontfileloader_AddRef
,
6587 inmemoryfontfileloader_Release
,
6588 inmemoryfontfileloader_CreateStreamFromKey
,
6589 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6590 inmemoryfontfileloader_GetFileCount
,
6593 HRESULT
create_inmemory_fileloader(IDWriteFontFileLoader
**ret
)
6595 struct dwrite_inmemory_fileloader
*loader
;
6599 loader
= heap_alloc_zero(sizeof(*loader
));
6601 return E_OUTOFMEMORY
;
6603 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6606 *ret
= (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
;
6611 static HRESULT WINAPI
dwritefontresource_QueryInterface(IDWriteFontResource
*iface
, REFIID riid
, void **obj
)
6613 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
6615 if (IsEqualIID(riid
, &IID_IDWriteFontResource
) ||
6616 IsEqualIID(riid
, &IID_IUnknown
))
6619 IDWriteFontResource_AddRef(iface
);
6623 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
6625 return E_NOINTERFACE
;
6628 static ULONG WINAPI
dwritefontresource_AddRef(IDWriteFontResource
*iface
)
6630 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6631 ULONG refcount
= InterlockedIncrement(&resource
->refcount
);
6633 TRACE("%p, refcount %u.\n", iface
, refcount
);
6638 static ULONG WINAPI
dwritefontresource_Release(IDWriteFontResource
*iface
)
6640 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6641 ULONG refcount
= InterlockedDecrement(&resource
->refcount
);
6643 TRACE("%p, refcount %u.\n", iface
, refcount
);
6647 IDWriteFactory7_Release(resource
->factory
);
6648 IDWriteFontFile_Release(resource
->file
);
6649 heap_free(resource
);
6655 static HRESULT WINAPI
dwritefontresource_GetFontFile(IDWriteFontResource
*iface
, IDWriteFontFile
**fontfile
)
6657 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6659 TRACE("%p, %p.\n", iface
, fontfile
);
6661 *fontfile
= resource
->file
;
6662 IDWriteFontFile_AddRef(*fontfile
);
6667 static UINT32 WINAPI
dwritefontresource_GetFontFaceIndex(IDWriteFontResource
*iface
)
6669 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6671 TRACE("%p.\n", iface
);
6673 return resource
->face_index
;
6676 static UINT32 WINAPI
dwritefontresource_GetFontAxisCount(IDWriteFontResource
*iface
)
6678 FIXME("%p.\n", iface
);
6683 static HRESULT WINAPI
dwritefontresource_GetDefaultFontAxisValues(IDWriteFontResource
*iface
,
6684 DWRITE_FONT_AXIS_VALUE
const *values
, UINT32 num_values
)
6686 FIXME("%p, %p, %u.\n", iface
, values
, num_values
);
6691 static HRESULT WINAPI
dwritefontresource_GetFontAxisRanges(IDWriteFontResource
*iface
,
6692 DWRITE_FONT_AXIS_RANGE
const *ranges
, UINT32 num_ranges
)
6694 FIXME("%p, %p, %u.\n", iface
, ranges
, num_ranges
);
6699 static DWRITE_FONT_AXIS_ATTRIBUTES WINAPI
dwritefontresource_GetFontAxisAttributes(IDWriteFontResource
*iface
,
6702 FIXME("%p, %u.\n", iface
, axis
);
6704 return DWRITE_FONT_AXIS_ATTRIBUTES_NONE
;
6707 static HRESULT WINAPI
dwritefontresource_GetAxisNames(IDWriteFontResource
*iface
, UINT32 axis
,
6708 IDWriteLocalizedStrings
**names
)
6710 FIXME("%p, %u, %p.\n", iface
, axis
, names
);
6715 static UINT32 WINAPI
dwritefontresource_GetAxisValueNameCount(IDWriteFontResource
*iface
, UINT32 axis
)
6717 FIXME("%p, %u.\n", iface
, axis
);
6722 static HRESULT WINAPI
dwritefontresource_GetAxisValueNames(IDWriteFontResource
*iface
, UINT32 axis
,
6723 UINT32 axis_value
, DWRITE_FONT_AXIS_RANGE
*axis_range
, IDWriteLocalizedStrings
**names
)
6725 FIXME("%p, %u, %u, %p, %p.\n", iface
, axis
, axis_value
, axis_range
, names
);
6730 static BOOL WINAPI
dwritefontresource_HasVariations(IDWriteFontResource
*iface
)
6732 FIXME("%p.\n", iface
);
6737 static HRESULT WINAPI
dwritefontresource_CreateFontFace(IDWriteFontResource
*iface
,
6738 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
6739 IDWriteFontFace5
**fontface
)
6741 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6742 IDWriteFontFaceReference1
*reference
;
6745 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, fontface
);
6747 hr
= IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
6748 simulations
, axis_values
, num_values
, &reference
);
6751 hr
= IDWriteFontFaceReference1_CreateFontFace(reference
, fontface
);
6752 IDWriteFontFaceReference1_Release(reference
);
6758 static HRESULT WINAPI
dwritefontresource_CreateFontFaceReference(IDWriteFontResource
*iface
,
6759 DWRITE_FONT_SIMULATIONS simulations
, DWRITE_FONT_AXIS_VALUE
const *axis_values
, UINT32 num_values
,
6760 IDWriteFontFaceReference1
**reference
)
6762 struct dwrite_fontresource
*resource
= impl_from_IDWriteFontResource(iface
);
6764 TRACE("%p, %#x, %p, %u, %p.\n", iface
, simulations
, axis_values
, num_values
, reference
);
6766 return IDWriteFactory7_CreateFontFaceReference(resource
->factory
, resource
->file
, resource
->face_index
,
6767 simulations
, axis_values
, num_values
, reference
);
6770 static const IDWriteFontResourceVtbl fontresourcevtbl
=
6772 dwritefontresource_QueryInterface
,
6773 dwritefontresource_AddRef
,
6774 dwritefontresource_Release
,
6775 dwritefontresource_GetFontFile
,
6776 dwritefontresource_GetFontFaceIndex
,
6777 dwritefontresource_GetFontAxisCount
,
6778 dwritefontresource_GetDefaultFontAxisValues
,
6779 dwritefontresource_GetFontAxisRanges
,
6780 dwritefontresource_GetFontAxisAttributes
,
6781 dwritefontresource_GetAxisNames
,
6782 dwritefontresource_GetAxisValueNameCount
,
6783 dwritefontresource_GetAxisValueNames
,
6784 dwritefontresource_HasVariations
,
6785 dwritefontresource_CreateFontFace
,
6786 dwritefontresource_CreateFontFaceReference
,
6789 HRESULT
create_font_resource(IDWriteFactory7
*factory
, IDWriteFontFile
*file
, UINT32 face_index
,
6790 IDWriteFontResource
**ret
)
6792 struct dwrite_fontresource
*resource
;
6796 resource
= heap_alloc_zero(sizeof(*resource
));
6798 return E_OUTOFMEMORY
;
6800 resource
->IDWriteFontResource_iface
.lpVtbl
= &fontresourcevtbl
;
6801 resource
->refcount
= 1;
6802 resource
->face_index
= face_index
;
6803 resource
->file
= file
;
6804 IDWriteFontFile_AddRef(resource
->file
);
6805 resource
->factory
= factory
;
6806 IDWriteFactory7_AddRef(resource
->factory
);
6808 *ret
= &resource
->IDWriteFontResource_iface
;