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
{
75 DWRITE_FONT_STYLE style
;
76 DWRITE_FONT_STRETCH stretch
;
77 DWRITE_FONT_WEIGHT weight
;
79 struct dwrite_font_propvec propvec
;
81 DWRITE_FONT_METRICS1 metrics
;
82 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
83 IDWriteLocalizedStrings
*names
;
85 /* data needed to create fontface instance */
86 DWRITE_FONT_FACE_TYPE face_type
;
87 IDWriteFontFile
*file
;
96 /* used to mark font as tested when scanning for simulation candidate */
97 BOOL bold_sim_tested
: 1;
98 BOOL oblique_sim_tested
: 1;
101 struct dwrite_fontfamily_data
{
104 IDWriteLocalizedStrings
*familyname
;
106 struct dwrite_font_data
**fonts
;
109 BOOL has_normal_face
: 1;
110 BOOL has_oblique_face
: 1;
111 BOOL has_italic_face
: 1;
114 struct dwrite_fontcollection
{
115 IDWriteFontCollection1 IDWriteFontCollection1_iface
;
118 IDWriteFactory5
*factory
;
119 struct dwrite_fontfamily_data
**family_data
;
124 struct dwrite_fontfamily
{
125 IDWriteFontFamily1 IDWriteFontFamily1_iface
;
128 struct dwrite_fontfamily_data
*data
;
129 struct dwrite_fontcollection
*collection
;
132 struct dwrite_fontlist
{
133 IDWriteFontList1 IDWriteFontList1_iface
;
136 struct dwrite_font_data
**fonts
;
138 struct dwrite_fontfamily
*family
;
142 IDWriteFont3 IDWriteFont3_iface
;
145 DWRITE_FONT_STYLE style
;
146 struct dwrite_font_data
*data
;
147 struct dwrite_fontfamily
*family
;
150 struct dwrite_fonttable
{
157 enum runanalysis_flags
{
158 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
159 RUNANALYSIS_BITMAP_READY
= 1 << 1,
160 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
163 struct dwrite_glyphrunanalysis
{
164 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
167 DWRITE_RENDERING_MODE1 rendering_mode
;
168 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
169 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
172 D2D_POINT_2F
*origins
;
177 UINT32 max_glyph_bitmap_size
;
180 struct dwrite_colorglyphenum
{
181 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
184 FLOAT origin_x
; /* original run origin */
187 IDWriteFontFace4
*fontface
; /* for convenience */
188 DWRITE_COLOR_GLYPH_RUN colorrun
; /* returned with GetCurrentRun() */
189 DWRITE_GLYPH_RUN run
; /* base run */
190 UINT32 palette
; /* palette index to get layer color from */
191 FLOAT
*advances
; /* original or measured advances for base glyphs */
192 FLOAT
*color_advances
; /* returned color run points to this */
193 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
194 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
195 UINT16
*glyphindices
; /* returned color run points to this */
196 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
197 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
198 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
199 UINT16 max_layer_num
; /* max number of layers for this run */
200 struct dwrite_fonttable colr
; /* used to access layers */
203 #define GLYPH_BLOCK_SHIFT 8
204 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
205 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
206 #define GLYPH_MAX 65536
208 enum fontface_flags
{
209 FONTFACE_IS_SYMBOL
= 1 << 0,
210 FONTFACE_IS_MONOSPACED
= 1 << 1,
211 FONTFACE_HAS_KERNING_PAIRS
= 1 << 2,
212 FONTFACE_HAS_VERTICAL_VARIANTS
= 1 << 3
215 struct dwrite_fontface
{
216 IDWriteFontFace4 IDWriteFontFace4_iface
;
219 IDWriteFontFileStream
**streams
;
220 IDWriteFontFile
**files
;
224 IDWriteFactory5
*factory
;
225 struct fontfacecached
*cached
;
228 DWRITE_FONT_FACE_TYPE type
;
229 DWRITE_FONT_METRICS1 metrics
;
230 DWRITE_CARET_METRICS caret
;
234 struct dwrite_fonttable cmap
;
235 struct dwrite_fonttable vdmx
;
236 struct dwrite_fonttable gasp
;
237 struct dwrite_fonttable cpal
;
238 struct dwrite_fonttable colr
;
239 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
241 DWRITE_FONT_STYLE style
;
242 DWRITE_FONT_STRETCH stretch
;
243 DWRITE_FONT_WEIGHT weight
;
244 DWRITE_PANOSE panose
;
245 UINT32 glyph_image_formats
;
250 struct dwrite_fontfile
{
251 IDWriteFontFile IDWriteFontFile_iface
;
254 IDWriteFontFileLoader
*loader
;
257 IDWriteFontFileStream
*stream
;
260 struct dwrite_fontfacereference
{
261 IDWriteFontFaceReference IDWriteFontFaceReference_iface
;
264 IDWriteFontFile
*file
;
267 IDWriteFactory5
*factory
;
270 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace4(IDWriteFontFace4
*iface
)
272 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace4_iface
);
275 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
277 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
280 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
282 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
285 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
287 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
290 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection1(IDWriteFontCollection1
*iface
)
292 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection1_iface
);
295 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
297 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
300 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
302 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
305 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList1(IDWriteFontList1
*iface
)
307 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList1_iface
);
310 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
312 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference_iface
);
315 static inline const char *debugstr_tag(UINT32 tag
)
317 return debugstr_an((char*)&tag
, 4);
320 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
322 static const DWRITE_GLYPH_METRICS nil
;
323 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
325 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
326 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
330 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
332 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
335 /* start new block */
336 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
338 return E_OUTOFMEMORY
;
341 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
345 static void* get_fontface_table(IDWriteFontFace4
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
349 if (table
->data
|| !table
->exists
)
352 table
->exists
= FALSE
;
353 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
355 if (FAILED(hr
) || !table
->exists
) {
356 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
363 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
364 struct dwrite_font_propvec
*vec
)
366 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
367 vec
->style
= style
* 7.0f
;
368 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
371 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
373 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
376 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
378 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
381 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
383 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
386 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
388 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
391 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
393 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_GASP_TAG
, &fontface
->gasp
);
394 *size
= fontface
->gasp
.size
;
398 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
400 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
403 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
405 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_COLR_TAG
, &fontface
->colr
);
408 static void addref_font_data(struct dwrite_font_data
*data
)
410 InterlockedIncrement(&data
->ref
);
413 static void release_font_data(struct dwrite_font_data
*data
)
417 if (InterlockedDecrement(&data
->ref
) > 0)
420 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
421 if (data
->info_strings
[i
])
422 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
425 IDWriteLocalizedStrings_Release(data
->names
);
427 IDWriteFontFile_Release(data
->file
);
428 heap_free(data
->facename
);
432 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
436 if (InterlockedDecrement(&data
->ref
) > 0)
439 for (i
= 0; i
< data
->font_count
; i
++)
440 release_font_data(data
->fonts
[i
]);
441 heap_free(data
->fonts
);
442 IDWriteLocalizedStrings_Release(data
->familyname
);
446 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace4
*iface
, REFIID riid
, void **obj
)
448 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
450 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
452 if (IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
453 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
454 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
455 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
456 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
457 IsEqualIID(riid
, &IID_IUnknown
))
460 IDWriteFontFace4_AddRef(iface
);
465 return E_NOINTERFACE
;
468 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace4
*iface
)
470 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
471 ULONG ref
= InterlockedIncrement(&This
->ref
);
472 TRACE("(%p)->(%d)\n", This
, ref
);
476 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace4
*iface
)
478 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
479 ULONG ref
= InterlockedDecrement(&This
->ref
);
481 TRACE("(%p)->(%d)\n", This
, ref
);
486 if (This
->cmap
.context
)
487 IDWriteFontFace4_ReleaseFontTable(iface
, This
->cmap
.context
);
488 if (This
->vdmx
.context
)
489 IDWriteFontFace4_ReleaseFontTable(iface
, This
->vdmx
.context
);
490 if (This
->gasp
.context
)
491 IDWriteFontFace4_ReleaseFontTable(iface
, This
->gasp
.context
);
492 if (This
->cpal
.context
)
493 IDWriteFontFace4_ReleaseFontTable(iface
, This
->cpal
.context
);
494 if (This
->colr
.context
)
495 IDWriteFontFace4_ReleaseFontTable(iface
, This
->colr
.context
);
496 for (i
= 0; i
< This
->file_count
; i
++) {
497 if (This
->streams
[i
])
498 IDWriteFontFileStream_Release(This
->streams
[i
]);
500 IDWriteFontFile_Release(This
->files
[i
]);
502 heap_free(This
->streams
);
503 heap_free(This
->files
);
505 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
506 heap_free(This
->glyphs
[i
]);
508 freetype_notify_cacheremove(iface
);
510 factory_release_cached_fontface(This
->cached
);
512 IDWriteFactory5_Release(This
->factory
);
519 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace4
*iface
)
521 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
522 TRACE("(%p)\n", This
);
526 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace4
*iface
, UINT32
*number_of_files
,
527 IDWriteFontFile
**fontfiles
)
529 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
532 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
533 if (fontfiles
== NULL
)
535 *number_of_files
= This
->file_count
;
538 if (*number_of_files
< This
->file_count
)
541 for (i
= 0; i
< This
->file_count
; i
++)
543 IDWriteFontFile_AddRef(This
->files
[i
]);
544 fontfiles
[i
] = This
->files
[i
];
550 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace4
*iface
)
552 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
553 TRACE("(%p)\n", This
);
557 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace4
*iface
)
559 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
560 TRACE("(%p)\n", This
);
561 return This
->simulations
;
564 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace4
*iface
)
566 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
567 TRACE("(%p)\n", This
);
568 return !!(This
->flags
& FONTFACE_IS_SYMBOL
);
571 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace4
*iface
, DWRITE_FONT_METRICS
*metrics
)
573 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
574 TRACE("(%p)->(%p)\n", This
, metrics
);
575 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
578 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace4
*iface
)
580 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
581 TRACE("(%p)\n", This
);
582 return freetype_get_glyphcount(iface
);
585 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4
*iface
,
586 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
588 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
592 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
598 FIXME("sideways metrics are not supported.\n");
600 for (i
= 0; i
< glyph_count
; i
++) {
601 DWRITE_GLYPH_METRICS metrics
;
603 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
605 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
606 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
616 static HRESULT
fontface_get_glyphs(struct dwrite_fontface
*fontface
, UINT32
const *codepoints
,
617 UINT32 count
, UINT16
*glyphs
)
623 memset(glyphs
, 0, count
* sizeof(*glyphs
));
627 freetype_get_glyphs(&fontface
->IDWriteFontFace4_iface
, fontface
->charmap
, codepoints
, count
, glyphs
);
631 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace4
*iface
, UINT32
const *codepoints
,
632 UINT32 count
, UINT16
*glyphs
)
634 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
636 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyphs
);
638 return fontface_get_glyphs(This
, codepoints
, count
, glyphs
);
641 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace4
*iface
, UINT32 table_tag
,
642 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
644 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
645 struct file_stream_desc stream_desc
;
647 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
649 stream_desc
.stream
= This
->streams
[0];
650 stream_desc
.face_type
= This
->type
;
651 stream_desc
.face_index
= This
->index
;
652 return opentype_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
655 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace4
*iface
, void *table_context
)
657 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
659 TRACE("(%p)->(%p)\n", This
, table_context
);
661 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
664 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace4
*iface
, FLOAT emSize
,
665 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
666 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
668 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
670 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
671 count
, is_sideways
, is_rtl
, sink
);
673 if (!glyphs
|| !sink
)
677 FIXME("sideways mode is not supported.\n");
679 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
682 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
683 FLOAT ppem
, WORD gasp
)
685 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
689 case DWRITE_MEASURING_MODE_NATURAL
:
691 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
692 mode
= DWRITE_RENDERING_MODE_NATURAL
;
694 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
697 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
698 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
700 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
701 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
710 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
,
711 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
713 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
718 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
721 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
725 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
726 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
729 ppem
= emSize
* ppdip
;
731 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
732 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
736 ptr
= get_fontface_gasp(This
, &size
);
737 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
738 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
742 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
743 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
745 DWRITE_FONT_METRICS1 metrics1
;
746 HRESULT hr
= IDWriteFontFace4_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
747 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
751 static inline int round_metric(FLOAT metric
)
753 return (int)floorf(metric
+ 0.5f
);
756 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
758 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
761 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
764 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT ppdip
,
765 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
766 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
768 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
769 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
770 DWRITE_MEASURING_MODE mode
;
775 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
776 glyph_count
, metrics
, is_sideways
);
778 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
779 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
781 size
= emSize
* ppdip
;
782 scale
= size
/ This
->metrics
.designUnitsPerEm
;
783 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
785 for (i
= 0; i
< glyph_count
; i
++) {
786 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
787 DWRITE_GLYPH_METRICS design
;
790 hr
= IDWriteFontFace4_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
794 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
796 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
798 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
800 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
801 SCALE_METRIC(leftSideBearing
);
802 SCALE_METRIC(rightSideBearing
);
803 SCALE_METRIC(topSideBearing
);
804 SCALE_METRIC(advanceHeight
);
805 SCALE_METRIC(bottomSideBearing
);
806 SCALE_METRIC(verticalOriginY
);
813 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace4
*iface
, DWRITE_FONT_METRICS1
*metrics
)
815 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
816 TRACE("(%p)->(%p)\n", This
, metrics
);
817 *metrics
= This
->metrics
;
820 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace4
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
821 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
823 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
824 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
825 UINT16 ascent
, descent
;
828 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
830 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
831 memset(metrics
, 0, sizeof(*metrics
));
835 em_size
*= pixels_per_dip
;
836 if (m
&& m
->m22
!= 0.0f
)
837 em_size
*= fabs(m
->m22
);
839 scale
= em_size
/ design
->designUnitsPerEm
;
840 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
841 ascent
= round_metric(design
->ascent
* scale
);
842 descent
= round_metric(design
->descent
* scale
);
845 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
846 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
847 metrics
->ascent
= round_metric(ascent
/ scale
);
848 metrics
->descent
= round_metric(descent
/ scale
);
850 SCALE_METRIC(lineGap
);
851 SCALE_METRIC(capHeight
);
852 SCALE_METRIC(xHeight
);
853 SCALE_METRIC(underlinePosition
);
854 SCALE_METRIC(underlineThickness
);
855 SCALE_METRIC(strikethroughPosition
);
856 SCALE_METRIC(strikethroughThickness
);
857 SCALE_METRIC(glyphBoxLeft
);
858 SCALE_METRIC(glyphBoxTop
);
859 SCALE_METRIC(glyphBoxRight
);
860 SCALE_METRIC(glyphBoxBottom
);
861 SCALE_METRIC(subscriptPositionX
);
862 SCALE_METRIC(subscriptPositionY
);
863 SCALE_METRIC(subscriptSizeX
);
864 SCALE_METRIC(subscriptSizeY
);
865 SCALE_METRIC(superscriptPositionX
);
866 SCALE_METRIC(superscriptPositionY
);
867 SCALE_METRIC(superscriptSizeX
);
868 SCALE_METRIC(superscriptSizeY
);
870 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
876 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace4
*iface
, DWRITE_CARET_METRICS
*metrics
)
878 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
879 TRACE("(%p)->(%p)\n", This
, metrics
);
880 *metrics
= This
->caret
;
883 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace4
*iface
, UINT32 max_count
,
884 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
886 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
888 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
891 if (max_count
&& !ranges
)
894 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
897 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace4
*iface
)
899 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
900 TRACE("(%p)\n", This
);
901 return !!(This
->flags
& FONTFACE_IS_MONOSPACED
);
904 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace4
*iface
,
905 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
907 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
908 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
911 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
914 FIXME("sideways mode not supported\n");
916 for (i
= 0; i
< glyph_count
; i
++) {
919 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
],
920 DWRITE_MEASURING_MODE_NATURAL
, &has_contours
);
922 advances
[i
] += adjustment
;
928 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace4
*iface
,
929 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
930 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
932 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
933 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
934 DWRITE_MEASURING_MODE mode
;
937 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
938 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
940 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
941 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
946 if (em_size
== 0.0f
) {
947 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
951 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
952 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
954 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
955 for (i
= 0; i
< glyph_count
; i
++) {
958 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
, &has_contours
);
960 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
+ adjustment
);
962 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
968 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace4
*iface
, UINT32 count
,
969 const UINT16
*indices
, INT32
*adjustments
)
971 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
974 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
976 if (!(indices
|| adjustments
) || !count
)
979 if (!indices
|| count
== 1) {
980 memset(adjustments
, 0, count
*sizeof(INT32
));
984 if (!(This
->flags
& FONTFACE_HAS_KERNING_PAIRS
)) {
985 memset(adjustments
, 0, count
*sizeof(INT32
));
989 for (i
= 0; i
< count
-1; i
++)
990 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
991 adjustments
[count
-1] = 0;
996 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace4
*iface
)
998 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
999 TRACE("(%p)\n", This
);
1000 return !!(This
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1003 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
,
1004 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1005 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1007 DWRITE_GRID_FIT_MODE gridfitmode
;
1008 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
1009 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1012 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace4
*iface
, UINT32 glyph_count
,
1013 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
1015 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1016 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
1020 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace4
*iface
)
1022 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1023 TRACE("(%p)\n", This
);
1024 return !!(This
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1027 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace4
*iface
)
1029 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1030 TRACE("(%p)\n", This
);
1031 return get_fontface_cpal(This
) && get_fontface_colr(This
);
1034 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace4
*iface
)
1036 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1037 TRACE("(%p)\n", This
);
1038 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
1041 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace4
*iface
)
1043 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1044 TRACE("(%p)\n", This
);
1045 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
1048 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace4
*iface
, UINT32 palette_index
,
1049 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1051 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1052 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
1053 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
1056 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
,
1057 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1058 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1059 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1061 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1066 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1067 measuringmode
, params
, renderingmode
, gridfitmode
);
1070 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1073 FIXME("sideways mode not supported\n");
1075 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1077 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1078 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1080 IDWriteRenderingParams2
*params2
;
1083 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1085 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1086 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1087 IDWriteRenderingParams2_Release(params2
);
1090 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1093 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1095 ptr
= get_fontface_gasp(This
, &size
);
1096 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1098 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1099 if (emSize
>= emthreshold
)
1100 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1102 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1105 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1106 if (emSize
>= emthreshold
)
1107 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1108 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1109 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1111 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1117 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace4
*iface
, IDWriteFontFaceReference
**ref
)
1119 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1120 FIXME("(%p)->(%p): stub\n", This
, ref
);
1124 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace4
*iface
, DWRITE_PANOSE
*panose
)
1126 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1127 TRACE("(%p)->(%p)\n", This
, panose
);
1128 *panose
= This
->panose
;
1131 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace4
*iface
)
1133 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1134 TRACE("(%p)\n", This
);
1135 return This
->weight
;
1138 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace4
*iface
)
1140 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1141 TRACE("(%p)\n", This
);
1142 return This
->stretch
;
1145 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace4
*iface
)
1147 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1148 TRACE("(%p)\n", This
);
1152 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace4
*iface
, IDWriteLocalizedStrings
**names
)
1154 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1155 FIXME("(%p)->(%p): stub\n", This
, names
);
1159 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace4
*iface
, IDWriteLocalizedStrings
**names
)
1161 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1162 FIXME("(%p)->(%p): stub\n", This
, names
);
1166 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace4
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1167 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1169 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1170 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1174 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace4
*iface
, UINT32 ch
)
1176 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1179 TRACE("(%p)->(0x%08x)\n", This
, ch
);
1182 if (FAILED(fontface_get_glyphs(This
, &ch
, 1, &index
)))
1188 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1189 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1190 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1192 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1197 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1198 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1201 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1204 FIXME("sideways mode not supported\n");
1206 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1208 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1209 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1211 IDWriteRenderingParams3
*params3
;
1214 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1216 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1217 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1218 IDWriteRenderingParams3_Release(params3
);
1221 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1224 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1226 ptr
= get_fontface_gasp(This
, &size
);
1227 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1229 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1230 if (emSize
>= emthreshold
)
1231 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1233 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, gasp
);
1236 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1237 if (emSize
>= emthreshold
)
1238 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1239 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1240 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1242 *gridfit_mode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1248 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace4
*iface
, UINT32 ch
)
1250 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1251 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1255 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace4
*iface
, UINT16 glyph
)
1257 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1258 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1262 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace4
*iface
, WCHAR
const *text
,
1263 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1265 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1266 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1270 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace4
*iface
, UINT16
const *glyphs
,
1271 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1273 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1274 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1278 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace4
*iface
, UINT16 glyph
,
1279 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1281 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1282 FIXME("(%p)->(%u %u %u %p): stub\n", This
, glyph
, ppem_first
, ppem_last
, formats
);
1286 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace4
*iface
)
1288 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1290 TRACE("(%p)\n", This
);
1292 return This
->glyph_image_formats
;
1295 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace4
*iface
, UINT16 glyph
,
1296 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1298 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1299 FIXME("(%p)->(%u %u %d %p %p): stub\n", This
, glyph
, ppem
, format
, data
, context
);
1303 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace4
*iface
, void *context
)
1305 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1306 FIXME("(%p)->(%p): stub\n", This
, context
);
1309 static const IDWriteFontFace4Vtbl dwritefontfacevtbl
= {
1310 dwritefontface_QueryInterface
,
1311 dwritefontface_AddRef
,
1312 dwritefontface_Release
,
1313 dwritefontface_GetType
,
1314 dwritefontface_GetFiles
,
1315 dwritefontface_GetIndex
,
1316 dwritefontface_GetSimulations
,
1317 dwritefontface_IsSymbolFont
,
1318 dwritefontface_GetMetrics
,
1319 dwritefontface_GetGlyphCount
,
1320 dwritefontface_GetDesignGlyphMetrics
,
1321 dwritefontface_GetGlyphIndices
,
1322 dwritefontface_TryGetFontTable
,
1323 dwritefontface_ReleaseFontTable
,
1324 dwritefontface_GetGlyphRunOutline
,
1325 dwritefontface_GetRecommendedRenderingMode
,
1326 dwritefontface_GetGdiCompatibleMetrics
,
1327 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1328 dwritefontface1_GetMetrics
,
1329 dwritefontface1_GetGdiCompatibleMetrics
,
1330 dwritefontface1_GetCaretMetrics
,
1331 dwritefontface1_GetUnicodeRanges
,
1332 dwritefontface1_IsMonospacedFont
,
1333 dwritefontface1_GetDesignGlyphAdvances
,
1334 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1335 dwritefontface1_GetKerningPairAdjustments
,
1336 dwritefontface1_HasKerningPairs
,
1337 dwritefontface1_GetRecommendedRenderingMode
,
1338 dwritefontface1_GetVerticalGlyphVariants
,
1339 dwritefontface1_HasVerticalGlyphVariants
,
1340 dwritefontface2_IsColorFont
,
1341 dwritefontface2_GetColorPaletteCount
,
1342 dwritefontface2_GetPaletteEntryCount
,
1343 dwritefontface2_GetPaletteEntries
,
1344 dwritefontface2_GetRecommendedRenderingMode
,
1345 dwritefontface3_GetFontFaceReference
,
1346 dwritefontface3_GetPanose
,
1347 dwritefontface3_GetWeight
,
1348 dwritefontface3_GetStretch
,
1349 dwritefontface3_GetStyle
,
1350 dwritefontface3_GetFamilyNames
,
1351 dwritefontface3_GetFaceNames
,
1352 dwritefontface3_GetInformationalStrings
,
1353 dwritefontface3_HasCharacter
,
1354 dwritefontface3_GetRecommendedRenderingMode
,
1355 dwritefontface3_IsCharacterLocal
,
1356 dwritefontface3_IsGlyphLocal
,
1357 dwritefontface3_AreCharactersLocal
,
1358 dwritefontface3_AreGlyphsLocal
,
1359 dwritefontface4_GetGlyphImageFormats_
,
1360 dwritefontface4_GetGlyphImageFormats
,
1361 dwritefontface4_GetGlyphImageData
,
1362 dwritefontface4_ReleaseGlyphImageData
1365 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace4
**fontface
)
1367 struct dwrite_font_data
*data
= font
->data
;
1368 struct fontface_desc desc
;
1369 struct list
*cached_list
;
1374 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1375 font
->data
->simulations
, (IDWriteFontFace
**)fontface
, &cached_list
);
1377 IDWriteFontFace4_AddRef(*fontface
);
1381 desc
.factory
= font
->family
->collection
->factory
;
1382 desc
.face_type
= data
->face_type
;
1383 desc
.files
= &data
->file
;
1384 desc
.files_number
= 1;
1385 desc
.index
= data
->face_index
;
1386 desc
.simulations
= data
->simulations
;
1387 desc
.font_data
= data
;
1388 return create_fontface(&desc
, cached_list
, fontface
);
1391 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1393 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1395 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1397 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1398 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1399 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1400 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1401 IsEqualIID(riid
, &IID_IUnknown
))
1404 IDWriteFont3_AddRef(iface
);
1409 return E_NOINTERFACE
;
1412 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1414 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1415 ULONG ref
= InterlockedIncrement(&This
->ref
);
1416 TRACE("(%p)->(%d)\n", This
, ref
);
1420 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1422 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1423 ULONG ref
= InterlockedDecrement(&This
->ref
);
1425 TRACE("(%p)->(%d)\n", This
, ref
);
1428 IDWriteFontFamily1_Release(&This
->family
->IDWriteFontFamily1_iface
);
1429 release_font_data(This
->data
);
1436 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1438 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1439 TRACE("(%p)->(%p)\n", This
, family
);
1441 *family
= (IDWriteFontFamily
*)This
->family
;
1442 IDWriteFontFamily_AddRef(*family
);
1446 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1448 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1449 TRACE("(%p)\n", This
);
1450 return This
->data
->weight
;
1453 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1455 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1456 TRACE("(%p)\n", This
);
1457 return This
->data
->stretch
;
1460 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1462 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1463 TRACE("(%p)\n", This
);
1467 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1469 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1470 IDWriteFontFace4
*fontface
;
1474 TRACE("(%p)\n", This
);
1476 hr
= get_fontface_from_font(This
, &fontface
);
1480 ret
= IDWriteFontFace4_IsSymbolFont(fontface
);
1481 IDWriteFontFace4_Release(fontface
);
1485 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1487 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1488 TRACE("(%p)->(%p)\n", This
, names
);
1489 return clone_localizedstring(This
->data
->names
, names
);
1492 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1493 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1495 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1496 struct dwrite_font_data
*data
= This
->data
;
1499 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1504 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1507 if (!data
->info_strings
[stringid
]) {
1508 IDWriteFontFace4
*fontface
;
1509 const void *table_data
;
1514 hr
= get_fontface_from_font(This
, &fontface
);
1518 table_exists
= FALSE
;
1519 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1520 if (FAILED(hr
) || !table_exists
)
1521 WARN("no NAME table found.\n");
1524 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1525 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
1526 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1529 IDWriteFontFace4_Release(fontface
);
1532 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1540 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1542 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1543 TRACE("(%p)\n", This
);
1544 return This
->data
->simulations
;
1547 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1549 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1551 TRACE("(%p)->(%p)\n", This
, metrics
);
1552 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1555 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 value
, BOOL
*exists
)
1557 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1558 IDWriteFontFace4
*fontface
;
1562 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1566 hr
= get_fontface_from_font(This
, &fontface
);
1571 hr
= IDWriteFontFace4_GetGlyphIndices(fontface
, &value
, 1, &index
);
1574 IDWriteFontFace4_Release(fontface
);
1576 *exists
= index
!= 0;
1580 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1582 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1583 TRACE("(%p)->(%p)\n", This
, fontface
);
1584 return IDWriteFont3_CreateFontFace(iface
, (IDWriteFontFace3
**)fontface
);
1587 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1589 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1590 TRACE("(%p)->(%p)\n", This
, metrics
);
1591 *metrics
= This
->data
->metrics
;
1594 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1596 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1597 TRACE("(%p)->(%p)\n", This
, panose
);
1598 *panose
= This
->data
->panose
;
1601 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1603 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1604 IDWriteFontFace4
*fontface
;
1607 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1609 hr
= get_fontface_from_font(This
, &fontface
);
1613 hr
= IDWriteFontFace4_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1614 IDWriteFontFace4_Release(fontface
);
1618 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1620 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1621 IDWriteFontFace4
*fontface
;
1625 TRACE("(%p)\n", This
);
1627 hr
= get_fontface_from_font(This
, &fontface
);
1631 ret
= IDWriteFontFace4_IsMonospacedFont(fontface
);
1632 IDWriteFontFace4_Release(fontface
);
1636 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1638 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1639 IDWriteFontFace4
*fontface
;
1643 TRACE("(%p)\n", This
);
1645 hr
= get_fontface_from_font(This
, &fontface
);
1649 ret
= IDWriteFontFace4_IsColorFont(fontface
);
1650 IDWriteFontFace4_Release(fontface
);
1654 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1656 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1658 TRACE("(%p)->(%p)\n", This
, fontface
);
1660 return get_fontface_from_font(This
, (IDWriteFontFace4
**)fontface
);
1663 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1665 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1666 FIXME("(%p)->(%p): stub\n", This
, font
);
1670 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1672 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1674 TRACE("(%p)->(%p)\n", This
, reference
);
1676 return IDWriteFactory5_CreateFontFaceReference_(This
->family
->collection
->factory
, This
->data
->file
,
1677 This
->data
->face_index
, This
->data
->simulations
, reference
);
1680 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1682 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1686 TRACE("(%p)->(0x%x)\n", This
, ch
);
1688 hr
= IDWriteFont_HasCharacter((IDWriteFont
*)iface
, ch
, &ret
);
1689 return hr
== S_OK
&& ret
;
1692 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1694 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1695 FIXME("(%p): stub\n", This
);
1696 return DWRITE_LOCALITY_LOCAL
;
1699 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1700 dwritefont_QueryInterface
,
1703 dwritefont_GetFontFamily
,
1704 dwritefont_GetWeight
,
1705 dwritefont_GetStretch
,
1706 dwritefont_GetStyle
,
1707 dwritefont_IsSymbolFont
,
1708 dwritefont_GetFaceNames
,
1709 dwritefont_GetInformationalStrings
,
1710 dwritefont_GetSimulations
,
1711 dwritefont_GetMetrics
,
1712 dwritefont_HasCharacter
,
1713 dwritefont_CreateFontFace
,
1714 dwritefont1_GetMetrics
,
1715 dwritefont1_GetPanose
,
1716 dwritefont1_GetUnicodeRanges
,
1717 dwritefont1_IsMonospacedFont
,
1718 dwritefont2_IsColorFont
,
1719 dwritefont3_CreateFontFace
,
1721 dwritefont3_GetFontFaceReference
,
1722 dwritefont3_HasCharacter
,
1723 dwritefont3_GetLocality
1726 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
1730 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
1731 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
1734 static struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
1738 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
1739 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace4_iface
);
1742 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
1744 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1745 *lf
= font
->data
->lf
;
1748 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
1750 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1754 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
1756 struct dwrite_font
*This
;
1760 This
= heap_alloc(sizeof(*This
));
1762 return E_OUTOFMEMORY
;
1764 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1766 This
->family
= family
;
1767 IDWriteFontFamily1_AddRef(&family
->IDWriteFontFamily1_iface
);
1768 This
->data
= family
->data
->fonts
[index
];
1769 This
->style
= This
->data
->style
;
1770 addref_font_data(This
->data
);
1772 *font
= &This
->IDWriteFont3_iface
;
1777 /* IDWriteFontList1 */
1778 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList1
*iface
, REFIID riid
, void **obj
)
1780 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1782 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1784 if (IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1785 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1786 IsEqualIID(riid
, &IID_IUnknown
))
1789 IDWriteFontList1_AddRef(iface
);
1794 return E_NOINTERFACE
;
1797 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList1
*iface
)
1799 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1800 ULONG ref
= InterlockedIncrement(&This
->ref
);
1801 TRACE("(%p)->(%d)\n", This
, ref
);
1805 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList1
*iface
)
1807 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1808 ULONG ref
= InterlockedDecrement(&This
->ref
);
1810 TRACE("(%p)->(%d)\n", This
, ref
);
1815 for (i
= 0; i
< This
->font_count
; i
++)
1816 release_font_data(This
->fonts
[i
]);
1817 IDWriteFontFamily1_Release(&This
->family
->IDWriteFontFamily1_iface
);
1818 heap_free(This
->fonts
);
1825 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList1
*iface
, IDWriteFontCollection
**collection
)
1827 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1828 return IDWriteFontFamily1_GetFontCollection(&This
->family
->IDWriteFontFamily1_iface
, collection
);
1831 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList1
*iface
)
1833 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1834 TRACE("(%p)\n", This
);
1835 return This
->font_count
;
1838 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont
**font
)
1840 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1842 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1846 if (This
->font_count
== 0)
1849 if (index
>= This
->font_count
)
1850 return E_INVALIDARG
;
1852 return create_font(This
->family
, index
, (IDWriteFont3
**)font
);
1855 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList1
*iface
, UINT32 index
)
1857 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1859 FIXME("(%p)->(%u): stub\n", This
, index
);
1861 return DWRITE_LOCALITY_LOCAL
;
1864 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1866 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1868 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1872 if (This
->font_count
== 0)
1875 if (index
>= This
->font_count
)
1878 return create_font(This
->family
, index
, font
);
1881 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList1
*iface
, UINT32 index
,
1882 IDWriteFontFaceReference
**reference
)
1884 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1888 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
1892 hr
= IDWriteFontList1_GetFont(iface
, index
, &font
);
1896 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
1897 IDWriteFont3_Release(font
);
1902 static const IDWriteFontList1Vtbl dwritefontlistvtbl
= {
1903 dwritefontlist_QueryInterface
,
1904 dwritefontlist_AddRef
,
1905 dwritefontlist_Release
,
1906 dwritefontlist_GetFontCollection
,
1907 dwritefontlist_GetFontCount
,
1908 dwritefontlist_GetFont
,
1909 dwritefontlist1_GetFontLocality
,
1910 dwritefontlist1_GetFont
,
1911 dwritefontlist1_GetFontFaceReference
1914 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1916 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1918 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1920 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1921 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1922 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1923 IsEqualIID(riid
, &IID_IUnknown
))
1926 IDWriteFontFamily1_AddRef(iface
);
1931 return E_NOINTERFACE
;
1934 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1936 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1937 ULONG ref
= InterlockedIncrement(&This
->ref
);
1938 TRACE("(%p)->(%d)\n", This
, ref
);
1942 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1944 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1945 ULONG ref
= InterlockedDecrement(&This
->ref
);
1947 TRACE("(%p)->(%d)\n", This
, ref
);
1951 IDWriteFontCollection1_Release(&This
->collection
->IDWriteFontCollection1_iface
);
1952 release_fontfamily_data(This
->data
);
1959 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
1961 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1963 TRACE("(%p)->(%p)\n", This
, collection
);
1965 *collection
= (IDWriteFontCollection
*)This
->collection
;
1966 IDWriteFontCollection_AddRef(*collection
);
1970 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
1972 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1973 TRACE("(%p)\n", This
);
1974 return This
->data
->font_count
;
1977 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
1979 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1981 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1985 if (This
->data
->font_count
== 0)
1988 if (index
>= This
->data
->font_count
)
1989 return E_INVALIDARG
;
1991 return create_font(This
, index
, (IDWriteFont3
**)font
);
1994 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
1996 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1997 return clone_localizedstring(This
->data
->familyname
, names
);
2000 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2001 const struct dwrite_font_propvec
*req
)
2003 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2004 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2005 FLOAT cur_req_prod
, next_req_prod
;
2007 if (next_to_req
< cur_to_req
)
2010 if (next_to_req
> cur_to_req
)
2013 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2014 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2016 if (next_req_prod
> cur_req_prod
)
2019 if (next_req_prod
< cur_req_prod
)
2022 if (next
->stretch
> cur
->stretch
)
2024 if (next
->stretch
< cur
->stretch
)
2027 if (next
->style
> cur
->style
)
2029 if (next
->style
< cur
->style
)
2032 if (next
->weight
> cur
->weight
)
2034 if (next
->weight
< cur
->weight
)
2037 /* full match, no reason to prefer new variant */
2041 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
2042 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2044 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2045 struct dwrite_font_propvec req
;
2048 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
2050 if (This
->data
->font_count
== 0) {
2052 return DWRITE_E_NOFONT
;
2055 init_font_prop_vec(weight
, stretch
, style
, &req
);
2058 for (i
= 1; i
< This
->data
->font_count
; i
++) {
2059 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &This
->data
->fonts
[match
]->propvec
, &req
))
2063 return create_font(This
, match
, (IDWriteFont3
**)font
);
2066 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2068 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2070 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2073 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2075 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2078 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2080 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2085 for (j
= 0; j
< b
; j
++) {
2086 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2087 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2088 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2089 fonts
->fonts
[j
+1] = s
;
2100 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
2101 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2103 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2104 matching_filter_func func
= NULL
;
2105 struct dwrite_font_propvec req
;
2106 struct dwrite_fontlist
*fonts
;
2109 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
2113 fonts
= heap_alloc(sizeof(*fonts
));
2115 return E_OUTOFMEMORY
;
2117 /* Allocate as many as family has, not all of them will be necessary used. */
2118 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
2119 if (!fonts
->fonts
) {
2121 return E_OUTOFMEMORY
;
2124 fonts
->IDWriteFontList1_iface
.lpVtbl
= &dwritefontlistvtbl
;
2126 fonts
->family
= This
;
2127 IDWriteFontFamily1_AddRef(&fonts
->family
->IDWriteFontFamily1_iface
);
2128 fonts
->font_count
= 0;
2130 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2131 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2132 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
2133 func
= is_font_acceptable_for_normal
;
2135 else /* requested oblique or italic */ {
2136 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
2137 func
= is_font_acceptable_for_oblique_italic
;
2140 for (i
= 0; i
< This
->data
->font_count
; i
++) {
2141 if (!func
|| func(This
->data
->fonts
[i
])) {
2142 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
2143 addref_font_data(This
->data
->fonts
[i
]);
2144 fonts
->font_count
++;
2148 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2149 init_font_prop_vec(weight
, stretch
, style
, &req
);
2150 matchingfonts_sort(fonts
, &req
);
2152 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList1_iface
;
2156 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
2158 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2160 FIXME("(%p)->(%u): stub\n", This
, index
);
2162 return DWRITE_LOCALITY_LOCAL
;
2165 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
2167 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2169 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
2173 if (This
->data
->font_count
== 0)
2176 if (index
>= This
->data
->font_count
)
2179 return create_font(This
, index
, font
);
2182 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
2183 IDWriteFontFaceReference
**reference
)
2185 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2189 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
2193 hr
= IDWriteFontFamily1_GetFont(iface
, index
, &font
);
2197 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2198 IDWriteFont3_Release(font
);
2203 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
2204 dwritefontfamily_QueryInterface
,
2205 dwritefontfamily_AddRef
,
2206 dwritefontfamily_Release
,
2207 dwritefontfamily_GetFontCollection
,
2208 dwritefontfamily_GetFontCount
,
2209 dwritefontfamily_GetFont
,
2210 dwritefontfamily_GetFamilyNames
,
2211 dwritefontfamily_GetFirstMatchingFont
,
2212 dwritefontfamily_GetMatchingFonts
,
2213 dwritefontfamily1_GetFontLocality
,
2214 dwritefontfamily1_GetFont
,
2215 dwritefontfamily1_GetFontFaceReference
2218 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
, IDWriteFontFamily1
**family
)
2220 struct dwrite_fontfamily
*This
;
2224 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
2225 if (!This
) return E_OUTOFMEMORY
;
2227 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
2229 This
->collection
= collection
;
2230 IDWriteFontCollection1_AddRef(&collection
->IDWriteFontCollection1_iface
);
2231 This
->data
= collection
->family_data
[index
];
2232 InterlockedIncrement(&This
->data
->ref
);
2234 *family
= &This
->IDWriteFontFamily1_iface
;
2239 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2242 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
2245 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2247 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2248 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2250 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2251 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2252 IsEqualIID(riid
, &IID_IUnknown
))
2255 IDWriteFontCollection1_AddRef(iface
);
2261 if (IsEqualIID(riid
, &IID_issystemcollection
))
2264 return E_NOINTERFACE
;
2267 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2269 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2270 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2272 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2273 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2274 IsEqualIID(riid
, &IID_IUnknown
))
2277 IDWriteFontCollection1_AddRef(iface
);
2283 return E_NOINTERFACE
;
2286 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2288 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2289 ULONG ref
= InterlockedIncrement(&This
->ref
);
2290 TRACE("(%p)->(%d)\n", This
, ref
);
2294 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2296 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2297 ULONG ref
= InterlockedDecrement(&This
->ref
);
2299 TRACE("(%p)->(%d)\n", This
, ref
);
2304 factory_detach_fontcollection(This
->factory
, iface
);
2305 for (i
= 0; i
< This
->family_count
; i
++)
2306 release_fontfamily_data(This
->family_data
[i
]);
2307 heap_free(This
->family_data
);
2314 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2316 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2317 TRACE("(%p)\n", This
);
2318 return This
->family_count
;
2321 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2323 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2325 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2327 if (index
>= This
->family_count
) {
2332 return create_fontfamily(This
, index
, (IDWriteFontFamily1
**)family
);
2335 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2339 for (i
= 0; i
< collection
->family_count
; i
++) {
2340 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2341 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2344 for (j
= 0; j
< count
; j
++) {
2346 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2347 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2355 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2357 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2358 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2359 *index
= collection_find_family(This
, name
);
2360 *exists
= *index
!= ~0u;
2364 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2366 UINT32 left_key_size
, right_key_size
;
2367 const void *left_key
, *right_key
;
2373 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2377 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2381 if (left_key_size
!= right_key_size
)
2384 return !memcmp(left_key
, right_key
, left_key_size
);
2387 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2389 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2390 IDWriteFontFamily1
*family
;
2391 UINT32 i
, j
, face_index
;
2392 BOOL found_font
= FALSE
;
2393 IDWriteFontFile
*file
;
2396 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2401 return E_INVALIDARG
;
2404 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2407 face_index
= IDWriteFontFace_GetIndex(face
);
2410 for (i
= 0; i
< This
->family_count
; i
++) {
2411 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2413 for (j
= 0; j
< family_data
->font_count
; j
++) {
2414 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2416 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2425 IDWriteFontFile_Release(file
);
2428 return DWRITE_E_NOFONT
;
2430 hr
= create_fontfamily(This
, i
, &family
);
2434 hr
= create_font(impl_from_IDWriteFontFamily1(family
), j
, (IDWriteFont3
**)font
);
2435 IDWriteFontFamily1_Release(family
);
2439 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2441 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2443 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2448 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2450 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2452 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2454 if (index
>= This
->family_count
) {
2459 return create_fontfamily(This
, index
, family
);
2462 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2463 dwritefontcollection_QueryInterface
,
2464 dwritefontcollection_AddRef
,
2465 dwritefontcollection_Release
,
2466 dwritefontcollection_GetFontFamilyCount
,
2467 dwritefontcollection_GetFontFamily
,
2468 dwritefontcollection_FindFamilyName
,
2469 dwritefontcollection_GetFontFromFontFace
,
2470 dwritefontcollection1_GetFontSet
,
2471 dwritefontcollection1_GetFontFamily
2474 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2475 dwritesystemfontcollection_QueryInterface
,
2476 dwritefontcollection_AddRef
,
2477 dwritefontcollection_Release
,
2478 dwritefontcollection_GetFontFamilyCount
,
2479 dwritefontcollection_GetFontFamily
,
2480 dwritefontcollection_FindFamilyName
,
2481 dwritefontcollection_GetFontFromFontFace
,
2482 dwritefontcollection1_GetFontSet
,
2483 dwritefontcollection1_GetFontFamily
2486 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2488 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2489 struct dwrite_font_data
**new_list
;
2492 new_alloc
= family_data
->font_alloc
* 2;
2493 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2495 return E_OUTOFMEMORY
;
2496 family_data
->fonts
= new_list
;
2497 family_data
->font_alloc
= new_alloc
;
2500 family_data
->fonts
[family_data
->font_count
] = font_data
;
2501 family_data
->font_count
++;
2502 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2503 family_data
->has_normal_face
= 1;
2504 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2505 family_data
->has_oblique_face
= 1;
2507 family_data
->has_italic_face
= 1;
2511 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2513 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2514 struct dwrite_fontfamily_data
**new_list
;
2517 new_alloc
= collection
->family_alloc
* 2;
2518 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2520 return E_OUTOFMEMORY
;
2522 collection
->family_alloc
= new_alloc
;
2523 collection
->family_data
= new_list
;
2526 collection
->family_data
[collection
->family_count
++] = family
;
2530 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2532 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2533 collection
->ref
= 1;
2534 collection
->family_count
= 0;
2535 collection
->family_alloc
= is_system
? 30 : 5;
2536 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2537 if (!collection
->family_data
)
2538 return E_OUTOFMEMORY
;
2543 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2545 IDWriteFontFileLoader
*loader
;
2552 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2556 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2560 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2561 IDWriteFontFileLoader_Release(loader
);
2568 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2570 BOOL exists
= FALSE
;
2575 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2576 if (FAILED(hr
) || !exists
)
2579 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2582 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2586 while (isspaceW(*in
))
2590 if (!(len
= strlenW(in
)))
2593 while (isspaceW(in
[len
-1]))
2596 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2605 INT len
; /* token length */
2606 INT fulllen
; /* full length including following separators */
2609 static inline BOOL
is_name_separator_char(WCHAR ch
)
2611 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2614 struct name_pattern
{
2615 const WCHAR
*part1
; /* NULL indicates end of list */
2616 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2619 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2621 const struct name_pattern
*pattern
;
2622 struct name_token
*token
;
2625 while ((pattern
= &patterns
[i
++])->part1
) {
2626 int len_part1
= strlenW(pattern
->part1
);
2627 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2629 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2630 if (len_part2
== 0) {
2631 /* simple case with single part pattern */
2632 if (token
->len
!= len_part1
)
2635 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2636 if (match
) *match
= *token
;
2637 list_remove(&token
->entry
);
2643 struct name_token
*next_token
;
2644 struct list
*next_entry
;
2646 /* pattern parts are stored in reading order, tokens list is reversed */
2647 if (token
->len
< len_part2
)
2650 /* it's possible to have combined string as a token, like ExtraCondensed */
2651 if (token
->len
== len_part1
+ len_part2
) {
2652 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2655 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2658 /* combined string match */
2659 if (match
) *match
= *token
;
2660 list_remove(&token
->entry
);
2665 /* now it's only possible to have two tokens matched to respective pattern parts */
2666 if (token
->len
!= len_part2
)
2669 next_entry
= list_next(tokens
, &token
->entry
);
2671 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2672 if (next_token
->len
!= len_part1
)
2675 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2678 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2681 /* both parts matched, remove tokens */
2683 match
->ptr
= next_token
->ptr
;
2684 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2686 list_remove(&token
->entry
);
2687 list_remove(&next_token
->entry
);
2688 heap_free(next_token
);
2703 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2705 static const WCHAR itaW
[] = {'i','t','a',0};
2706 static const WCHAR italW
[] = {'i','t','a','l',0};
2707 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2708 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2710 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2711 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2712 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2713 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2715 static const struct name_pattern italic_patterns
[] = {
2724 static const struct name_pattern oblique_patterns
[] = {
2733 /* italic patterns first */
2734 if (match_pattern_list(tokens
, italic_patterns
, match
))
2735 return DWRITE_FONT_STYLE_ITALIC
;
2737 /* oblique patterns */
2738 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2739 return DWRITE_FONT_STYLE_OBLIQUE
;
2744 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2745 struct name_token
*match
)
2747 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2748 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2749 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2750 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2751 static const WCHAR wideW
[] = {'w','i','d','e',0};
2752 static const WCHAR condW
[] = {'c','o','n','d',0};
2754 static const struct name_pattern ultracondensed_patterns
[] = {
2755 { extraW
, compressedW
},
2756 { extW
, compressedW
},
2757 { ultraW
, compressedW
},
2758 { ultraW
, condensedW
},
2763 static const struct name_pattern extracondensed_patterns
[] = {
2765 { extraW
, condensedW
},
2766 { extW
, condensedW
},
2772 static const struct name_pattern semicondensed_patterns
[] = {
2775 { semiW
, condensedW
},
2780 static const struct name_pattern semiexpanded_patterns
[] = {
2782 { semiW
, expandedW
},
2783 { semiW
, extendedW
},
2787 static const struct name_pattern extraexpanded_patterns
[] = {
2788 { extraW
, expandedW
},
2789 { extW
, expandedW
},
2790 { extraW
, extendedW
},
2791 { extW
, extendedW
},
2795 static const struct name_pattern ultraexpanded_patterns
[] = {
2796 { ultraW
, expandedW
},
2797 { ultraW
, extendedW
},
2801 static const struct name_pattern condensed_patterns
[] = {
2807 static const struct name_pattern expanded_patterns
[] = {
2813 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2814 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2816 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2817 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2819 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2820 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2822 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2823 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2825 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2826 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2828 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2829 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2831 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2832 return DWRITE_FONT_STRETCH_CONDENSED
;
2834 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2835 return DWRITE_FONT_STRETCH_EXPANDED
;
2840 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2841 struct name_token
*match
)
2843 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2844 static const WCHAR nordW
[] = {'n','o','r','d',0};
2846 static const struct name_pattern thin_patterns
[] = {
2853 static const struct name_pattern extralight_patterns
[] = {
2860 static const struct name_pattern semilight_patterns
[] = {
2865 static const struct name_pattern demibold_patterns
[] = {
2871 static const struct name_pattern extrabold_patterns
[] = {
2878 static const struct name_pattern extrablack_patterns
[] = {
2885 static const struct name_pattern bold_patterns
[] = {
2890 static const struct name_pattern thin2_patterns
[] = {
2895 static const struct name_pattern light_patterns
[] = {
2900 static const struct name_pattern medium_patterns
[] = {
2905 static const struct name_pattern black_patterns
[] = {
2912 static const struct name_pattern demibold2_patterns
[] = {
2917 static const struct name_pattern extrabold2_patterns
[] = {
2922 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2923 matching pattern. */
2925 if (match_pattern_list(tokens
, thin_patterns
, match
))
2926 return DWRITE_FONT_WEIGHT_THIN
;
2928 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2929 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2931 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2932 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2934 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2935 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2937 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2938 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2940 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2941 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2943 if (match_pattern_list(tokens
, bold_patterns
, match
))
2944 return DWRITE_FONT_WEIGHT_BOLD
;
2946 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2947 return DWRITE_FONT_WEIGHT_THIN
;
2949 if (match_pattern_list(tokens
, light_patterns
, match
))
2950 return DWRITE_FONT_WEIGHT_LIGHT
;
2952 if (match_pattern_list(tokens
, medium_patterns
, match
))
2953 return DWRITE_FONT_WEIGHT_MEDIUM
;
2955 if (match_pattern_list(tokens
, black_patterns
, match
))
2956 return DWRITE_FONT_WEIGHT_BLACK
;
2958 if (match_pattern_list(tokens
, black_patterns
, match
))
2959 return DWRITE_FONT_WEIGHT_BLACK
;
2961 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2962 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2964 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2965 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2967 /* FIXME: use abbreviated names to extract weight */
2972 struct knownweight_entry
{
2974 DWRITE_FONT_WEIGHT weight
;
2977 static int compare_knownweights(const void *a
, const void* b
)
2979 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2980 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2983 if (target
> entry
->weight
)
2985 else if (target
< entry
->weight
)
2991 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2993 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2994 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2995 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2996 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2997 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2998 const struct knownweight_entry
*ptr
;
3000 static const struct knownweight_entry knownweights
[] = {
3001 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3002 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3003 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3004 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3005 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3006 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3007 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3008 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3009 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3010 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3013 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
3014 compare_knownweights
);
3020 strcpyW(nameW
, ptr
->nameW
);
3024 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3026 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3027 strW
[name
->len
] = 0;
3030 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3031 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3033 static const WCHAR bookW
[] = {'B','o','o','k',0};
3034 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3035 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3036 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3037 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3039 static const WCHAR
*regular_patterns
[] = {
3048 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3052 len
= strlenW(facenameW
);
3054 /* remove rightmost regular variant from face name */
3055 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3056 int pattern_len
= strlenW(ptr
);
3059 if (pattern_len
> len
)
3062 src
= facenameW
+ len
- pattern_len
;
3063 while (src
>= facenameW
) {
3064 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3065 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3066 len
= strlenW(facenameW
);
3078 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3086 struct name_token
*token
= heap_alloc(sizeof(*token
));
3091 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3097 /* skip separators */
3098 while (is_name_separator_char(*ptr
)) {
3103 list_add_head(tokens
, &token
->entry
);
3107 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3109 struct name_token
*token
, *token2
;
3110 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3113 list_remove(&token
->entry
);
3115 /* don't include last separator */
3116 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3117 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3125 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3127 struct name_token stretch_name
, weight_name
, style_name
;
3128 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3129 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3130 const WCHAR
*regular_ptr
= NULL
;
3131 DWRITE_FONT_STRETCH stretch
;
3132 DWRITE_FONT_WEIGHT weight
;
3136 /* remove leading and trailing spaces from family and face name */
3137 trim_spaces(familyW
, familynameW
);
3138 len
= trim_spaces(faceW
, facenameW
);
3140 /* remove rightmost regular variant from face name */
3141 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3143 /* append face name to family name, FIXME check if face name is a substring of family name */
3145 strcatW(familynameW
, spaceW
);
3146 strcatW(familynameW
, facenameW
);
3149 /* tokenize with " .-_" */
3150 fontname_tokenize(&tokens
, familynameW
);
3152 /* extract and resolve style */
3153 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3155 /* extract stretch */
3156 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3158 /* extract weight */
3159 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3161 /* resolve weight */
3162 if (weight
!= font
->weight
) {
3163 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3164 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3165 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3166 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3167 !(abs(weight
- font
->weight
) <= 150 &&
3168 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3169 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3170 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3172 font
->weight
= weight
;
3176 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3177 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3178 stretch itself is normal (extracted stretch is never normal). */
3179 if (stretch
!= font
->stretch
) {
3180 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3181 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3182 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3184 font
->stretch
= stretch
;
3188 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3190 /* get final combined string from what's left in token list, list is released */
3191 fontname_tokens_to_str(&tokens
, finalW
);
3193 if (!strcmpW(familyW
, finalW
))
3196 /* construct face name */
3197 strcpyW(familyW
, finalW
);
3199 /* resolved weight name */
3200 if (weight_name
.ptr
)
3201 font_name_token_to_str(&weight_name
, weightW
);
3202 /* ignore normal weight */
3203 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3205 /* for known weight values use appropriate names */
3206 else if (is_known_weight_value(font
->weight
, weightW
)) {
3208 /* use Wnnn format as a fallback in case weight is not one of known values */
3210 static const WCHAR fmtW
[] = {'W','%','d',0};
3211 sprintfW(weightW
, fmtW
, font
->weight
);
3214 /* resolved stretch name */
3215 if (stretch_name
.ptr
)
3216 font_name_token_to_str(&stretch_name
, stretchW
);
3217 /* ignore normal stretch */
3218 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3220 /* use predefined stretch names */
3222 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3223 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3224 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3225 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3226 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3227 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3229 static const WCHAR
*stretchnamesW
[] = {
3230 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3235 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3241 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3244 /* resolved style name */
3246 font_name_token_to_str(&style_name
, styleW
);
3247 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3249 /* use predefined names */
3251 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3252 strcpyW(styleW
, italicW
);
3254 strcpyW(styleW
, obliqueW
);
3257 /* use Regular match if it was found initially */
3258 if (!*weightW
&& !*stretchW
&& !*styleW
)
3259 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3263 strcpyW(faceW
, stretchW
);
3266 strcatW(faceW
, spaceW
);
3267 strcatW(faceW
, weightW
);
3271 strcatW(faceW
, spaceW
);
3272 strcatW(faceW
, styleW
);
3276 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3280 static HRESULT
init_font_data(const struct fontface_desc
*desc
, IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
3282 struct file_stream_desc stream_desc
;
3283 struct dwrite_font_props props
;
3284 struct dwrite_font_data
*data
;
3285 IDWriteFontFileStream
*stream
;
3286 WCHAR familyW
[255], faceW
[255];
3290 data
= heap_alloc_zero(sizeof(*data
));
3292 return E_OUTOFMEMORY
;
3294 hr
= get_filestream_from_file(desc
->files
[0], &stream
);
3301 data
->file
= desc
->files
[0];
3302 data
->face_index
= desc
->index
;
3303 data
->face_type
= desc
->face_type
;
3304 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3305 data
->bold_sim_tested
= 0;
3306 data
->oblique_sim_tested
= 0;
3307 IDWriteFontFile_AddRef(data
->file
);
3309 stream_desc
.stream
= stream
;
3310 stream_desc
.face_type
= desc
->face_type
;
3311 stream_desc
.face_index
= desc
->index
;
3312 opentype_get_font_properties(&stream_desc
, &props
);
3313 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3314 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3316 /* get family name from font file */
3317 hr
= opentype_get_font_familyname(&stream_desc
, family_name
);
3318 IDWriteFontFileStream_Release(stream
);
3320 WARN("unable to get family name from font\n");
3321 release_font_data(data
);
3325 data
->style
= props
.style
;
3326 data
->stretch
= props
.stretch
;
3327 data
->weight
= props
.weight
;
3328 data
->panose
= props
.panose
;
3329 data
->lf
= props
.lf
;
3331 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3332 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3333 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3334 set_en_localizedstring(*family_name
, familyW
);
3335 set_en_localizedstring(data
->names
, faceW
);
3338 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3344 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3345 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3347 struct dwrite_font_data
*data
;
3351 data
= heap_alloc_zero(sizeof(*data
));
3353 return E_OUTOFMEMORY
;
3357 data
->simulations
|= sim
;
3358 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3359 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3360 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3361 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3362 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3364 IDWriteFontFile_AddRef(data
->file
);
3366 create_localizedstrings(&data
->names
);
3367 add_localizedstring(data
->names
, enusW
, facenameW
);
3369 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3375 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3377 struct dwrite_fontfamily_data
*data
;
3379 data
= heap_alloc(sizeof(*data
));
3381 return E_OUTOFMEMORY
;
3384 data
->font_count
= 0;
3385 data
->font_alloc
= 2;
3386 data
->has_normal_face
= 0;
3387 data
->has_oblique_face
= 0;
3388 data
->has_italic_face
= 0;
3390 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3393 return E_OUTOFMEMORY
;
3396 data
->familyname
= familyname
;
3397 IDWriteLocalizedStrings_AddRef(familyname
);
3403 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3405 UINT32 i
, j
, heaviest
;
3407 for (i
= 0; i
< family
->font_count
; i
++) {
3408 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3411 if (family
->fonts
[i
]->bold_sim_tested
)
3414 family
->fonts
[i
]->bold_sim_tested
= 1;
3415 for (j
= i
; j
< family
->font_count
; j
++) {
3416 if (family
->fonts
[j
]->bold_sim_tested
)
3419 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3420 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3421 if (family
->fonts
[j
]->weight
> weight
) {
3422 weight
= family
->fonts
[j
]->weight
;
3425 family
->fonts
[j
]->bold_sim_tested
= 1;
3429 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3430 static const struct name_pattern weightsim_patterns
[] = {
3445 WCHAR facenameW
[255], initialW
[255];
3446 struct dwrite_font_data
*boldface
;
3449 /* add Bold simulation based on heaviest face data */
3451 /* Simulated face name should only contain Bold as weight term,
3452 so remove existing regular and weight terms. */
3453 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3454 facename_remove_regular_term(initialW
, -1);
3456 /* remove current weight pattern */
3457 fontname_tokenize(&tokens
, initialW
);
3458 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3459 fontname_tokens_to_str(&tokens
, facenameW
);
3461 /* Bold suffix for new name */
3463 strcatW(facenameW
, spaceW
);
3464 strcatW(facenameW
, boldW
);
3466 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3467 boldface
->bold_sim_tested
= 1;
3468 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
3469 fontfamily_add_font(family
, boldface
);
3475 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3479 for (i
= 0; i
< family
->font_count
; i
++) {
3480 UINT32 regular
= ~0u, oblique
= ~0u;
3481 struct dwrite_font_data
*obliqueface
;
3482 WCHAR facenameW
[255];
3484 if (family
->fonts
[i
]->oblique_sim_tested
)
3487 family
->fonts
[i
]->oblique_sim_tested
= 1;
3488 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3490 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3493 /* find regular style with same weight/stretch values */
3494 for (j
= i
; j
< family
->font_count
; j
++) {
3495 if (family
->fonts
[j
]->oblique_sim_tested
)
3498 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3499 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3501 family
->fonts
[j
]->oblique_sim_tested
= 1;
3502 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3505 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3509 if (regular
!= ~0u && oblique
!= ~0u)
3513 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3517 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3521 /* add oblique simulation based on this regular face */
3523 /* remove regular term if any, append 'Oblique' */
3524 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3525 facename_remove_regular_term(facenameW
, -1);
3528 strcatW(facenameW
, spaceW
);
3529 strcatW(facenameW
, obliqueW
);
3531 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3532 obliqueface
->oblique_sim_tested
= 1;
3533 obliqueface
->lf
.lfItalic
= 1;
3534 fontfamily_add_font(family
, obliqueface
);
3539 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3540 const WCHAR
*replacement_name
)
3542 UINT32 i
= collection_find_family(collection
, replacement_name
);
3543 struct dwrite_fontfamily_data
*target
;
3544 IDWriteLocalizedStrings
*strings
;
3547 /* replacement does not exist */
3551 hr
= create_localizedstrings(&strings
);
3555 /* add a new family with target name, reuse font data from replacement */
3556 add_localizedstring(strings
, enusW
, target_name
);
3557 hr
= init_fontfamily_data(strings
, &target
);
3559 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3562 for (i
= 0; i
< replacement
->font_count
; i
++) {
3563 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3564 addref_font_data(replacement
->fonts
[i
]);
3567 fontcollection_add_family(collection
, target
);
3568 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3569 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3571 IDWriteLocalizedStrings_Release(strings
);
3575 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3576 system font collections. */
3577 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3579 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3584 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3587 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3592 max_namelen
++; /* returned value doesn't include room for '\0' */
3593 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3594 data
= heap_alloc(max_datalen
);
3596 datalen
= max_datalen
;
3597 namelen
= max_namelen
;
3598 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3599 if (collection_find_family(collection
, name
) == ~0u) {
3600 if (type
== REG_MULTI_SZ
) {
3601 WCHAR
*replacement
= data
;
3602 while (*replacement
) {
3603 if (fontcollection_add_replacement(collection
, name
, replacement
))
3605 replacement
+= strlenW(replacement
) + 1;
3608 else if (type
== REG_SZ
)
3609 fontcollection_add_replacement(collection
, name
, data
);
3612 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3614 datalen
= max_datalen
;
3615 namelen
= max_namelen
;
3623 HRESULT
create_font_collection(IDWriteFactory5
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
3624 IDWriteFontCollection1
**ret
)
3626 struct fontfile_enum
{
3628 IDWriteFontFile
*file
;
3630 struct fontfile_enum
*fileenum
, *fileenum2
;
3631 struct dwrite_fontcollection
*collection
;
3632 struct list scannedfiles
;
3633 BOOL current
= FALSE
;
3639 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3640 if (!collection
) return E_OUTOFMEMORY
;
3642 hr
= init_font_collection(collection
, is_system
);
3644 heap_free(collection
);
3648 *ret
= &collection
->IDWriteFontCollection1_iface
;
3650 TRACE("building font collection:\n");
3652 list_init(&scannedfiles
);
3653 while (hr
== S_OK
) {
3654 DWRITE_FONT_FACE_TYPE face_type
;
3655 DWRITE_FONT_FILE_TYPE file_type
;
3656 BOOL supported
, same
= FALSE
;
3657 IDWriteFontFile
*file
;
3661 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3662 if (FAILED(hr
) || !current
)
3665 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3669 /* check if we've scanned this file already */
3670 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3671 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3676 IDWriteFontFile_Release(file
);
3680 /* failed font files are skipped */
3681 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3682 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3683 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3684 IDWriteFontFile_Release(file
);
3689 /* add to scanned list */
3690 fileenum
= heap_alloc(sizeof(*fileenum
));
3691 fileenum
->file
= file
;
3692 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3694 for (i
= 0; i
< face_count
; i
++) {
3695 IDWriteLocalizedStrings
*family_name
= NULL
;
3696 struct dwrite_font_data
*font_data
;
3697 struct fontface_desc desc
;
3701 desc
.factory
= factory
;
3702 desc
.face_type
= face_type
;
3704 desc
.files_number
= 1;
3706 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3707 desc
.font_data
= NULL
;
3709 /* alloc and init new font data structure */
3710 hr
= init_font_data(&desc
, &family_name
, &font_data
);
3712 /* move to next one */
3717 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3719 /* ignore dot named faces */
3720 if (familyW
[0] == '.') {
3721 WARN("Ignoring face %s\n", debugstr_w(familyW
));
3722 IDWriteLocalizedStrings_Release(family_name
);
3723 release_font_data(font_data
);
3727 index
= collection_find_family(collection
, familyW
);
3729 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3731 struct dwrite_fontfamily_data
*family_data
;
3733 /* create and init new family */
3734 hr
= init_fontfamily_data(family_name
, &family_data
);
3736 /* add font to family, family - to collection */
3737 hr
= fontfamily_add_font(family_data
, font_data
);
3739 hr
= fontcollection_add_family(collection
, family_data
);
3742 release_fontfamily_data(family_data
);
3746 IDWriteLocalizedStrings_Release(family_name
);
3753 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3754 IDWriteFontFile_Release(fileenum
->file
);
3755 list_remove(&fileenum
->entry
);
3756 heap_free(fileenum
);
3759 for (i
= 0; i
< collection
->family_count
; i
++) {
3760 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3761 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3765 fontcollection_add_replacements(collection
);
3767 collection
->factory
= factory
;
3768 IDWriteFactory5_AddRef(factory
);
3773 struct system_fontfile_enumerator
3775 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3778 IDWriteFactory5
*factory
;
3783 DWORD max_val_count
;
3786 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3788 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3791 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3795 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3796 IDWriteFontFileEnumerator_AddRef(iface
);
3801 return E_NOINTERFACE
;
3804 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3806 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3807 return InterlockedIncrement(&enumerator
->ref
);
3810 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3812 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3813 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3816 IDWriteFactory5_Release(enumerator
->factory
);
3817 RegCloseKey(enumerator
->hkey
);
3818 heap_free(enumerator
->value
);
3819 heap_free(enumerator
);
3825 static HRESULT
create_local_file_reference(IDWriteFactory5
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3829 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3830 if (!strchrW(filename
, '\\')) {
3831 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3832 WCHAR fullpathW
[MAX_PATH
];
3834 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3835 strcatW(fullpathW
, fontsW
);
3836 strcatW(fullpathW
, filename
);
3838 hr
= IDWriteFactory5_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3841 hr
= IDWriteFactory5_CreateFontFileReference(factory
, filename
, NULL
, file
);
3846 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3848 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3849 DWORD ret
, type
, val_count
, count
;
3850 WCHAR
*value
, *filename
;
3855 if (enumerator
->index
< 0)
3858 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3859 if (ret
!= ERROR_SUCCESS
)
3863 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3864 filename
= heap_alloc(count
);
3865 if (!value
|| !filename
) {
3867 heap_free(filename
);
3868 return E_OUTOFMEMORY
;
3871 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3874 heap_free(filename
);
3878 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3881 heap_free(filename
);
3885 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3887 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3890 enumerator
->index
++;
3892 if (!enumerator
->value
) {
3893 if (RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3894 &enumerator
->max_val_count
, NULL
, NULL
, NULL
))
3897 enumerator
->max_val_count
++;
3898 if (!(enumerator
->value
= heap_alloc(enumerator
->max_val_count
* sizeof(*enumerator
->value
))))
3899 return E_OUTOFMEMORY
;
3902 /* iterate until we find next string value */
3904 DWORD type
= 0, count
, val_count
;
3906 val_count
= enumerator
->max_val_count
;
3907 *enumerator
->value
= 0;
3908 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, enumerator
->value
, &val_count
,
3909 NULL
, &type
, NULL
, &count
))
3911 if (type
== REG_SZ
&& *enumerator
->value
&& *enumerator
->value
!= '@') {
3915 enumerator
->index
++;
3918 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3922 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3924 systemfontfileenumerator_QueryInterface
,
3925 systemfontfileenumerator_AddRef
,
3926 systemfontfileenumerator_Release
,
3927 systemfontfileenumerator_MoveNext
,
3928 systemfontfileenumerator_GetCurrentFontFile
3931 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory5
*factory
, IDWriteFontFileEnumerator
**ret
)
3933 struct system_fontfile_enumerator
*enumerator
;
3934 static const WCHAR fontslistW
[] = {
3935 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3936 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3937 'F','o','n','t','s',0
3942 enumerator
= heap_alloc(sizeof(*enumerator
));
3944 return E_OUTOFMEMORY
;
3946 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3947 enumerator
->ref
= 1;
3948 enumerator
->factory
= factory
;
3949 enumerator
->index
= -1;
3950 enumerator
->value
= NULL
;
3951 enumerator
->max_val_count
= 0;
3952 IDWriteFactory5_AddRef(factory
);
3954 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3955 ERR("failed to open fonts list key\n");
3956 IDWriteFactory5_Release(factory
);
3957 heap_free(enumerator
);
3961 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3966 HRESULT
get_system_fontcollection(IDWriteFactory5
*factory
, IDWriteFontCollection1
**collection
)
3968 IDWriteFontFileEnumerator
*enumerator
;
3973 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3977 TRACE("building system font collection for factory %p\n", factory
);
3978 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3979 IDWriteFontFileEnumerator_Release(enumerator
);
3983 static HRESULT
eudc_collection_add_family(IDWriteFactory5
*factory
, struct dwrite_fontcollection
*collection
,
3984 const WCHAR
*keynameW
, const WCHAR
*pathW
)
3986 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};
3987 static const WCHAR emptyW
[] = {0};
3988 IDWriteLocalizedStrings
*names
;
3989 DWRITE_FONT_FACE_TYPE face_type
;
3990 DWRITE_FONT_FILE_TYPE file_type
;
3992 UINT32 face_count
, i
;
3993 IDWriteFontFile
*file
;
3995 struct dwrite_fontfamily_data
*family_data
;
3997 /* create font file from this path */
3998 hr
= create_local_file_reference(factory
, pathW
, &file
);
4002 /* failed font files are skipped */
4003 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
4004 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4005 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4006 IDWriteFontFile_Release(file
);
4010 /* create and init new family */
4012 /* Family names are added for non-specific locale, represented with empty string.
4013 Default family appears with empty family name. */
4014 create_localizedstrings(&names
);
4015 if (!strcmpiW(keynameW
, defaultfontW
))
4016 add_localizedstring(names
, emptyW
, emptyW
);
4018 add_localizedstring(names
, emptyW
, keynameW
);
4020 hr
= init_fontfamily_data(names
, &family_data
);
4021 IDWriteLocalizedStrings_Release(names
);
4023 IDWriteFontFile_Release(file
);
4027 /* fill with faces */
4028 for (i
= 0; i
< face_count
; i
++) {
4029 struct dwrite_font_data
*font_data
;
4030 struct fontface_desc desc
;
4032 /* alloc and init new font data structure */
4033 desc
.factory
= factory
;
4034 desc
.face_type
= face_type
;
4037 desc
.files_number
= 1;
4038 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4039 desc
.font_data
= NULL
;
4041 hr
= init_font_data(&desc
, &names
, &font_data
);
4045 IDWriteLocalizedStrings_Release(names
);
4047 /* add font to family */
4048 hr
= fontfamily_add_font(family_data
, font_data
);
4050 release_font_data(font_data
);
4053 /* add family to collection */
4054 hr
= fontcollection_add_family(collection
, family_data
);
4056 release_fontfamily_data(family_data
);
4057 IDWriteFontFile_Release(file
);
4062 HRESULT
get_eudc_fontcollection(IDWriteFactory5
*factory
, IDWriteFontCollection1
**ret
)
4064 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4065 struct dwrite_fontcollection
*collection
;
4066 static const WCHAR emptyW
[] = {0};
4067 WCHAR eudckeypathW
[16];
4075 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4079 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4080 if (!collection
) return E_OUTOFMEMORY
;
4082 hr
= init_font_collection(collection
, FALSE
);
4084 heap_free(collection
);
4088 *ret
= &collection
->IDWriteFontCollection1_iface
;
4089 collection
->factory
= factory
;
4090 IDWriteFactory5_AddRef(factory
);
4092 /* return empty collection if EUDC fonts are not configured */
4093 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4094 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4097 retval
= ERROR_SUCCESS
;
4099 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4100 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4101 DWORD type
, path_len
, name_len
;
4103 path_len
= sizeof(pathW
)/sizeof(*pathW
);
4104 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
4105 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4106 if (retval
|| type
!= REG_SZ
)
4109 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4111 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4113 RegCloseKey(eudckey
);
4115 /* try to add global default if not defined for specific codepage */
4117 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
4119 if (FAILED(hr
) || !exists
) {
4120 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4121 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4123 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4126 /* EUDC collection offers simulated faces too */
4127 for (i
= 0; i
< collection
->family_count
; i
++) {
4128 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4129 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4135 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4137 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4139 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4141 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4144 IDWriteFontFile_AddRef(iface
);
4149 return E_NOINTERFACE
;
4152 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4154 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4155 ULONG ref
= InterlockedIncrement(&This
->ref
);
4156 TRACE("(%p)->(%d)\n", This
, ref
);
4160 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4162 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4163 ULONG ref
= InterlockedDecrement(&This
->ref
);
4165 TRACE("(%p)->(%d)\n", This
, ref
);
4169 IDWriteFontFileLoader_Release(This
->loader
);
4170 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4171 heap_free(This
->reference_key
);
4178 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4180 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4181 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4182 *fontFileReferenceKey
= This
->reference_key
;
4183 *fontFileReferenceKeySize
= This
->key_size
;
4188 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4190 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4191 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4192 *fontFileLoader
= This
->loader
;
4193 IDWriteFontFileLoader_AddRef(This
->loader
);
4198 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
4199 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
4201 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4202 IDWriteFontFileStream
*stream
;
4205 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
4207 *isSupportedFontType
= FALSE
;
4208 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4210 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4213 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4217 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
4219 /* TODO: Further Analysis */
4220 IDWriteFontFileStream_Release(stream
);
4224 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4225 dwritefontfile_QueryInterface
,
4226 dwritefontfile_AddRef
,
4227 dwritefontfile_Release
,
4228 dwritefontfile_GetReferenceKey
,
4229 dwritefontfile_GetLoader
,
4230 dwritefontfile_Analyze
,
4233 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4234 IDWriteFontFile
**ret
)
4236 struct dwrite_fontfile
*file
;
4241 file
= heap_alloc(sizeof(*file
));
4242 key
= heap_alloc(key_size
);
4243 if (!file
|| !key
) {
4246 return E_OUTOFMEMORY
;
4249 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4251 IDWriteFontFileLoader_AddRef(loader
);
4252 file
->loader
= loader
;
4253 file
->stream
= NULL
;
4254 file
->reference_key
= key
;
4255 memcpy(file
->reference_key
, reference_key
, key_size
);
4256 file
->key_size
= key_size
;
4258 *ret
= &file
->IDWriteFontFile_iface
;
4263 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
4265 IDWriteFontFileLoader
*loader
;
4271 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4275 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
4277 IDWriteFontFileLoader_Release(loader
);
4281 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
4282 IDWriteFontFileLoader_Release(loader
);
4287 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace4
**ret
)
4289 struct file_stream_desc stream_desc
;
4290 struct dwrite_fontface
*fontface
;
4297 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4299 return E_OUTOFMEMORY
;
4301 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4302 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * desc
->files_number
);
4304 if (!fontface
->files
|| !fontface
->streams
) {
4305 heap_free(fontface
->files
);
4306 heap_free(fontface
->streams
);
4307 heap_free(fontface
);
4308 return E_OUTOFMEMORY
;
4311 fontface
->IDWriteFontFace4_iface
.lpVtbl
= &dwritefontfacevtbl
;
4313 fontface
->type
= desc
->face_type
;
4314 fontface
->file_count
= desc
->files_number
;
4315 fontface
->cmap
.exists
= TRUE
;
4316 fontface
->vdmx
.exists
= TRUE
;
4317 fontface
->gasp
.exists
= TRUE
;
4318 fontface
->cpal
.exists
= TRUE
;
4319 fontface
->colr
.exists
= TRUE
;
4320 fontface
->index
= desc
->index
;
4321 fontface
->simulations
= desc
->simulations
;
4323 for (i
= 0; i
< fontface
->file_count
; i
++) {
4324 hr
= get_stream_from_file(desc
->files
[i
], &fontface
->streams
[i
]);
4326 IDWriteFontFace4_Release(&fontface
->IDWriteFontFace4_iface
);
4330 fontface
->files
[i
] = desc
->files
[i
];
4331 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4334 stream_desc
.stream
= fontface
->streams
[0];
4335 stream_desc
.face_type
= desc
->face_type
;
4336 stream_desc
.face_index
= desc
->index
;
4337 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4338 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4339 /* TODO: test what happens if caret is already slanted */
4340 if (fontface
->caret
.slopeRise
== 1) {
4341 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4342 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4346 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace4_iface
, &is_symbol
);
4348 fontface
->flags
|= FONTFACE_IS_SYMBOL
;
4349 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace4_iface
))
4350 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4351 if (freetype_is_monospaced(&fontface
->IDWriteFontFace4_iface
))
4352 fontface
->flags
|= FONTFACE_IS_MONOSPACED
;
4353 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace4_iface
))
4354 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4355 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace4_iface
);
4357 /* Font properties are reused from font object when 'normal' face creation path is used:
4358 collection -> family -> matching font -> fontface.
4360 If face is created directly from factory we have to go through properties resolution.
4362 if (desc
->font_data
) {
4363 fontface
->weight
= desc
->font_data
->weight
;
4364 fontface
->style
= desc
->font_data
->style
;
4365 fontface
->stretch
= desc
->font_data
->stretch
;
4366 fontface
->panose
= desc
->font_data
->panose
;
4367 fontface
->lf
= desc
->font_data
->lf
;
4370 IDWriteLocalizedStrings
*names
;
4371 struct dwrite_font_data
*data
;
4373 hr
= init_font_data(desc
, &names
, &data
);
4375 IDWriteFontFace4_Release(&fontface
->IDWriteFontFace4_iface
);
4379 fontface
->weight
= data
->weight
;
4380 fontface
->style
= data
->style
;
4381 fontface
->stretch
= data
->stretch
;
4382 fontface
->panose
= data
->panose
;
4383 fontface
->lf
= data
->lf
;
4385 IDWriteLocalizedStrings_Release(names
);
4386 release_font_data(data
);
4389 fontface
->cached
= factory_cache_fontface(cached_list
, &fontface
->IDWriteFontFace4_iface
);
4390 IDWriteFactory5_AddRef(fontface
->factory
= desc
->factory
);
4392 *ret
= &fontface
->IDWriteFontFace4_iface
;
4396 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4403 struct local_cached_stream
4406 IDWriteFontFileStream
*stream
;
4407 struct local_refkey
*key
;
4411 struct dwrite_localfontfilestream
4413 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4416 struct local_cached_stream
*entry
;
4417 const void *file_ptr
;
4421 struct dwrite_localfontfileloader
{
4422 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4425 struct list streams
;
4428 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4430 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4433 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4435 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4438 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4440 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4441 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4442 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
4445 IDWriteFontFileStream_AddRef(iface
);
4450 return E_NOINTERFACE
;
4453 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4455 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4456 ULONG ref
= InterlockedIncrement(&This
->ref
);
4457 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4461 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4463 list_remove(&stream
->entry
);
4464 heap_free(stream
->key
);
4468 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4470 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4471 ULONG ref
= InterlockedDecrement(&This
->ref
);
4473 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4476 UnmapViewOfFile(This
->file_ptr
);
4477 release_cached_stream(This
->entry
);
4484 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
4485 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4487 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4489 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
4490 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4492 *fragment_context
= NULL
;
4494 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4495 *fragment_start
= NULL
;
4499 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4503 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4505 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4506 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4509 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4511 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4512 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4517 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4519 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4522 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4524 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4525 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4526 *last_writetime
= li
.QuadPart
;
4531 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4533 localfontfilestream_QueryInterface
,
4534 localfontfilestream_AddRef
,
4535 localfontfilestream_Release
,
4536 localfontfilestream_ReadFileFragment
,
4537 localfontfilestream_ReleaseFileFragment
,
4538 localfontfilestream_GetFileSize
,
4539 localfontfilestream_GetLastWriteTime
4542 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4544 struct dwrite_localfontfilestream
*This
;
4548 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4550 return E_OUTOFMEMORY
;
4552 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4555 This
->file_ptr
= file_ptr
;
4557 This
->entry
= entry
;
4559 *ret
= &This
->IDWriteFontFileStream_iface
;
4563 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4565 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4567 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4569 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
4572 IDWriteLocalFontFileLoader_AddRef(iface
);
4577 return E_NOINTERFACE
;
4580 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4582 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4583 ULONG ref
= InterlockedIncrement(&This
->ref
);
4584 TRACE("(%p)->(%d)\n", This
, ref
);
4588 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4590 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4591 ULONG ref
= InterlockedDecrement(&This
->ref
);
4593 TRACE("(%p)->(%d)\n", This
, ref
);
4596 struct local_cached_stream
*stream
, *stream2
;
4598 /* This will detach all entries from cache. Entries are released together with streams,
4599 so stream controls cache entry lifetime. */
4600 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
4601 list_init(&stream
->entry
);
4609 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
4611 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4612 const struct local_refkey
*refkey
= key
;
4613 struct local_cached_stream
*stream
;
4614 IDWriteFontFileStream
*filestream
;
4615 HANDLE file
, mapping
;
4620 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
4621 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4623 /* search cache first */
4624 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4625 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4626 *ret
= stream
->stream
;
4627 IDWriteFontFileStream_AddRef(*ret
);
4634 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4635 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4636 if (file
== INVALID_HANDLE_VALUE
)
4639 GetFileSizeEx(file
, &size
);
4640 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4645 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4646 CloseHandle(mapping
);
4648 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
4652 stream
= heap_alloc(sizeof(*stream
));
4654 UnmapViewOfFile(file_ptr
);
4655 return E_OUTOFMEMORY
;
4658 stream
->key
= heap_alloc(key_size
);
4660 UnmapViewOfFile(file_ptr
);
4662 return E_OUTOFMEMORY
;
4665 stream
->key_size
= key_size
;
4666 memcpy(stream
->key
, key
, key_size
);
4668 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4670 UnmapViewOfFile(file_ptr
);
4671 heap_free(stream
->key
);
4676 stream
->stream
= filestream
;
4677 list_add_head(&This
->streams
, &stream
->entry
);
4679 *ret
= stream
->stream
;
4684 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4686 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4687 const struct local_refkey
*refkey
= key
;
4689 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4691 *length
= strlenW(refkey
->name
);
4695 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4697 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4698 const struct local_refkey
*refkey
= key
;
4700 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4702 if (length
< strlenW(refkey
->name
))
4703 return E_INVALIDARG
;
4705 strcpyW(path
, refkey
->name
);
4709 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
4711 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4712 const struct local_refkey
*refkey
= key
;
4714 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
4716 *writetime
= refkey
->writetime
;
4720 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4721 localfontfileloader_QueryInterface
,
4722 localfontfileloader_AddRef
,
4723 localfontfileloader_Release
,
4724 localfontfileloader_CreateStreamFromKey
,
4725 localfontfileloader_GetFilePathLengthFromKey
,
4726 localfontfileloader_GetFilePathFromKey
,
4727 localfontfileloader_GetLastWriteTimeFromKey
4730 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
**ret
)
4732 struct dwrite_localfontfileloader
*This
;
4736 This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
4738 return E_OUTOFMEMORY
;
4740 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4742 list_init(&This
->streams
);
4744 *ret
= &This
->IDWriteLocalFontFileLoader_iface
;
4748 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4750 struct local_refkey
*refkey
;
4753 return E_INVALIDARG
;
4755 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4758 refkey
= heap_alloc(*size
);
4760 return E_OUTOFMEMORY
;
4763 refkey
->writetime
= *writetime
;
4765 WIN32_FILE_ATTRIBUTE_DATA info
;
4767 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4768 refkey
->writetime
= info
.ftLastWriteTime
;
4770 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4772 strcpyW(refkey
->name
, path
);
4779 /* IDWriteGlyphRunAnalysis */
4780 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4782 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4784 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4786 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4787 IsEqualIID(riid
, &IID_IUnknown
))
4790 IDWriteGlyphRunAnalysis_AddRef(iface
);
4795 return E_NOINTERFACE
;
4798 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4800 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4801 ULONG ref
= InterlockedIncrement(&This
->ref
);
4802 TRACE("(%p)->(%u)\n", This
, ref
);
4806 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4808 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4809 ULONG ref
= InterlockedDecrement(&This
->ref
);
4811 TRACE("(%p)->(%u)\n", This
, ref
);
4814 if (This
->run
.fontFace
)
4815 IDWriteFontFace_Release(This
->run
.fontFace
);
4816 heap_free(This
->glyphs
);
4817 heap_free(This
->origins
);
4818 heap_free(This
->bitmap
);
4825 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
4829 case DWRITE_RENDERING_MODE1_NATURAL
:
4830 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
4831 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
4838 static UINT32
get_glyph_bitmap_pitch(DWRITE_TEXTURE_TYPE type
, INT width
)
4840 return type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? (width
+ 3) / 4 * 4 :
4841 ((width
+ 31) >> 5) << 2;
4844 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4846 struct dwrite_glyphbitmap glyph_bitmap
;
4847 IDWriteFontFace4
*fontface
;
4851 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4852 *bounds
= analysis
->bounds
;
4856 if (analysis
->run
.isSideways
)
4857 FIXME("sideways runs are not supported.\n");
4859 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
4861 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
4863 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4864 glyph_bitmap
.fontface
= fontface
;
4865 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
4866 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
4867 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4868 glyph_bitmap
.m
= &analysis
->m
;
4870 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4871 RECT
*bbox
= &glyph_bitmap
.bbox
;
4874 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4875 freetype_get_glyph_bbox(&glyph_bitmap
);
4877 bitmap_size
= get_glyph_bitmap_pitch(analysis
->texture_type
, bbox
->right
- bbox
->left
) *
4878 (bbox
->bottom
- bbox
->top
);
4879 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
4880 analysis
->max_glyph_bitmap_size
= bitmap_size
;
4882 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
4883 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4886 IDWriteFontFace4_Release(fontface
);
4888 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4889 *bounds
= analysis
->bounds
;
4892 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4894 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4896 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4898 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4899 SetRectEmpty(bounds
);
4900 return E_INVALIDARG
;
4903 if (type
!= This
->texture_type
) {
4904 SetRectEmpty(bounds
);
4908 glyphrunanalysis_get_texturebounds(This
, bounds
);
4912 static inline int get_dib_stride( int width
, int bpp
)
4914 return ((width
* bpp
+ 31) >> 3) & ~3;
4917 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4919 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4920 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4921 (runbounds
->left
- bounds
->left
) * 3;
4923 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4924 runbounds
->left
- bounds
->left
;
4927 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
4929 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4930 struct dwrite_glyphbitmap glyph_bitmap
;
4931 IDWriteFontFace4
*fontface
;
4932 D2D_POINT_2F origin
;
4937 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
4939 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
4943 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4944 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4946 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
4947 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
4948 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
4949 IDWriteFontFace4_Release(fontface
);
4950 return E_OUTOFMEMORY
;
4953 origin
.x
= origin
.y
= 0.0f
;
4955 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4956 glyph_bitmap
.fontface
= fontface
;
4957 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
4958 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
4959 glyph_bitmap
.type
= analysis
->texture_type
;
4960 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4961 glyph_bitmap
.m
= &analysis
->m
;
4962 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
4963 IDWriteFontFace4_Release(fontface
);
4964 return E_OUTOFMEMORY
;
4967 bbox
= &glyph_bitmap
.bbox
;
4969 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4970 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
4971 int x
, y
, width
, height
;
4974 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4975 freetype_get_glyph_bbox(&glyph_bitmap
);
4977 if (IsRectEmpty(bbox
))
4980 width
= bbox
->right
- bbox
->left
;
4981 height
= bbox
->bottom
- bbox
->top
;
4983 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->texture_type
, width
);
4984 memset(src
, 0, height
* glyph_bitmap
.pitch
);
4985 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4987 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
4989 /* blit to analysis bitmap */
4990 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
4993 /* convert 1bpp to 8bpp/24bpp */
4994 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4995 for (y
= 0; y
< height
; y
++) {
4996 for (x
= 0; x
< width
; x
++)
4997 if (src
[x
/ 8] & masks
[x
% 8])
4998 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4999 src
+= glyph_bitmap
.pitch
;
5000 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5004 for (y
= 0; y
< height
; y
++) {
5005 for (x
= 0; x
< width
; x
++)
5006 if (src
[x
/ 8] & masks
[x
% 8])
5007 dst
[x
] = DWRITE_ALPHA_MAX
;
5008 src
+= get_dib_stride(width
, 1);
5009 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5014 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
5015 for (y
= 0; y
< height
; y
++) {
5016 for (x
= 0; x
< width
; x
++)
5017 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5018 src
+= glyph_bitmap
.pitch
;
5019 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5023 heap_free(glyph_bitmap
.buf
);
5025 IDWriteFontFace4_Release(fontface
);
5027 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5029 /* we don't need this anymore */
5030 heap_free(analysis
->glyphs
);
5031 heap_free(analysis
->origins
);
5032 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5034 analysis
->glyphs
= NULL
;
5035 analysis
->origins
= NULL
;
5036 analysis
->run
.glyphIndices
= NULL
;
5037 analysis
->run
.fontFace
= NULL
;
5042 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5043 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5045 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5049 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5051 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5052 return E_INVALIDARG
;
5054 /* make sure buffer is large enough for requested texture type */
5055 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5056 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5059 if (size
< required
)
5060 return E_NOT_SUFFICIENT_BUFFER
;
5062 /* validate requested texture type */
5063 if (This
->texture_type
!= type
)
5064 return DWRITE_E_UNSUPPORTEDOPERATION
;
5066 memset(bitmap
, 0, size
);
5067 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5068 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5069 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5070 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5071 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5072 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5076 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5079 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5083 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5084 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5086 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5087 memcpy(dst
, src
, draw_width
);
5096 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5097 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5099 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5101 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5104 return E_INVALIDARG
;
5106 switch (This
->rendering_mode
)
5108 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5109 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5112 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5113 *gamma
= (FLOAT
)value
/ 1000.0f
;
5115 *cleartypelevel
= 1.0f
;
5118 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5119 WARN("Downsampled mode is ignored.\n");
5121 case DWRITE_RENDERING_MODE1_ALIASED
:
5122 case DWRITE_RENDERING_MODE1_NATURAL
:
5123 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5124 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5125 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5126 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5135 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5136 glyphrunanalysis_QueryInterface
,
5137 glyphrunanalysis_AddRef
,
5138 glyphrunanalysis_Release
,
5139 glyphrunanalysis_GetAlphaTextureBounds
,
5140 glyphrunanalysis_CreateAlphaTexture
,
5141 glyphrunanalysis_GetAlphaBlendParams
5144 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5147 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5148 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5152 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5154 struct dwrite_glyphrunanalysis
*analysis
;
5155 DWRITE_FONT_METRICS metrics
;
5156 IDWriteFontFace1
*fontface1
;
5157 D2D_POINT_2F origin
;
5164 /* check for valid rendering mode */
5165 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5166 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5167 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5168 return E_INVALIDARG
;
5170 analysis
= heap_alloc(sizeof(*analysis
));
5172 return E_OUTOFMEMORY
;
5174 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5176 analysis
->rendering_mode
= desc
->rendering_mode
;
5178 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
)
5179 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5181 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5183 analysis
->flags
= 0;
5184 analysis
->bitmap
= NULL
;
5185 analysis
->max_glyph_bitmap_size
= 0;
5186 SetRectEmpty(&analysis
->bounds
);
5187 analysis
->run
= *desc
->run
;
5188 analysis
->run
.fontEmSize
*= desc
->ppdip
;
5189 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5190 analysis
->glyphs
= heap_alloc(desc
->run
->glyphCount
* sizeof(*analysis
->glyphs
));
5191 analysis
->origins
= heap_alloc(desc
->run
->glyphCount
* sizeof(*analysis
->origins
));
5193 if (!analysis
->glyphs
|| !analysis
->origins
) {
5194 heap_free(analysis
->glyphs
);
5195 heap_free(analysis
->origins
);
5197 analysis
->glyphs
= NULL
;
5198 analysis
->origins
= NULL
;
5200 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5201 return E_OUTOFMEMORY
;
5204 /* check if transform is usable */
5205 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5206 analysis
->m
= *desc
->transform
;
5207 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5210 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5212 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5213 analysis
->run
.glyphAdvances
= NULL
;
5214 analysis
->run
.glyphOffsets
= NULL
;
5216 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5218 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5220 IDWriteFontFace_GetMetrics(desc
->run
->fontFace
, &metrics
);
5221 if (FAILED(hr
= IDWriteFontFace_QueryInterface(desc
->run
->fontFace
, &IID_IDWriteFontFace1
, (void **)&fontface1
)))
5222 WARN("Failed to get IDWriteFontFace1, %#x.\n", hr
);
5224 origin
.x
= desc
->origin_x
* desc
->ppdip
;
5225 origin
.y
= desc
->origin_y
* desc
->ppdip
;
5226 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5229 /* Use nominal advances if not provided by caller. */
5230 if (desc
->run
->glyphAdvances
)
5231 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
] * desc
->ppdip
;
5236 switch (desc
->measuring_mode
)
5238 case DWRITE_MEASURING_MODE_NATURAL
:
5239 if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, desc
->run
->glyphIndices
+ i
, &a
,
5240 desc
->run
->isSideways
)))
5241 advance
= rtl_factor
* get_scaled_advance_width(a
, desc
->run
->fontEmSize
, &metrics
) * desc
->ppdip
;
5243 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5244 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5245 if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, desc
->run
->fontEmSize
,
5246 desc
->ppdip
, desc
->transform
, desc
->measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
,
5247 desc
->run
->isSideways
, 1, desc
->run
->glyphIndices
+ i
, &a
)))
5248 advance
= rtl_factor
* floorf(a
* desc
->run
->fontEmSize
* desc
->ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
);
5255 analysis
->origins
[i
] = origin
;
5257 /* Offsets are optional, appled to pre-transformed origin. */
5258 if (desc
->run
->glyphOffsets
) {
5259 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
* desc
->ppdip
;
5260 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
* desc
->ppdip
;
5262 if (desc
->run
->isSideways
) {
5263 analysis
->origins
[i
].x
+= ascenderoffset
;
5264 analysis
->origins
[i
].y
+= advanceoffset
;
5267 analysis
->origins
[i
].x
+= advanceoffset
;
5268 analysis
->origins
[i
].y
+= ascenderoffset
;
5272 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5273 transform_point(analysis
->origins
+ i
, &analysis
->m
);
5275 if (desc
->run
->isSideways
)
5276 origin
.y
+= advance
;
5278 origin
.x
+= advance
;
5281 IDWriteFontFace1_Release(fontface1
);
5283 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5287 /* IDWriteColorGlyphRunEnumerator */
5288 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
5290 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5292 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5294 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5295 IsEqualIID(riid
, &IID_IUnknown
))
5298 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
5303 return E_NOINTERFACE
;
5306 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
5308 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5309 ULONG ref
= InterlockedIncrement(&This
->ref
);
5310 TRACE("(%p)->(%u)\n", This
, ref
);
5314 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
5316 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5317 ULONG ref
= InterlockedDecrement(&This
->ref
);
5319 TRACE("(%p)->(%u)\n", This
, ref
);
5322 heap_free(This
->advances
);
5323 heap_free(This
->color_advances
);
5324 heap_free(This
->offsets
);
5325 heap_free(This
->color_offsets
);
5326 heap_free(This
->glyphindices
);
5327 heap_free(This
->glyphs
);
5328 if (This
->colr
.context
)
5329 IDWriteFontFace4_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
5330 IDWriteFontFace4_Release(This
->fontface
);
5337 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5339 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5340 FLOAT origin
= 0.0f
;
5346 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5350 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5352 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5353 FLOAT advance_adj
= 0.0f
;
5354 BOOL got_palette_index
;
5357 /* start with regular glyphs */
5358 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5359 UINT32 first_glyph
= 0;
5361 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5362 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5363 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5364 first_glyph
= min(first_glyph
, g
);
5367 glyphenum
->glyphindices
[g
] = 1;
5368 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5369 if (glyphenum
->color_offsets
)
5370 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5373 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5374 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5375 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5376 colorrun
->paletteIndex
= 0xffff;
5377 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5378 glyphenum
->has_regular_glyphs
= FALSE
;
5382 colorrun
->glyphRun
.glyphCount
= 0;
5383 got_palette_index
= FALSE
;
5387 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5389 glyphenum
->glyphindices
[g
] = 1;
5391 /* all glyph layers were returned */
5392 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5393 advance_adj
+= glyphenum
->advances
[g
];
5397 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5398 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5399 if (!got_palette_index
) {
5400 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5401 /* use foreground color or request one from the font */
5402 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5403 if (colorrun
->paletteIndex
!= 0xffff) {
5404 HRESULT hr
= IDWriteFontFace4_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5405 1, &colorrun
->runColor
);
5407 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5408 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5410 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5411 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5412 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5413 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5414 got_palette_index
= TRUE
;
5417 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5418 /* offsets are relative to glyph origin, nothing to fix up */
5419 if (glyphenum
->color_offsets
)
5420 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5421 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5423 glyphenum
->color_advances
[index
-1] += advance_adj
;
5424 colorrun
->glyphRun
.glyphCount
++;
5428 advance_adj
+= glyphenum
->advances
[g
];
5431 /* reset last advance */
5432 if (colorrun
->glyphRun
.glyphCount
)
5433 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5435 return colorrun
->glyphRun
.glyphCount
> 0;
5438 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5440 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5442 TRACE("(%p)->(%p)\n", This
, has_run
);
5446 This
->colorrun
.glyphRun
.glyphCount
= 0;
5447 while (This
->current_layer
< This
->max_layer_num
) {
5448 if (colorglyphenum_build_color_run(This
))
5451 This
->current_layer
++;
5454 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5459 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5461 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5463 TRACE("(%p)->(%p)\n", This
, run
);
5465 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5467 return E_NOT_VALID_STATE
;
5470 *run
= &This
->colorrun
;
5474 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5475 colorglyphenum_QueryInterface
,
5476 colorglyphenum_AddRef
,
5477 colorglyphenum_Release
,
5478 colorglyphenum_MoveNext
,
5479 colorglyphenum_GetCurrentRun
5482 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5483 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5485 struct dwrite_colorglyphenum
*colorglyphenum
;
5486 BOOL colorfont
, has_colored_glyph
;
5487 IDWriteFontFace4
*fontface
;
5493 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace4
, (void**)&fontface
);
5495 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5499 colorfont
= IDWriteFontFace4_IsColorFont(fontface
) && IDWriteFontFace4_GetColorPaletteCount(fontface
) > palette
;
5501 hr
= DWRITE_E_NOCOLOR
;
5505 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5506 if (!colorglyphenum
) {
5511 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5512 colorglyphenum
->ref
= 1;
5513 colorglyphenum
->origin_x
= originX
;
5514 colorglyphenum
->origin_y
= originY
;
5515 colorglyphenum
->fontface
= fontface
;
5516 colorglyphenum
->glyphs
= NULL
;
5517 colorglyphenum
->run
= *run
;
5518 colorglyphenum
->run
.glyphIndices
= NULL
;
5519 colorglyphenum
->run
.glyphAdvances
= NULL
;
5520 colorglyphenum
->run
.glyphOffsets
= NULL
;
5521 colorglyphenum
->palette
= palette
;
5522 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5523 colorglyphenum
->colr
.exists
= TRUE
;
5524 get_fontface_table(fontface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5525 colorglyphenum
->current_layer
= 0;
5526 colorglyphenum
->max_layer_num
= 0;
5528 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5530 has_colored_glyph
= FALSE
;
5531 colorglyphenum
->has_regular_glyphs
= FALSE
;
5532 for (i
= 0; i
< run
->glyphCount
; i
++) {
5533 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5534 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5535 has_colored_glyph
= TRUE
;
5537 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5538 colorglyphenum
->has_regular_glyphs
= TRUE
;
5541 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5542 is supposed to proceed normally, like if font had no color info at all. */
5543 if (!has_colored_glyph
) {
5544 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5545 return DWRITE_E_NOCOLOR
;
5548 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5549 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5550 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5551 if (run
->glyphOffsets
) {
5552 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5553 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5554 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5557 colorglyphenum
->colorrun
.glyphRun
.fontFace
= (IDWriteFontFace
*)fontface
;
5558 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
5559 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5560 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5561 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5562 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5564 if (run
->glyphAdvances
)
5565 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5567 DWRITE_FONT_METRICS metrics
;
5569 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5570 for (i
= 0; i
< run
->glyphCount
; i
++) {
5574 switch (measuring_mode
)
5576 case DWRITE_MEASURING_MODE_NATURAL
:
5577 hr
= IDWriteFontFace4_GetDesignGlyphAdvances(fontface
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5580 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5582 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5583 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5584 hr
= IDWriteFontFace4_GetGdiCompatibleGlyphAdvances(fontface
, run
->fontEmSize
, 1.0f
, transform
,
5585 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5587 colorglyphenum
->advances
[i
] = 0.0f
;
5589 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5597 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5601 IDWriteFontFace4_Release(fontface
);
5605 /* IDWriteFontFaceReference */
5606 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
5608 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5610 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5612 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) || IsEqualIID(riid
, &IID_IUnknown
)) {
5614 IDWriteFontFaceReference_AddRef(iface
);
5620 return E_NOINTERFACE
;
5623 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference
*iface
)
5625 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5626 ULONG ref
= InterlockedIncrement(&This
->ref
);
5627 TRACE("(%p)->(%u)\n", This
, ref
);
5631 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference
*iface
)
5633 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5634 ULONG ref
= InterlockedDecrement(&This
->ref
);
5636 TRACE("(%p)->(%u)\n", This
, ref
);
5639 IDWriteFontFile_Release(This
->file
);
5640 IDWriteFactory5_Release(This
->factory
);
5647 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference
*iface
, IDWriteFontFace3
**fontface
)
5649 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5651 TRACE("(%p)->(%p)\n", This
, fontface
);
5653 return IDWriteFontFaceReference_CreateFontFaceWithSimulations(iface
, This
->simulations
, fontface
);
5656 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
5657 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
5659 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5660 DWRITE_FONT_FILE_TYPE file_type
;
5661 DWRITE_FONT_FACE_TYPE face_type
;
5662 IDWriteFontFace
*fontface
;
5667 TRACE("(%p)->(%d %p)\n", This
, simulations
, ret
);
5669 hr
= IDWriteFontFile_Analyze(This
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
5673 hr
= IDWriteFactory5_CreateFontFace(This
->factory
, face_type
, 1, &This
->file
, This
->index
, simulations
, &fontface
);
5674 if (SUCCEEDED(hr
)) {
5675 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
5676 IDWriteFontFace_Release(fontface
);
5682 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
5684 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5685 IDWriteFontFile
*file
;
5688 TRACE("(%p)->(%p)\n", This
, ref
);
5690 if (FAILED(IDWriteFontFaceReference_GetFontFile(ref
, &file
)))
5693 ret
= is_same_fontfile(This
->file
, file
) &&
5694 This
->index
== IDWriteFontFaceReference_GetFontFaceIndex(ref
) &&
5695 This
->simulations
== IDWriteFontFaceReference_GetSimulations(ref
);
5696 IDWriteFontFile_Release(file
);
5701 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
5703 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5705 TRACE("(%p)\n", This
);
5710 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference
*iface
)
5712 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5714 TRACE("(%p)\n", This
);
5716 return This
->simulations
;
5719 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
5721 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5722 IDWriteFontFileLoader
*loader
;
5727 TRACE("(%p)->(%p)\n", This
, file
);
5729 hr
= IDWriteFontFile_GetReferenceKey(This
->file
, &key
, &key_size
);
5733 hr
= IDWriteFontFile_GetLoader(This
->file
, &loader
);
5737 hr
= IDWriteFactory5_CreateCustomFontFileReference(This
->factory
, key
, key_size
, loader
, file
);
5738 IDWriteFontFileLoader_Release(loader
);
5743 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
5745 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5747 FIXME("(%p): stub\n", This
);
5752 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference
*iface
)
5754 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5756 FIXME("(%p): stub\n", This
);
5761 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
5763 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5765 FIXME("(%p)->(%p): stub\n", This
, writetime
);
5770 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference
*iface
)
5772 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5774 FIXME("(%p): stub\n", This
);
5776 return DWRITE_LOCALITY_LOCAL
;
5779 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
5781 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5783 FIXME("(%p): stub\n", This
);
5788 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
, WCHAR
const *chars
,
5791 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5793 FIXME("(%p)->(%s:%u): stub\n", This
, debugstr_wn(chars
, count
), count
);
5798 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
, UINT16
const *glyphs
,
5801 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5803 FIXME("(%p)->(%p %u): stub\n", This
, glyphs
, count
);
5808 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
5809 UINT64 offset
, UINT64 size
)
5811 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5813 FIXME("(%p)->(0x%s 0x%s): stub\n", This
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
5818 static const IDWriteFontFaceReferenceVtbl fontfacereferencevtbl
= {
5819 fontfacereference_QueryInterface
,
5820 fontfacereference_AddRef
,
5821 fontfacereference_Release
,
5822 fontfacereference_CreateFontFace
,
5823 fontfacereference_CreateFontFaceWithSimulations
,
5824 fontfacereference_Equals
,
5825 fontfacereference_GetFontFaceIndex
,
5826 fontfacereference_GetSimulations
,
5827 fontfacereference_GetFontFile
,
5828 fontfacereference_GetLocalFileSize
,
5829 fontfacereference_GetFileSize
,
5830 fontfacereference_GetFileTime
,
5831 fontfacereference_GetLocality
,
5832 fontfacereference_EnqueueFontDownloadRequest
,
5833 fontfacereference_EnqueueCharacterDownloadRequest
,
5834 fontfacereference_EnqueueGlyphDownloadRequest
,
5835 fontfacereference_EnqueueFileFragmentDownloadRequest
5838 HRESULT
create_fontfacereference(IDWriteFactory5
*factory
, IDWriteFontFile
*file
, UINT32 index
,
5839 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFaceReference
**ret
)
5841 struct dwrite_fontfacereference
*ref
;
5845 if (!is_simulation_valid(simulations
))
5846 return E_INVALIDARG
;
5848 ref
= heap_alloc(sizeof(*ref
));
5850 return E_OUTOFMEMORY
;
5852 ref
->IDWriteFontFaceReference_iface
.lpVtbl
= &fontfacereferencevtbl
;
5855 ref
->factory
= factory
;
5856 IDWriteFactory5_AddRef(ref
->factory
);
5858 IDWriteFontFile_AddRef(ref
->file
);
5860 ref
->simulations
= simulations
;
5861 *ret
= &ref
->IDWriteFontFaceReference_iface
;