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 FONTSIGNATURE fontsig
;
80 struct dwrite_font_propvec propvec
;
82 DWRITE_FONT_METRICS1 metrics
;
83 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
84 IDWriteLocalizedStrings
*names
;
86 /* data needed to create fontface instance */
87 DWRITE_FONT_FACE_TYPE face_type
;
88 IDWriteFontFile
*file
;
97 /* used to mark font as tested when scanning for simulation candidate */
98 BOOL bold_sim_tested
: 1;
99 BOOL oblique_sim_tested
: 1;
102 struct dwrite_fontfamily_data
{
105 IDWriteLocalizedStrings
*familyname
;
107 struct dwrite_font_data
**fonts
;
110 BOOL has_normal_face
: 1;
111 BOOL has_oblique_face
: 1;
112 BOOL has_italic_face
: 1;
115 struct dwrite_fontcollection
{
116 IDWriteFontCollection1 IDWriteFontCollection1_iface
;
119 IDWriteFactory5
*factory
;
120 struct dwrite_fontfamily_data
**family_data
;
125 struct dwrite_fontfamily
{
126 IDWriteFontFamily1 IDWriteFontFamily1_iface
;
129 struct dwrite_fontfamily_data
*data
;
130 struct dwrite_fontcollection
*collection
;
133 struct dwrite_fontlist
{
134 IDWriteFontList1 IDWriteFontList1_iface
;
137 struct dwrite_font_data
**fonts
;
139 struct dwrite_fontfamily
*family
;
143 IDWriteFont3 IDWriteFont3_iface
;
146 DWRITE_FONT_STYLE style
;
147 struct dwrite_font_data
*data
;
148 struct dwrite_fontfamily
*family
;
151 struct dwrite_fonttable
{
158 enum runanalysis_flags
{
159 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
160 RUNANALYSIS_BITMAP_READY
= 1 << 1,
161 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
164 struct dwrite_glyphrunanalysis
{
165 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
168 DWRITE_RENDERING_MODE1 rendering_mode
;
169 DWRITE_TEXTURE_TYPE texture_type
; /* derived from rendering mode specified on creation */
170 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
173 D2D_POINT_2F
*origins
;
178 UINT32 max_glyph_bitmap_size
;
181 struct dwrite_colorglyphenum
{
182 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
185 FLOAT origin_x
; /* original run origin */
188 IDWriteFontFace4
*fontface
; /* for convenience */
189 DWRITE_COLOR_GLYPH_RUN colorrun
; /* returned with GetCurrentRun() */
190 DWRITE_GLYPH_RUN run
; /* base run */
191 UINT32 palette
; /* palette index to get layer color from */
192 FLOAT
*advances
; /* original or measured advances for base glyphs */
193 FLOAT
*color_advances
; /* returned color run points to this */
194 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
195 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
196 UINT16
*glyphindices
; /* returned color run points to this */
197 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
198 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
199 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
200 UINT16 max_layer_num
; /* max number of layers for this run */
201 struct dwrite_fonttable colr
; /* used to access layers */
204 #define GLYPH_BLOCK_SHIFT 8
205 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
206 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
207 #define GLYPH_MAX 65536
209 enum fontface_flags
{
210 FONTFACE_IS_SYMBOL
= 1 << 0,
211 FONTFACE_IS_MONOSPACED
= 1 << 1,
212 FONTFACE_HAS_KERNING_PAIRS
= 1 << 2,
213 FONTFACE_HAS_VERTICAL_VARIANTS
= 1 << 3
216 struct dwrite_fontface
{
217 IDWriteFontFace4 IDWriteFontFace4_iface
;
220 IDWriteFontFileStream
*stream
;
221 IDWriteFontFile
**files
;
225 IDWriteFactory5
*factory
;
226 struct fontfacecached
*cached
;
229 DWRITE_FONT_FACE_TYPE type
;
230 DWRITE_FONT_METRICS1 metrics
;
231 DWRITE_CARET_METRICS caret
;
235 struct dwrite_fonttable cmap
;
236 struct dwrite_fonttable vdmx
;
237 struct dwrite_fonttable gasp
;
238 struct dwrite_fonttable cpal
;
239 struct dwrite_fonttable colr
;
240 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
242 DWRITE_FONT_STYLE style
;
243 DWRITE_FONT_STRETCH stretch
;
244 DWRITE_FONT_WEIGHT weight
;
245 DWRITE_PANOSE panose
;
246 FONTSIGNATURE fontsig
;
247 UINT32 glyph_image_formats
;
252 struct dwrite_fontfile
{
253 IDWriteFontFile IDWriteFontFile_iface
;
256 IDWriteFontFileLoader
*loader
;
259 IDWriteFontFileStream
*stream
;
262 struct dwrite_fontfacereference
{
263 IDWriteFontFaceReference IDWriteFontFaceReference_iface
;
266 IDWriteFontFile
*file
;
269 IDWriteFactory5
*factory
;
272 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace4(IDWriteFontFace4
*iface
)
274 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace4_iface
);
277 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
279 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
282 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
284 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
287 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
289 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
292 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection1(IDWriteFontCollection1
*iface
)
294 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection1_iface
);
297 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
299 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
302 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
304 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
307 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList1(IDWriteFontList1
*iface
)
309 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList1_iface
);
312 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
314 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference_iface
);
317 static inline const char *debugstr_tag(UINT32 tag
)
319 return debugstr_an((char*)&tag
, 4);
322 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
324 static const DWRITE_GLYPH_METRICS nil
;
325 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
327 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
328 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
332 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
334 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
337 /* start new block */
338 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
340 return E_OUTOFMEMORY
;
343 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
347 static void* get_fontface_table(IDWriteFontFace4
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
351 if (table
->data
|| !table
->exists
)
354 table
->exists
= FALSE
;
355 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
357 if (FAILED(hr
) || !table
->exists
) {
358 TRACE("Font does not have %s table\n", debugstr_tag(tag
));
365 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
366 struct dwrite_font_propvec
*vec
)
368 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
369 vec
->style
= style
* 7.0f
;
370 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
373 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
375 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
378 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
380 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
383 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
385 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
388 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
390 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
393 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
395 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_GASP_TAG
, &fontface
->gasp
);
396 *size
= fontface
->gasp
.size
;
400 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
402 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
405 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
407 return get_fontface_table(&fontface
->IDWriteFontFace4_iface
, MS_COLR_TAG
, &fontface
->colr
);
410 static void addref_font_data(struct dwrite_font_data
*data
)
412 InterlockedIncrement(&data
->ref
);
415 static void release_font_data(struct dwrite_font_data
*data
)
419 if (InterlockedDecrement(&data
->ref
) > 0)
422 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
423 if (data
->info_strings
[i
])
424 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
427 IDWriteLocalizedStrings_Release(data
->names
);
429 IDWriteFontFile_Release(data
->file
);
430 heap_free(data
->facename
);
434 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
438 if (InterlockedDecrement(&data
->ref
) > 0)
441 for (i
= 0; i
< data
->font_count
; i
++)
442 release_font_data(data
->fonts
[i
]);
443 heap_free(data
->fonts
);
444 IDWriteLocalizedStrings_Release(data
->familyname
);
448 void fontface_detach_from_cache(IDWriteFontFace4
*iface
)
450 struct dwrite_fontface
*fontface
= impl_from_IDWriteFontFace4(iface
);
451 fontface
->cached
= NULL
;
454 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace4
*iface
, REFIID riid
, void **obj
)
456 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
458 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
460 if (IsEqualIID(riid
, &IID_IDWriteFontFace4
) ||
461 IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
462 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
463 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
464 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
465 IsEqualIID(riid
, &IID_IUnknown
))
468 if (InterlockedIncrement(&This
->ref
) == 1) {
469 InterlockedDecrement(&This
->ref
);
476 WARN("%s not implemented.\n", debugstr_guid(riid
));
479 return E_NOINTERFACE
;
482 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace4
*iface
)
484 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
485 ULONG ref
= InterlockedIncrement(&This
->ref
);
486 TRACE("(%p)->(%d)\n", This
, ref
);
490 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace4
*iface
)
492 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
493 ULONG ref
= InterlockedDecrement(&This
->ref
);
495 TRACE("(%p)->(%d)\n", This
, ref
);
501 factory_lock(This
->factory
);
502 list_remove(&This
->cached
->entry
);
503 factory_unlock(This
->factory
);
504 heap_free(This
->cached
);
507 if (This
->cmap
.context
)
508 IDWriteFontFace4_ReleaseFontTable(iface
, This
->cmap
.context
);
509 if (This
->vdmx
.context
)
510 IDWriteFontFace4_ReleaseFontTable(iface
, This
->vdmx
.context
);
511 if (This
->gasp
.context
)
512 IDWriteFontFace4_ReleaseFontTable(iface
, This
->gasp
.context
);
513 if (This
->cpal
.context
)
514 IDWriteFontFace4_ReleaseFontTable(iface
, This
->cpal
.context
);
515 if (This
->colr
.context
)
516 IDWriteFontFace4_ReleaseFontTable(iface
, This
->colr
.context
);
517 for (i
= 0; i
< This
->file_count
; i
++) {
519 IDWriteFontFile_Release(This
->files
[i
]);
522 IDWriteFontFileStream_Release(This
->stream
);
523 heap_free(This
->files
);
525 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
526 heap_free(This
->glyphs
[i
]);
528 freetype_notify_cacheremove(iface
);
530 IDWriteFactory5_Release(This
->factory
);
537 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace4
*iface
)
539 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
540 TRACE("(%p)\n", This
);
544 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace4
*iface
, UINT32
*number_of_files
,
545 IDWriteFontFile
**fontfiles
)
547 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
550 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
551 if (fontfiles
== NULL
)
553 *number_of_files
= This
->file_count
;
556 if (*number_of_files
< This
->file_count
)
559 for (i
= 0; i
< This
->file_count
; i
++)
561 IDWriteFontFile_AddRef(This
->files
[i
]);
562 fontfiles
[i
] = This
->files
[i
];
568 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace4
*iface
)
570 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
571 TRACE("(%p)\n", This
);
575 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace4
*iface
)
577 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
578 TRACE("(%p)\n", This
);
579 return This
->simulations
;
582 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace4
*iface
)
584 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
585 TRACE("(%p)\n", This
);
586 return !!(This
->flags
& FONTFACE_IS_SYMBOL
);
589 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace4
*iface
, DWRITE_FONT_METRICS
*metrics
)
591 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
592 TRACE("(%p)->(%p)\n", This
, metrics
);
593 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
596 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace4
*iface
)
598 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
599 TRACE("(%p)\n", This
);
600 return freetype_get_glyphcount(iface
);
603 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4
*iface
,
604 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
606 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
610 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
616 FIXME("sideways metrics are not supported.\n");
618 for (i
= 0; i
< glyph_count
; i
++) {
619 DWRITE_GLYPH_METRICS metrics
;
621 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
623 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
624 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
634 static HRESULT
fontface_get_glyphs(struct dwrite_fontface
*fontface
, UINT32
const *codepoints
,
635 UINT32 count
, UINT16
*glyphs
)
641 memset(glyphs
, 0, count
* sizeof(*glyphs
));
645 freetype_get_glyphs(&fontface
->IDWriteFontFace4_iface
, fontface
->charmap
, codepoints
, count
, glyphs
);
649 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace4
*iface
, UINT32
const *codepoints
,
650 UINT32 count
, UINT16
*glyphs
)
652 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
654 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyphs
);
656 return fontface_get_glyphs(This
, codepoints
, count
, glyphs
);
659 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace4
*iface
, UINT32 table_tag
,
660 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
662 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
663 struct file_stream_desc stream_desc
;
665 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
667 stream_desc
.stream
= This
->stream
;
668 stream_desc
.face_type
= This
->type
;
669 stream_desc
.face_index
= This
->index
;
670 return opentype_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
673 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace4
*iface
, void *table_context
)
675 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
677 TRACE("(%p)->(%p)\n", This
, table_context
);
679 IDWriteFontFileStream_ReleaseFileFragment(This
->stream
, table_context
);
682 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace4
*iface
, FLOAT emSize
,
683 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
684 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
686 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
688 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
689 count
, is_sideways
, is_rtl
, sink
);
691 if (!glyphs
|| !sink
)
695 FIXME("sideways mode is not supported.\n");
697 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
700 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
701 FLOAT ppem
, WORD gasp
)
703 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
707 case DWRITE_MEASURING_MODE_NATURAL
:
709 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
710 mode
= DWRITE_RENDERING_MODE_NATURAL
;
712 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
715 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
716 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
718 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
719 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
728 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
,
729 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
731 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
736 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
739 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
743 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
744 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
747 ppem
= emSize
* ppdip
;
749 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
750 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
754 ptr
= get_fontface_gasp(This
, &size
);
755 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
756 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
760 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
761 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
763 DWRITE_FONT_METRICS1 metrics1
;
764 HRESULT hr
= IDWriteFontFace4_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
765 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
769 static inline int round_metric(FLOAT metric
)
771 return (int)floorf(metric
+ 0.5f
);
774 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
776 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
779 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
782 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT ppdip
,
783 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
784 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
786 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
787 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
788 DWRITE_MEASURING_MODE mode
;
793 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
794 glyph_count
, metrics
, is_sideways
);
796 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
797 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
799 size
= emSize
* ppdip
;
800 scale
= size
/ This
->metrics
.designUnitsPerEm
;
801 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
803 for (i
= 0; i
< glyph_count
; i
++) {
804 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
805 DWRITE_GLYPH_METRICS design
;
808 hr
= IDWriteFontFace4_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
812 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
814 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
816 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
818 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
819 SCALE_METRIC(leftSideBearing
);
820 SCALE_METRIC(rightSideBearing
);
821 SCALE_METRIC(topSideBearing
);
822 SCALE_METRIC(advanceHeight
);
823 SCALE_METRIC(bottomSideBearing
);
824 SCALE_METRIC(verticalOriginY
);
831 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace4
*iface
, DWRITE_FONT_METRICS1
*metrics
)
833 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
834 TRACE("(%p)->(%p)\n", This
, metrics
);
835 *metrics
= This
->metrics
;
838 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace4
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
839 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
841 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
842 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
843 UINT16 ascent
, descent
;
846 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
848 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
849 memset(metrics
, 0, sizeof(*metrics
));
853 em_size
*= pixels_per_dip
;
854 if (m
&& m
->m22
!= 0.0f
)
855 em_size
*= fabs(m
->m22
);
857 scale
= em_size
/ design
->designUnitsPerEm
;
858 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
859 ascent
= round_metric(design
->ascent
* scale
);
860 descent
= round_metric(design
->descent
* scale
);
863 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
864 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
865 metrics
->ascent
= round_metric(ascent
/ scale
);
866 metrics
->descent
= round_metric(descent
/ scale
);
868 SCALE_METRIC(lineGap
);
869 SCALE_METRIC(capHeight
);
870 SCALE_METRIC(xHeight
);
871 SCALE_METRIC(underlinePosition
);
872 SCALE_METRIC(underlineThickness
);
873 SCALE_METRIC(strikethroughPosition
);
874 SCALE_METRIC(strikethroughThickness
);
875 SCALE_METRIC(glyphBoxLeft
);
876 SCALE_METRIC(glyphBoxTop
);
877 SCALE_METRIC(glyphBoxRight
);
878 SCALE_METRIC(glyphBoxBottom
);
879 SCALE_METRIC(subscriptPositionX
);
880 SCALE_METRIC(subscriptPositionY
);
881 SCALE_METRIC(subscriptSizeX
);
882 SCALE_METRIC(subscriptSizeY
);
883 SCALE_METRIC(superscriptPositionX
);
884 SCALE_METRIC(superscriptPositionY
);
885 SCALE_METRIC(superscriptSizeX
);
886 SCALE_METRIC(superscriptSizeY
);
888 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
894 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace4
*iface
, DWRITE_CARET_METRICS
*metrics
)
896 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
897 TRACE("(%p)->(%p)\n", This
, metrics
);
898 *metrics
= This
->caret
;
901 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace4
*iface
, UINT32 max_count
,
902 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
904 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
906 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
909 if (max_count
&& !ranges
)
912 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
915 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace4
*iface
)
917 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
918 TRACE("(%p)\n", This
);
919 return !!(This
->flags
& FONTFACE_IS_MONOSPACED
);
922 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace4
*iface
,
923 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
925 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
926 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
929 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
932 FIXME("sideways mode not supported\n");
934 for (i
= 0; i
< glyph_count
; i
++) {
937 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
],
938 DWRITE_MEASURING_MODE_NATURAL
, &has_contours
);
940 advances
[i
] += adjustment
;
946 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace4
*iface
,
947 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
948 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
950 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
951 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
952 DWRITE_MEASURING_MODE mode
;
955 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
956 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
958 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
959 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
964 if (em_size
== 0.0f
) {
965 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
969 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
970 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
972 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
973 for (i
= 0; i
< glyph_count
; i
++) {
976 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
, &has_contours
);
978 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
+ adjustment
);
980 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
986 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace4
*iface
, UINT32 count
,
987 const UINT16
*indices
, INT32
*adjustments
)
989 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
992 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
994 if (!(indices
|| adjustments
) || !count
)
997 if (!indices
|| count
== 1) {
998 memset(adjustments
, 0, count
*sizeof(INT32
));
1002 if (!(This
->flags
& FONTFACE_HAS_KERNING_PAIRS
)) {
1003 memset(adjustments
, 0, count
*sizeof(INT32
));
1007 for (i
= 0; i
< count
-1; i
++)
1008 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1009 adjustments
[count
-1] = 0;
1014 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace4
*iface
)
1016 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1017 TRACE("(%p)\n", This
);
1018 return !!(This
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1021 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
,
1022 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1023 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1025 DWRITE_GRID_FIT_MODE gridfitmode
;
1026 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
1027 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1030 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace4
*iface
, UINT32 glyph_count
,
1031 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
1033 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1034 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
1038 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace4
*iface
)
1040 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1041 TRACE("(%p)\n", This
);
1042 return !!(This
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1045 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace4
*iface
)
1047 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1048 TRACE("(%p)\n", This
);
1049 return get_fontface_cpal(This
) && get_fontface_colr(This
);
1052 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace4
*iface
)
1054 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1055 TRACE("(%p)\n", This
);
1056 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
1059 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace4
*iface
)
1061 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1062 TRACE("(%p)\n", This
);
1063 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
1066 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace4
*iface
, UINT32 palette_index
,
1067 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1069 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1070 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
1071 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
1074 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
,
1075 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1076 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1077 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1079 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1084 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1085 measuringmode
, params
, renderingmode
, gridfitmode
);
1088 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1091 FIXME("sideways mode not supported\n");
1093 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1095 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1096 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1098 IDWriteRenderingParams2
*params2
;
1101 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1103 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1104 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1105 IDWriteRenderingParams2_Release(params2
);
1108 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1111 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1113 ptr
= get_fontface_gasp(This
, &size
);
1114 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1116 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1117 if (emSize
>= emthreshold
)
1118 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1120 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1123 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1124 if (emSize
>= emthreshold
)
1125 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1126 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1127 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1129 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1135 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace4
*iface
, IDWriteFontFaceReference
**ref
)
1137 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1138 FIXME("(%p)->(%p): stub\n", This
, ref
);
1142 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace4
*iface
, DWRITE_PANOSE
*panose
)
1144 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1145 TRACE("(%p)->(%p)\n", This
, panose
);
1146 *panose
= This
->panose
;
1149 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace4
*iface
)
1151 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1152 TRACE("(%p)\n", This
);
1153 return This
->weight
;
1156 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace4
*iface
)
1158 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1159 TRACE("(%p)\n", This
);
1160 return This
->stretch
;
1163 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace4
*iface
)
1165 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1166 TRACE("(%p)\n", This
);
1170 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace4
*iface
, IDWriteLocalizedStrings
**names
)
1172 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1173 FIXME("(%p)->(%p): stub\n", This
, names
);
1177 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace4
*iface
, IDWriteLocalizedStrings
**names
)
1179 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1180 FIXME("(%p)->(%p): stub\n", This
, names
);
1184 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace4
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1185 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1187 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1188 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1192 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace4
*iface
, UINT32 ch
)
1194 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1197 TRACE("(%p)->(%#x)\n", This
, ch
);
1200 if (FAILED(fontface_get_glyphs(This
, &ch
, 1, &index
)))
1206 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1207 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1208 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1210 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1215 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1216 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1219 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1222 FIXME("sideways mode not supported\n");
1224 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1226 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1227 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1229 IDWriteRenderingParams3
*params3
;
1232 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1234 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1235 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1236 IDWriteRenderingParams3_Release(params3
);
1239 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1242 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1244 ptr
= get_fontface_gasp(This
, &size
);
1245 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1247 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1248 if (emSize
>= emthreshold
)
1249 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1251 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, gasp
);
1254 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1255 if (emSize
>= emthreshold
)
1256 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1257 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1258 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1260 *gridfit_mode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1266 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace4
*iface
, UINT32 ch
)
1268 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1269 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1273 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace4
*iface
, UINT16 glyph
)
1275 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1276 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1280 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace4
*iface
, WCHAR
const *text
,
1281 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1283 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1284 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1288 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace4
*iface
, UINT16
const *glyphs
,
1289 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1291 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1292 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1296 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace4
*iface
, UINT16 glyph
,
1297 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1299 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1300 FIXME("(%p)->(%u %u %u %p): stub\n", This
, glyph
, ppem_first
, ppem_last
, formats
);
1304 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace4
*iface
)
1306 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1308 TRACE("(%p)\n", This
);
1310 return This
->glyph_image_formats
;
1313 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace4
*iface
, UINT16 glyph
,
1314 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1316 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1317 FIXME("(%p)->(%u %u %d %p %p): stub\n", This
, glyph
, ppem
, format
, data
, context
);
1321 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace4
*iface
, void *context
)
1323 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1324 FIXME("(%p)->(%p): stub\n", This
, context
);
1327 static const IDWriteFontFace4Vtbl dwritefontfacevtbl
= {
1328 dwritefontface_QueryInterface
,
1329 dwritefontface_AddRef
,
1330 dwritefontface_Release
,
1331 dwritefontface_GetType
,
1332 dwritefontface_GetFiles
,
1333 dwritefontface_GetIndex
,
1334 dwritefontface_GetSimulations
,
1335 dwritefontface_IsSymbolFont
,
1336 dwritefontface_GetMetrics
,
1337 dwritefontface_GetGlyphCount
,
1338 dwritefontface_GetDesignGlyphMetrics
,
1339 dwritefontface_GetGlyphIndices
,
1340 dwritefontface_TryGetFontTable
,
1341 dwritefontface_ReleaseFontTable
,
1342 dwritefontface_GetGlyphRunOutline
,
1343 dwritefontface_GetRecommendedRenderingMode
,
1344 dwritefontface_GetGdiCompatibleMetrics
,
1345 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1346 dwritefontface1_GetMetrics
,
1347 dwritefontface1_GetGdiCompatibleMetrics
,
1348 dwritefontface1_GetCaretMetrics
,
1349 dwritefontface1_GetUnicodeRanges
,
1350 dwritefontface1_IsMonospacedFont
,
1351 dwritefontface1_GetDesignGlyphAdvances
,
1352 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1353 dwritefontface1_GetKerningPairAdjustments
,
1354 dwritefontface1_HasKerningPairs
,
1355 dwritefontface1_GetRecommendedRenderingMode
,
1356 dwritefontface1_GetVerticalGlyphVariants
,
1357 dwritefontface1_HasVerticalGlyphVariants
,
1358 dwritefontface2_IsColorFont
,
1359 dwritefontface2_GetColorPaletteCount
,
1360 dwritefontface2_GetPaletteEntryCount
,
1361 dwritefontface2_GetPaletteEntries
,
1362 dwritefontface2_GetRecommendedRenderingMode
,
1363 dwritefontface3_GetFontFaceReference
,
1364 dwritefontface3_GetPanose
,
1365 dwritefontface3_GetWeight
,
1366 dwritefontface3_GetStretch
,
1367 dwritefontface3_GetStyle
,
1368 dwritefontface3_GetFamilyNames
,
1369 dwritefontface3_GetFaceNames
,
1370 dwritefontface3_GetInformationalStrings
,
1371 dwritefontface3_HasCharacter
,
1372 dwritefontface3_GetRecommendedRenderingMode
,
1373 dwritefontface3_IsCharacterLocal
,
1374 dwritefontface3_IsGlyphLocal
,
1375 dwritefontface3_AreCharactersLocal
,
1376 dwritefontface3_AreGlyphsLocal
,
1377 dwritefontface4_GetGlyphImageFormats_
,
1378 dwritefontface4_GetGlyphImageFormats
,
1379 dwritefontface4_GetGlyphImageData
,
1380 dwritefontface4_ReleaseGlyphImageData
1383 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace4
**fontface
)
1385 struct dwrite_font_data
*data
= font
->data
;
1386 struct fontface_desc desc
;
1387 struct list
*cached_list
;
1392 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1393 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1397 if (FAILED(hr
= get_filestream_from_file(data
->file
, &desc
.stream
)))
1400 desc
.factory
= font
->family
->collection
->factory
;
1401 desc
.face_type
= data
->face_type
;
1402 desc
.files
= &data
->file
;
1403 desc
.files_number
= 1;
1404 desc
.index
= data
->face_index
;
1405 desc
.simulations
= data
->simulations
;
1406 desc
.font_data
= data
;
1407 hr
= create_fontface(&desc
, cached_list
, fontface
);
1409 IDWriteFontFileStream_Release(desc
.stream
);
1413 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1415 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1417 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1419 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1420 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1421 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1422 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1423 IsEqualIID(riid
, &IID_IUnknown
))
1426 IDWriteFont3_AddRef(iface
);
1430 WARN("%s not implemented.\n", debugstr_guid(riid
));
1433 return E_NOINTERFACE
;
1436 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1438 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1439 ULONG ref
= InterlockedIncrement(&This
->ref
);
1440 TRACE("(%p)->(%d)\n", This
, ref
);
1444 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1446 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1447 ULONG ref
= InterlockedDecrement(&This
->ref
);
1449 TRACE("(%p)->(%d)\n", This
, ref
);
1452 IDWriteFontFamily1_Release(&This
->family
->IDWriteFontFamily1_iface
);
1453 release_font_data(This
->data
);
1460 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1462 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1463 TRACE("(%p)->(%p)\n", This
, family
);
1465 *family
= (IDWriteFontFamily
*)This
->family
;
1466 IDWriteFontFamily_AddRef(*family
);
1470 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1472 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1473 TRACE("(%p)\n", This
);
1474 return This
->data
->weight
;
1477 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1479 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1480 TRACE("(%p)\n", This
);
1481 return This
->data
->stretch
;
1484 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1486 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1487 TRACE("(%p)\n", This
);
1491 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1493 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1494 IDWriteFontFace4
*fontface
;
1498 TRACE("(%p)\n", This
);
1500 hr
= get_fontface_from_font(This
, &fontface
);
1504 ret
= IDWriteFontFace4_IsSymbolFont(fontface
);
1505 IDWriteFontFace4_Release(fontface
);
1509 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1511 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1512 TRACE("(%p)->(%p)\n", This
, names
);
1513 return clone_localizedstring(This
->data
->names
, names
);
1516 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1517 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1519 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1520 struct dwrite_font_data
*data
= This
->data
;
1523 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1528 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1531 if (!data
->info_strings
[stringid
]) {
1532 IDWriteFontFace4
*fontface
;
1533 const void *table_data
;
1538 hr
= get_fontface_from_font(This
, &fontface
);
1542 table_exists
= FALSE
;
1543 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1544 if (FAILED(hr
) || !table_exists
)
1545 WARN("no NAME table found.\n");
1548 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1549 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
1550 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1553 IDWriteFontFace4_Release(fontface
);
1556 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1564 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1566 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1567 TRACE("(%p)\n", This
);
1568 return This
->data
->simulations
;
1571 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1573 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1575 TRACE("(%p)->(%p)\n", This
, metrics
);
1576 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1579 static HRESULT
font_has_character(struct dwrite_font
*font
, UINT32 ch
, BOOL
*exists
)
1581 IDWriteFontFace4
*fontface
;
1587 hr
= get_fontface_from_font(font
, &fontface
);
1592 hr
= IDWriteFontFace4_GetGlyphIndices(fontface
, &ch
, 1, &index
);
1593 IDWriteFontFace4_Release(fontface
);
1597 *exists
= index
!= 0;
1601 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
1603 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1605 TRACE("(%p)->(%#x %p)\n", This
, ch
, exists
);
1607 return font_has_character(This
, ch
, exists
);
1610 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1612 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1613 TRACE("(%p)->(%p)\n", This
, fontface
);
1614 return IDWriteFont3_CreateFontFace(iface
, (IDWriteFontFace3
**)fontface
);
1617 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1619 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1620 TRACE("(%p)->(%p)\n", This
, metrics
);
1621 *metrics
= This
->data
->metrics
;
1624 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1626 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1627 TRACE("(%p)->(%p)\n", This
, panose
);
1628 *panose
= This
->data
->panose
;
1631 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1633 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1634 IDWriteFontFace4
*fontface
;
1637 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1639 hr
= get_fontface_from_font(This
, &fontface
);
1643 hr
= IDWriteFontFace4_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1644 IDWriteFontFace4_Release(fontface
);
1648 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1650 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1651 IDWriteFontFace4
*fontface
;
1655 TRACE("(%p)\n", This
);
1657 hr
= get_fontface_from_font(This
, &fontface
);
1661 ret
= IDWriteFontFace4_IsMonospacedFont(fontface
);
1662 IDWriteFontFace4_Release(fontface
);
1666 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1668 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1669 IDWriteFontFace4
*fontface
;
1673 TRACE("(%p)\n", This
);
1675 hr
= get_fontface_from_font(This
, &fontface
);
1679 ret
= IDWriteFontFace4_IsColorFont(fontface
);
1680 IDWriteFontFace4_Release(fontface
);
1684 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1686 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1688 TRACE("(%p)->(%p)\n", This
, fontface
);
1690 return get_fontface_from_font(This
, (IDWriteFontFace4
**)fontface
);
1693 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1695 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1696 FIXME("(%p)->(%p): stub\n", This
, font
);
1700 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1702 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1704 TRACE("(%p)->(%p)\n", This
, reference
);
1706 return IDWriteFactory5_CreateFontFaceReference_(This
->family
->collection
->factory
, This
->data
->file
,
1707 This
->data
->face_index
, This
->data
->simulations
, reference
);
1710 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1712 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1715 TRACE("(%p)->(%#x)\n", This
, ch
);
1717 return font_has_character(This
, ch
, &ret
) == S_OK
&& ret
;
1720 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1722 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1723 FIXME("(%p): stub\n", This
);
1724 return DWRITE_LOCALITY_LOCAL
;
1727 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1728 dwritefont_QueryInterface
,
1731 dwritefont_GetFontFamily
,
1732 dwritefont_GetWeight
,
1733 dwritefont_GetStretch
,
1734 dwritefont_GetStyle
,
1735 dwritefont_IsSymbolFont
,
1736 dwritefont_GetFaceNames
,
1737 dwritefont_GetInformationalStrings
,
1738 dwritefont_GetSimulations
,
1739 dwritefont_GetMetrics
,
1740 dwritefont_HasCharacter
,
1741 dwritefont_CreateFontFace
,
1742 dwritefont1_GetMetrics
,
1743 dwritefont1_GetPanose
,
1744 dwritefont1_GetUnicodeRanges
,
1745 dwritefont1_IsMonospacedFont
,
1746 dwritefont2_IsColorFont
,
1747 dwritefont3_CreateFontFace
,
1749 dwritefont3_GetFontFaceReference
,
1750 dwritefont3_HasCharacter
,
1751 dwritefont3_GetLocality
1754 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
1758 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
1759 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
1762 static struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
1766 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
1767 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace4_iface
);
1770 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
1772 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1773 *lf
= font
->data
->lf
;
1776 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
1778 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1782 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
1784 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1785 *fontsig
= font
->data
->fontsig
;
1789 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
1791 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1792 *fontsig
= fontface
->fontsig
;
1796 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
1798 struct dwrite_font
*This
;
1802 This
= heap_alloc(sizeof(*This
));
1804 return E_OUTOFMEMORY
;
1806 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1808 This
->family
= family
;
1809 IDWriteFontFamily1_AddRef(&family
->IDWriteFontFamily1_iface
);
1810 This
->data
= family
->data
->fonts
[index
];
1811 This
->style
= This
->data
->style
;
1812 addref_font_data(This
->data
);
1814 *font
= &This
->IDWriteFont3_iface
;
1819 /* IDWriteFontList1 */
1820 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList1
*iface
, REFIID riid
, void **obj
)
1822 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1824 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1826 if (IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1827 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1828 IsEqualIID(riid
, &IID_IUnknown
))
1831 IDWriteFontList1_AddRef(iface
);
1835 WARN("%s not implemented.\n", debugstr_guid(riid
));
1838 return E_NOINTERFACE
;
1841 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList1
*iface
)
1843 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1844 ULONG ref
= InterlockedIncrement(&This
->ref
);
1845 TRACE("(%p)->(%d)\n", This
, ref
);
1849 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList1
*iface
)
1851 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1852 ULONG ref
= InterlockedDecrement(&This
->ref
);
1854 TRACE("(%p)->(%d)\n", This
, ref
);
1859 for (i
= 0; i
< This
->font_count
; i
++)
1860 release_font_data(This
->fonts
[i
]);
1861 IDWriteFontFamily1_Release(&This
->family
->IDWriteFontFamily1_iface
);
1862 heap_free(This
->fonts
);
1869 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList1
*iface
, IDWriteFontCollection
**collection
)
1871 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1872 return IDWriteFontFamily1_GetFontCollection(&This
->family
->IDWriteFontFamily1_iface
, collection
);
1875 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList1
*iface
)
1877 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1878 TRACE("(%p)\n", This
);
1879 return This
->font_count
;
1882 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont
**font
)
1884 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1886 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1890 if (This
->font_count
== 0)
1893 if (index
>= This
->font_count
)
1894 return E_INVALIDARG
;
1896 return create_font(This
->family
, index
, (IDWriteFont3
**)font
);
1899 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList1
*iface
, UINT32 index
)
1901 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1903 FIXME("(%p)->(%u): stub\n", This
, index
);
1905 return DWRITE_LOCALITY_LOCAL
;
1908 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1910 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1912 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1916 if (This
->font_count
== 0)
1919 if (index
>= This
->font_count
)
1922 return create_font(This
->family
, index
, font
);
1925 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList1
*iface
, UINT32 index
,
1926 IDWriteFontFaceReference
**reference
)
1928 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1932 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
1936 hr
= IDWriteFontList1_GetFont(iface
, index
, &font
);
1940 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
1941 IDWriteFont3_Release(font
);
1946 static const IDWriteFontList1Vtbl dwritefontlistvtbl
= {
1947 dwritefontlist_QueryInterface
,
1948 dwritefontlist_AddRef
,
1949 dwritefontlist_Release
,
1950 dwritefontlist_GetFontCollection
,
1951 dwritefontlist_GetFontCount
,
1952 dwritefontlist_GetFont
,
1953 dwritefontlist1_GetFontLocality
,
1954 dwritefontlist1_GetFont
,
1955 dwritefontlist1_GetFontFaceReference
1958 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1960 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1962 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1964 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1965 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1966 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1967 IsEqualIID(riid
, &IID_IUnknown
))
1970 IDWriteFontFamily1_AddRef(iface
);
1974 WARN("%s not implemented.\n", debugstr_guid(riid
));
1977 return E_NOINTERFACE
;
1980 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1982 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1983 ULONG ref
= InterlockedIncrement(&This
->ref
);
1984 TRACE("(%p)->(%d)\n", This
, ref
);
1988 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1990 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1991 ULONG ref
= InterlockedDecrement(&This
->ref
);
1993 TRACE("(%p)->(%d)\n", This
, ref
);
1997 IDWriteFontCollection1_Release(&This
->collection
->IDWriteFontCollection1_iface
);
1998 release_fontfamily_data(This
->data
);
2005 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
2007 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2009 TRACE("(%p)->(%p)\n", This
, collection
);
2011 *collection
= (IDWriteFontCollection
*)This
->collection
;
2012 IDWriteFontCollection_AddRef(*collection
);
2016 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
2018 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2019 TRACE("(%p)\n", This
);
2020 return This
->data
->font_count
;
2023 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
2025 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2027 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
2031 if (This
->data
->font_count
== 0)
2034 if (index
>= This
->data
->font_count
)
2035 return E_INVALIDARG
;
2037 return create_font(This
, index
, (IDWriteFont3
**)font
);
2040 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
2042 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2043 return clone_localizedstring(This
->data
->familyname
, names
);
2046 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2047 const struct dwrite_font_propvec
*req
)
2049 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2050 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2051 FLOAT cur_req_prod
, next_req_prod
;
2053 if (next_to_req
< cur_to_req
)
2056 if (next_to_req
> cur_to_req
)
2059 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2060 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2062 if (next_req_prod
> cur_req_prod
)
2065 if (next_req_prod
< cur_req_prod
)
2068 if (next
->stretch
> cur
->stretch
)
2070 if (next
->stretch
< cur
->stretch
)
2073 if (next
->style
> cur
->style
)
2075 if (next
->style
< cur
->style
)
2078 if (next
->weight
> cur
->weight
)
2080 if (next
->weight
< cur
->weight
)
2083 /* full match, no reason to prefer new variant */
2087 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
2088 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2090 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2091 struct dwrite_font_propvec req
;
2094 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
2096 if (This
->data
->font_count
== 0) {
2098 return DWRITE_E_NOFONT
;
2101 init_font_prop_vec(weight
, stretch
, style
, &req
);
2104 for (i
= 1; i
< This
->data
->font_count
; i
++) {
2105 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &This
->data
->fonts
[match
]->propvec
, &req
))
2109 return create_font(This
, match
, (IDWriteFont3
**)font
);
2112 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2114 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2116 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2119 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2121 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2124 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2126 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2131 for (j
= 0; j
< b
; j
++) {
2132 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2133 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2134 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2135 fonts
->fonts
[j
+1] = s
;
2146 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
2147 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2149 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2150 matching_filter_func func
= NULL
;
2151 struct dwrite_font_propvec req
;
2152 struct dwrite_fontlist
*fonts
;
2155 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
2159 fonts
= heap_alloc(sizeof(*fonts
));
2161 return E_OUTOFMEMORY
;
2163 /* Allocate as many as family has, not all of them will be necessary used. */
2164 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
2165 if (!fonts
->fonts
) {
2167 return E_OUTOFMEMORY
;
2170 fonts
->IDWriteFontList1_iface
.lpVtbl
= &dwritefontlistvtbl
;
2172 fonts
->family
= This
;
2173 IDWriteFontFamily1_AddRef(&fonts
->family
->IDWriteFontFamily1_iface
);
2174 fonts
->font_count
= 0;
2176 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2177 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2178 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
2179 func
= is_font_acceptable_for_normal
;
2181 else /* requested oblique or italic */ {
2182 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
2183 func
= is_font_acceptable_for_oblique_italic
;
2186 for (i
= 0; i
< This
->data
->font_count
; i
++) {
2187 if (!func
|| func(This
->data
->fonts
[i
])) {
2188 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
2189 addref_font_data(This
->data
->fonts
[i
]);
2190 fonts
->font_count
++;
2194 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2195 init_font_prop_vec(weight
, stretch
, style
, &req
);
2196 matchingfonts_sort(fonts
, &req
);
2198 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList1_iface
;
2202 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
2204 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2206 FIXME("(%p)->(%u): stub\n", This
, index
);
2208 return DWRITE_LOCALITY_LOCAL
;
2211 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
2213 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2215 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
2219 if (This
->data
->font_count
== 0)
2222 if (index
>= This
->data
->font_count
)
2225 return create_font(This
, index
, font
);
2228 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
2229 IDWriteFontFaceReference
**reference
)
2231 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2235 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
2239 hr
= IDWriteFontFamily1_GetFont(iface
, index
, &font
);
2243 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2244 IDWriteFont3_Release(font
);
2249 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
2250 dwritefontfamily_QueryInterface
,
2251 dwritefontfamily_AddRef
,
2252 dwritefontfamily_Release
,
2253 dwritefontfamily_GetFontCollection
,
2254 dwritefontfamily_GetFontCount
,
2255 dwritefontfamily_GetFont
,
2256 dwritefontfamily_GetFamilyNames
,
2257 dwritefontfamily_GetFirstMatchingFont
,
2258 dwritefontfamily_GetMatchingFonts
,
2259 dwritefontfamily1_GetFontLocality
,
2260 dwritefontfamily1_GetFont
,
2261 dwritefontfamily1_GetFontFaceReference
2264 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
, IDWriteFontFamily1
**family
)
2266 struct dwrite_fontfamily
*This
;
2270 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
2271 if (!This
) return E_OUTOFMEMORY
;
2273 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
2275 This
->collection
= collection
;
2276 IDWriteFontCollection1_AddRef(&collection
->IDWriteFontCollection1_iface
);
2277 This
->data
= collection
->family_data
[index
];
2278 InterlockedIncrement(&This
->data
->ref
);
2280 *family
= &This
->IDWriteFontFamily1_iface
;
2285 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2288 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
2291 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2293 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2294 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2296 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2297 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2298 IsEqualIID(riid
, &IID_IUnknown
))
2301 IDWriteFontCollection1_AddRef(iface
);
2307 if (IsEqualIID(riid
, &IID_issystemcollection
))
2310 WARN("%s not implemented.\n", debugstr_guid(riid
));
2312 return E_NOINTERFACE
;
2315 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2317 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2318 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2320 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2321 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2322 IsEqualIID(riid
, &IID_IUnknown
))
2325 IDWriteFontCollection1_AddRef(iface
);
2329 WARN("%s not implemented.\n", debugstr_guid(riid
));
2333 return E_NOINTERFACE
;
2336 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2338 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2339 ULONG ref
= InterlockedIncrement(&This
->ref
);
2340 TRACE("(%p)->(%d)\n", This
, ref
);
2344 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2346 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2347 ULONG ref
= InterlockedDecrement(&This
->ref
);
2349 TRACE("(%p)->(%d)\n", This
, ref
);
2354 factory_detach_fontcollection(This
->factory
, iface
);
2355 for (i
= 0; i
< This
->family_count
; i
++)
2356 release_fontfamily_data(This
->family_data
[i
]);
2357 heap_free(This
->family_data
);
2364 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2366 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2367 TRACE("(%p)\n", This
);
2368 return This
->family_count
;
2371 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2373 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2375 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2377 if (index
>= This
->family_count
) {
2382 return create_fontfamily(This
, index
, (IDWriteFontFamily1
**)family
);
2385 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2389 for (i
= 0; i
< collection
->family_count
; i
++) {
2390 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2391 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2394 for (j
= 0; j
< count
; j
++) {
2396 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2397 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2405 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2407 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2408 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2409 *index
= collection_find_family(This
, name
);
2410 *exists
= *index
!= ~0u;
2414 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2416 UINT32 left_key_size
, right_key_size
;
2417 const void *left_key
, *right_key
;
2423 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2427 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2431 if (left_key_size
!= right_key_size
)
2434 return !memcmp(left_key
, right_key
, left_key_size
);
2437 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2439 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2440 IDWriteFontFamily1
*family
;
2441 UINT32 i
, j
, face_index
;
2442 BOOL found_font
= FALSE
;
2443 IDWriteFontFile
*file
;
2446 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2451 return E_INVALIDARG
;
2454 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2457 face_index
= IDWriteFontFace_GetIndex(face
);
2460 for (i
= 0; i
< This
->family_count
; i
++) {
2461 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2463 for (j
= 0; j
< family_data
->font_count
; j
++) {
2464 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2466 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2475 IDWriteFontFile_Release(file
);
2478 return DWRITE_E_NOFONT
;
2480 hr
= create_fontfamily(This
, i
, &family
);
2484 hr
= create_font(impl_from_IDWriteFontFamily1(family
), j
, (IDWriteFont3
**)font
);
2485 IDWriteFontFamily1_Release(family
);
2489 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2491 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2493 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2498 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2500 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2502 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2504 if (index
>= This
->family_count
) {
2509 return create_fontfamily(This
, index
, family
);
2512 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2513 dwritefontcollection_QueryInterface
,
2514 dwritefontcollection_AddRef
,
2515 dwritefontcollection_Release
,
2516 dwritefontcollection_GetFontFamilyCount
,
2517 dwritefontcollection_GetFontFamily
,
2518 dwritefontcollection_FindFamilyName
,
2519 dwritefontcollection_GetFontFromFontFace
,
2520 dwritefontcollection1_GetFontSet
,
2521 dwritefontcollection1_GetFontFamily
2524 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2525 dwritesystemfontcollection_QueryInterface
,
2526 dwritefontcollection_AddRef
,
2527 dwritefontcollection_Release
,
2528 dwritefontcollection_GetFontFamilyCount
,
2529 dwritefontcollection_GetFontFamily
,
2530 dwritefontcollection_FindFamilyName
,
2531 dwritefontcollection_GetFontFromFontFace
,
2532 dwritefontcollection1_GetFontSet
,
2533 dwritefontcollection1_GetFontFamily
2536 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2538 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2539 struct dwrite_font_data
**new_list
;
2542 new_alloc
= family_data
->font_alloc
* 2;
2543 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2545 return E_OUTOFMEMORY
;
2546 family_data
->fonts
= new_list
;
2547 family_data
->font_alloc
= new_alloc
;
2550 family_data
->fonts
[family_data
->font_count
] = font_data
;
2551 family_data
->font_count
++;
2552 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2553 family_data
->has_normal_face
= 1;
2554 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2555 family_data
->has_oblique_face
= 1;
2557 family_data
->has_italic_face
= 1;
2561 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2563 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2564 struct dwrite_fontfamily_data
**new_list
;
2567 new_alloc
= collection
->family_alloc
* 2;
2568 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2570 return E_OUTOFMEMORY
;
2572 collection
->family_alloc
= new_alloc
;
2573 collection
->family_data
= new_list
;
2576 collection
->family_data
[collection
->family_count
++] = family
;
2580 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2582 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2583 collection
->ref
= 1;
2584 collection
->family_count
= 0;
2585 collection
->family_alloc
= is_system
? 30 : 5;
2586 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2587 if (!collection
->family_data
)
2588 return E_OUTOFMEMORY
;
2593 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2595 IDWriteFontFileLoader
*loader
;
2602 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2606 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2610 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2611 IDWriteFontFileLoader_Release(loader
);
2618 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2620 BOOL exists
= FALSE
;
2625 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2626 if (FAILED(hr
) || !exists
)
2629 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2632 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2636 while (isspaceW(*in
))
2640 if (!(len
= strlenW(in
)))
2643 while (isspaceW(in
[len
-1]))
2646 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2655 INT len
; /* token length */
2656 INT fulllen
; /* full length including following separators */
2659 static inline BOOL
is_name_separator_char(WCHAR ch
)
2661 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2664 struct name_pattern
{
2665 const WCHAR
*part1
; /* NULL indicates end of list */
2666 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2669 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2671 const struct name_pattern
*pattern
;
2672 struct name_token
*token
;
2675 while ((pattern
= &patterns
[i
++])->part1
) {
2676 int len_part1
= strlenW(pattern
->part1
);
2677 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2679 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2680 if (len_part2
== 0) {
2681 /* simple case with single part pattern */
2682 if (token
->len
!= len_part1
)
2685 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2686 if (match
) *match
= *token
;
2687 list_remove(&token
->entry
);
2693 struct name_token
*next_token
;
2694 struct list
*next_entry
;
2696 /* pattern parts are stored in reading order, tokens list is reversed */
2697 if (token
->len
< len_part2
)
2700 /* it's possible to have combined string as a token, like ExtraCondensed */
2701 if (token
->len
== len_part1
+ len_part2
) {
2702 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2705 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2708 /* combined string match */
2709 if (match
) *match
= *token
;
2710 list_remove(&token
->entry
);
2715 /* now it's only possible to have two tokens matched to respective pattern parts */
2716 if (token
->len
!= len_part2
)
2719 next_entry
= list_next(tokens
, &token
->entry
);
2721 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2722 if (next_token
->len
!= len_part1
)
2725 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2728 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2731 /* both parts matched, remove tokens */
2733 match
->ptr
= next_token
->ptr
;
2734 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2736 list_remove(&token
->entry
);
2737 list_remove(&next_token
->entry
);
2738 heap_free(next_token
);
2753 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2755 static const WCHAR itaW
[] = {'i','t','a',0};
2756 static const WCHAR italW
[] = {'i','t','a','l',0};
2757 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2758 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2760 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2761 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2762 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2763 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2765 static const struct name_pattern italic_patterns
[] = {
2774 static const struct name_pattern oblique_patterns
[] = {
2783 /* italic patterns first */
2784 if (match_pattern_list(tokens
, italic_patterns
, match
))
2785 return DWRITE_FONT_STYLE_ITALIC
;
2787 /* oblique patterns */
2788 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2789 return DWRITE_FONT_STYLE_OBLIQUE
;
2794 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2795 struct name_token
*match
)
2797 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2798 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2799 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2800 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2801 static const WCHAR wideW
[] = {'w','i','d','e',0};
2802 static const WCHAR condW
[] = {'c','o','n','d',0};
2804 static const struct name_pattern ultracondensed_patterns
[] = {
2805 { extraW
, compressedW
},
2806 { extW
, compressedW
},
2807 { ultraW
, compressedW
},
2808 { ultraW
, condensedW
},
2813 static const struct name_pattern extracondensed_patterns
[] = {
2815 { extraW
, condensedW
},
2816 { extW
, condensedW
},
2822 static const struct name_pattern semicondensed_patterns
[] = {
2825 { semiW
, condensedW
},
2830 static const struct name_pattern semiexpanded_patterns
[] = {
2832 { semiW
, expandedW
},
2833 { semiW
, extendedW
},
2837 static const struct name_pattern extraexpanded_patterns
[] = {
2838 { extraW
, expandedW
},
2839 { extW
, expandedW
},
2840 { extraW
, extendedW
},
2841 { extW
, extendedW
},
2845 static const struct name_pattern ultraexpanded_patterns
[] = {
2846 { ultraW
, expandedW
},
2847 { ultraW
, extendedW
},
2851 static const struct name_pattern condensed_patterns
[] = {
2857 static const struct name_pattern expanded_patterns
[] = {
2863 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2864 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2866 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2867 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2869 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2870 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2872 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2873 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2875 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2876 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2878 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2879 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2881 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2882 return DWRITE_FONT_STRETCH_CONDENSED
;
2884 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2885 return DWRITE_FONT_STRETCH_EXPANDED
;
2890 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2891 struct name_token
*match
)
2893 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2894 static const WCHAR nordW
[] = {'n','o','r','d',0};
2896 static const struct name_pattern thin_patterns
[] = {
2903 static const struct name_pattern extralight_patterns
[] = {
2910 static const struct name_pattern semilight_patterns
[] = {
2915 static const struct name_pattern demibold_patterns
[] = {
2921 static const struct name_pattern extrabold_patterns
[] = {
2928 static const struct name_pattern extrablack_patterns
[] = {
2935 static const struct name_pattern bold_patterns
[] = {
2940 static const struct name_pattern thin2_patterns
[] = {
2945 static const struct name_pattern light_patterns
[] = {
2950 static const struct name_pattern medium_patterns
[] = {
2955 static const struct name_pattern black_patterns
[] = {
2962 static const struct name_pattern demibold2_patterns
[] = {
2967 static const struct name_pattern extrabold2_patterns
[] = {
2972 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2973 matching pattern. */
2975 if (match_pattern_list(tokens
, thin_patterns
, match
))
2976 return DWRITE_FONT_WEIGHT_THIN
;
2978 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2979 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2981 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2982 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2984 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2985 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2987 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2988 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2990 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2991 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2993 if (match_pattern_list(tokens
, bold_patterns
, match
))
2994 return DWRITE_FONT_WEIGHT_BOLD
;
2996 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2997 return DWRITE_FONT_WEIGHT_THIN
;
2999 if (match_pattern_list(tokens
, light_patterns
, match
))
3000 return DWRITE_FONT_WEIGHT_LIGHT
;
3002 if (match_pattern_list(tokens
, medium_patterns
, match
))
3003 return DWRITE_FONT_WEIGHT_MEDIUM
;
3005 if (match_pattern_list(tokens
, black_patterns
, match
))
3006 return DWRITE_FONT_WEIGHT_BLACK
;
3008 if (match_pattern_list(tokens
, black_patterns
, match
))
3009 return DWRITE_FONT_WEIGHT_BLACK
;
3011 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3012 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3014 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3015 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3017 /* FIXME: use abbreviated names to extract weight */
3022 struct knownweight_entry
{
3024 DWRITE_FONT_WEIGHT weight
;
3027 static int compare_knownweights(const void *a
, const void* b
)
3029 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3030 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3033 if (target
> entry
->weight
)
3035 else if (target
< entry
->weight
)
3041 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3043 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3044 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3045 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3046 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3047 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3048 const struct knownweight_entry
*ptr
;
3050 static const struct knownweight_entry knownweights
[] = {
3051 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3052 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3053 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3054 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3055 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3056 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3057 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3058 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3059 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3060 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3063 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
3064 compare_knownweights
);
3070 strcpyW(nameW
, ptr
->nameW
);
3074 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3076 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3077 strW
[name
->len
] = 0;
3080 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3081 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3083 static const WCHAR bookW
[] = {'B','o','o','k',0};
3084 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3085 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3086 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3087 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3089 static const WCHAR
*regular_patterns
[] = {
3098 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3102 len
= strlenW(facenameW
);
3104 /* remove rightmost regular variant from face name */
3105 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3106 int pattern_len
= strlenW(ptr
);
3109 if (pattern_len
> len
)
3112 src
= facenameW
+ len
- pattern_len
;
3113 while (src
>= facenameW
) {
3114 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3115 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3116 len
= strlenW(facenameW
);
3128 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3136 struct name_token
*token
= heap_alloc(sizeof(*token
));
3141 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3147 /* skip separators */
3148 while (is_name_separator_char(*ptr
)) {
3153 list_add_head(tokens
, &token
->entry
);
3157 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3159 struct name_token
*token
, *token2
;
3160 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3163 list_remove(&token
->entry
);
3165 /* don't include last separator */
3166 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3167 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3175 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3177 struct name_token stretch_name
, weight_name
, style_name
;
3178 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3179 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3180 const WCHAR
*regular_ptr
= NULL
;
3181 DWRITE_FONT_STRETCH stretch
;
3182 DWRITE_FONT_WEIGHT weight
;
3186 /* remove leading and trailing spaces from family and face name */
3187 trim_spaces(familyW
, familynameW
);
3188 len
= trim_spaces(faceW
, facenameW
);
3190 /* remove rightmost regular variant from face name */
3191 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3193 /* append face name to family name, FIXME check if face name is a substring of family name */
3195 strcatW(familynameW
, spaceW
);
3196 strcatW(familynameW
, facenameW
);
3199 /* tokenize with " .-_" */
3200 fontname_tokenize(&tokens
, familynameW
);
3202 /* extract and resolve style */
3203 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3205 /* extract stretch */
3206 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3208 /* extract weight */
3209 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3211 /* resolve weight */
3212 if (weight
!= font
->weight
) {
3213 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3214 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3215 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3216 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3217 !(abs(weight
- font
->weight
) <= 150 &&
3218 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3219 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3220 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3222 font
->weight
= weight
;
3226 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3227 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3228 stretch itself is normal (extracted stretch is never normal). */
3229 if (stretch
!= font
->stretch
) {
3230 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3231 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3232 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3234 font
->stretch
= stretch
;
3238 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3240 /* get final combined string from what's left in token list, list is released */
3241 fontname_tokens_to_str(&tokens
, finalW
);
3243 if (!strcmpW(familyW
, finalW
))
3246 /* construct face name */
3247 strcpyW(familyW
, finalW
);
3249 /* resolved weight name */
3250 if (weight_name
.ptr
)
3251 font_name_token_to_str(&weight_name
, weightW
);
3252 /* ignore normal weight */
3253 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3255 /* for known weight values use appropriate names */
3256 else if (is_known_weight_value(font
->weight
, weightW
)) {
3258 /* use Wnnn format as a fallback in case weight is not one of known values */
3260 static const WCHAR fmtW
[] = {'W','%','d',0};
3261 sprintfW(weightW
, fmtW
, font
->weight
);
3264 /* resolved stretch name */
3265 if (stretch_name
.ptr
)
3266 font_name_token_to_str(&stretch_name
, stretchW
);
3267 /* ignore normal stretch */
3268 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3270 /* use predefined stretch names */
3272 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3273 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3274 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3275 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3276 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3277 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3279 static const WCHAR
*stretchnamesW
[] = {
3280 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3285 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3291 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3294 /* resolved style name */
3296 font_name_token_to_str(&style_name
, styleW
);
3297 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3299 /* use predefined names */
3301 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3302 strcpyW(styleW
, italicW
);
3304 strcpyW(styleW
, obliqueW
);
3307 /* use Regular match if it was found initially */
3308 if (!*weightW
&& !*stretchW
&& !*styleW
)
3309 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3313 strcpyW(faceW
, stretchW
);
3316 strcatW(faceW
, spaceW
);
3317 strcatW(faceW
, weightW
);
3321 strcatW(faceW
, spaceW
);
3322 strcatW(faceW
, styleW
);
3326 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3330 static HRESULT
init_font_data(const struct fontface_desc
*desc
, IDWriteLocalizedStrings
**family_name
,
3331 struct dwrite_font_data
**ret
)
3333 struct file_stream_desc stream_desc
;
3334 struct dwrite_font_props props
;
3335 struct dwrite_font_data
*data
;
3336 WCHAR familyW
[255], faceW
[255];
3341 data
= heap_alloc_zero(sizeof(*data
));
3343 return E_OUTOFMEMORY
;
3346 data
->file
= desc
->files
[0];
3347 data
->face_index
= desc
->index
;
3348 data
->face_type
= desc
->face_type
;
3349 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3350 data
->bold_sim_tested
= 0;
3351 data
->oblique_sim_tested
= 0;
3352 IDWriteFontFile_AddRef(data
->file
);
3354 stream_desc
.stream
= desc
->stream
;
3355 stream_desc
.face_type
= desc
->face_type
;
3356 stream_desc
.face_index
= desc
->index
;
3357 opentype_get_font_properties(&stream_desc
, &props
);
3358 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3359 opentype_get_font_facename(&stream_desc
, props
.lf
.lfFaceName
, &data
->names
);
3361 /* get family name from font file */
3362 hr
= opentype_get_font_familyname(&stream_desc
, family_name
);
3364 WARN("unable to get family name from font\n");
3365 release_font_data(data
);
3369 data
->style
= props
.style
;
3370 data
->stretch
= props
.stretch
;
3371 data
->weight
= props
.weight
;
3372 data
->panose
= props
.panose
;
3373 data
->fontsig
= props
.fontsig
;
3374 data
->lf
= props
.lf
;
3376 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3377 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3378 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3379 set_en_localizedstring(*family_name
, familyW
);
3380 set_en_localizedstring(data
->names
, faceW
);
3383 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3389 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3390 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3392 struct dwrite_font_data
*data
;
3396 data
= heap_alloc_zero(sizeof(*data
));
3398 return E_OUTOFMEMORY
;
3402 data
->simulations
|= sim
;
3403 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3404 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3405 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3406 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3407 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3409 IDWriteFontFile_AddRef(data
->file
);
3411 create_localizedstrings(&data
->names
);
3412 add_localizedstring(data
->names
, enusW
, facenameW
);
3414 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3420 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3422 struct dwrite_fontfamily_data
*data
;
3424 data
= heap_alloc(sizeof(*data
));
3426 return E_OUTOFMEMORY
;
3429 data
->font_count
= 0;
3430 data
->font_alloc
= 2;
3431 data
->has_normal_face
= 0;
3432 data
->has_oblique_face
= 0;
3433 data
->has_italic_face
= 0;
3435 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3438 return E_OUTOFMEMORY
;
3441 data
->familyname
= familyname
;
3442 IDWriteLocalizedStrings_AddRef(familyname
);
3448 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3450 UINT32 i
, j
, heaviest
;
3452 for (i
= 0; i
< family
->font_count
; i
++) {
3453 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3456 if (family
->fonts
[i
]->bold_sim_tested
)
3459 family
->fonts
[i
]->bold_sim_tested
= 1;
3460 for (j
= i
; j
< family
->font_count
; j
++) {
3461 if (family
->fonts
[j
]->bold_sim_tested
)
3464 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3465 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3466 if (family
->fonts
[j
]->weight
> weight
) {
3467 weight
= family
->fonts
[j
]->weight
;
3470 family
->fonts
[j
]->bold_sim_tested
= 1;
3474 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3475 static const struct name_pattern weightsim_patterns
[] = {
3490 WCHAR facenameW
[255], initialW
[255];
3491 struct dwrite_font_data
*boldface
;
3494 /* add Bold simulation based on heaviest face data */
3496 /* Simulated face name should only contain Bold as weight term,
3497 so remove existing regular and weight terms. */
3498 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3499 facename_remove_regular_term(initialW
, -1);
3501 /* remove current weight pattern */
3502 fontname_tokenize(&tokens
, initialW
);
3503 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3504 fontname_tokens_to_str(&tokens
, facenameW
);
3506 /* Bold suffix for new name */
3508 strcatW(facenameW
, spaceW
);
3509 strcatW(facenameW
, boldW
);
3511 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3512 boldface
->bold_sim_tested
= 1;
3513 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
3514 fontfamily_add_font(family
, boldface
);
3520 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3524 for (i
= 0; i
< family
->font_count
; i
++) {
3525 UINT32 regular
= ~0u, oblique
= ~0u;
3526 struct dwrite_font_data
*obliqueface
;
3527 WCHAR facenameW
[255];
3529 if (family
->fonts
[i
]->oblique_sim_tested
)
3532 family
->fonts
[i
]->oblique_sim_tested
= 1;
3533 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3535 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3538 /* find regular style with same weight/stretch values */
3539 for (j
= i
; j
< family
->font_count
; j
++) {
3540 if (family
->fonts
[j
]->oblique_sim_tested
)
3543 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3544 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3546 family
->fonts
[j
]->oblique_sim_tested
= 1;
3547 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3550 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3554 if (regular
!= ~0u && oblique
!= ~0u)
3558 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3562 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3566 /* add oblique simulation based on this regular face */
3568 /* remove regular term if any, append 'Oblique' */
3569 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3570 facename_remove_regular_term(facenameW
, -1);
3573 strcatW(facenameW
, spaceW
);
3574 strcatW(facenameW
, obliqueW
);
3576 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3577 obliqueface
->oblique_sim_tested
= 1;
3578 obliqueface
->lf
.lfItalic
= 1;
3579 fontfamily_add_font(family
, obliqueface
);
3584 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3585 const WCHAR
*replacement_name
)
3587 UINT32 i
= collection_find_family(collection
, replacement_name
);
3588 struct dwrite_fontfamily_data
*target
;
3589 IDWriteLocalizedStrings
*strings
;
3592 /* replacement does not exist */
3596 hr
= create_localizedstrings(&strings
);
3600 /* add a new family with target name, reuse font data from replacement */
3601 add_localizedstring(strings
, enusW
, target_name
);
3602 hr
= init_fontfamily_data(strings
, &target
);
3604 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3607 for (i
= 0; i
< replacement
->font_count
; i
++) {
3608 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3609 addref_font_data(replacement
->fonts
[i
]);
3612 fontcollection_add_family(collection
, target
);
3613 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3614 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3616 IDWriteLocalizedStrings_Release(strings
);
3620 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3621 system font collections. */
3622 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3624 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3629 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3632 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3637 max_namelen
++; /* returned value doesn't include room for '\0' */
3638 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3639 data
= heap_alloc(max_datalen
);
3641 datalen
= max_datalen
;
3642 namelen
= max_namelen
;
3643 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3644 if (collection_find_family(collection
, name
) == ~0u) {
3645 if (type
== REG_MULTI_SZ
) {
3646 WCHAR
*replacement
= data
;
3647 while (*replacement
) {
3648 if (fontcollection_add_replacement(collection
, name
, replacement
))
3650 replacement
+= strlenW(replacement
) + 1;
3653 else if (type
== REG_SZ
)
3654 fontcollection_add_replacement(collection
, name
, data
);
3657 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3659 datalen
= max_datalen
;
3660 namelen
= max_namelen
;
3668 HRESULT
create_font_collection(IDWriteFactory5
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
3669 IDWriteFontCollection1
**ret
)
3671 struct fontfile_enum
{
3673 IDWriteFontFile
*file
;
3675 struct fontfile_enum
*fileenum
, *fileenum2
;
3676 struct dwrite_fontcollection
*collection
;
3677 struct list scannedfiles
;
3678 BOOL current
= FALSE
;
3684 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3685 if (!collection
) return E_OUTOFMEMORY
;
3687 hr
= init_font_collection(collection
, is_system
);
3689 heap_free(collection
);
3693 *ret
= &collection
->IDWriteFontCollection1_iface
;
3695 TRACE("building font collection:\n");
3697 list_init(&scannedfiles
);
3698 while (hr
== S_OK
) {
3699 DWRITE_FONT_FACE_TYPE face_type
;
3700 DWRITE_FONT_FILE_TYPE file_type
;
3701 BOOL supported
, same
= FALSE
;
3702 IDWriteFontFileStream
*stream
;
3703 IDWriteFontFile
*file
;
3707 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3708 if (FAILED(hr
) || !current
)
3711 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3715 /* check if we've scanned this file already */
3716 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3717 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3722 IDWriteFontFile_Release(file
);
3726 if (FAILED(get_filestream_from_file(file
, &stream
))) {
3727 IDWriteFontFile_Release(file
);
3731 /* Unsupported formats are skipped. */
3732 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
3733 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3734 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3735 IDWriteFontFileStream_Release(stream
);
3736 IDWriteFontFile_Release(file
);
3741 /* add to scanned list */
3742 fileenum
= heap_alloc(sizeof(*fileenum
));
3743 fileenum
->file
= file
;
3744 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3746 for (i
= 0; i
< face_count
; i
++) {
3747 IDWriteLocalizedStrings
*family_name
= NULL
;
3748 struct dwrite_font_data
*font_data
;
3749 struct fontface_desc desc
;
3753 desc
.factory
= factory
;
3754 desc
.face_type
= face_type
;
3756 desc
.stream
= stream
;
3757 desc
.files_number
= 1;
3759 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3760 desc
.font_data
= NULL
;
3762 /* alloc and init new font data structure */
3763 hr
= init_font_data(&desc
, &family_name
, &font_data
);
3765 /* move to next one */
3770 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3772 /* ignore dot named faces */
3773 if (familyW
[0] == '.') {
3774 WARN("Ignoring face %s\n", debugstr_w(familyW
));
3775 IDWriteLocalizedStrings_Release(family_name
);
3776 release_font_data(font_data
);
3780 index
= collection_find_family(collection
, familyW
);
3782 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3784 struct dwrite_fontfamily_data
*family_data
;
3786 /* create and init new family */
3787 hr
= init_fontfamily_data(family_name
, &family_data
);
3789 /* add font to family, family - to collection */
3790 hr
= fontfamily_add_font(family_data
, font_data
);
3792 hr
= fontcollection_add_family(collection
, family_data
);
3795 release_fontfamily_data(family_data
);
3799 IDWriteLocalizedStrings_Release(family_name
);
3806 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3807 IDWriteFontFile_Release(fileenum
->file
);
3808 list_remove(&fileenum
->entry
);
3809 heap_free(fileenum
);
3812 for (i
= 0; i
< collection
->family_count
; i
++) {
3813 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3814 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3818 fontcollection_add_replacements(collection
);
3820 collection
->factory
= factory
;
3821 IDWriteFactory5_AddRef(factory
);
3826 struct system_fontfile_enumerator
3828 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3831 IDWriteFactory5
*factory
;
3836 DWORD filename_size
;
3839 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3841 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3844 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3846 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3847 IDWriteFontFileEnumerator_AddRef(iface
);
3852 WARN("%s not implemented.\n", debugstr_guid(riid
));
3856 return E_NOINTERFACE
;
3859 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3861 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3862 return InterlockedIncrement(&enumerator
->ref
);
3865 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3867 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3868 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3871 IDWriteFactory5_Release(enumerator
->factory
);
3872 RegCloseKey(enumerator
->hkey
);
3873 heap_free(enumerator
->filename
);
3874 heap_free(enumerator
);
3880 static HRESULT
create_local_file_reference(IDWriteFactory5
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3884 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3885 if (!strchrW(filename
, '\\')) {
3886 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3887 WCHAR fullpathW
[MAX_PATH
];
3889 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3890 strcatW(fullpathW
, fontsW
);
3891 strcatW(fullpathW
, filename
);
3893 hr
= IDWriteFactory5_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3896 hr
= IDWriteFactory5_CreateFontFileReference(factory
, filename
, NULL
, file
);
3901 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3903 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3907 if (enumerator
->index
< 0 || !enumerator
->filename
|| !*enumerator
->filename
)
3910 return create_local_file_reference(enumerator
->factory
, enumerator
->filename
, file
);
3913 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3915 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3916 WCHAR name_buf
[256], *name
= name_buf
;
3917 DWORD name_count
, max_name_count
= sizeof(name_buf
) / sizeof(*name_buf
), type
, data_size
;
3922 enumerator
->index
++;
3924 /* iterate until we find next string value */
3927 name_count
= max_name_count
;
3928 data_size
= enumerator
->filename_size
- sizeof(*enumerator
->filename
);
3930 r
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, name
, &name_count
,
3931 NULL
, &type
, (BYTE
*)enumerator
->filename
, &data_size
);
3932 if (r
== ERROR_MORE_DATA
) {
3933 if (name_count
>= max_name_count
) {
3934 if (name
!= name_buf
) heap_free(name
);
3935 max_name_count
*= 2;
3936 name
= heap_alloc(max_name_count
* sizeof(*name
));
3937 if (!name
) return E_OUTOFMEMORY
;
3939 if (data_size
> enumerator
->filename_size
- sizeof(*enumerator
->filename
)) {
3940 heap_free(enumerator
->filename
);
3941 enumerator
->filename_size
= max(data_size
+ sizeof(*enumerator
->filename
), enumerator
->filename_size
* 2);
3942 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
3943 if (!enumerator
->filename
) {
3949 } while (r
== ERROR_MORE_DATA
);
3951 if (r
!= ERROR_SUCCESS
) {
3952 enumerator
->filename
[0] = 0;
3955 enumerator
->filename
[data_size
/ sizeof(*enumerator
->filename
)] = 0;
3956 if (type
== REG_SZ
&& *name
!= '@') {
3960 enumerator
->index
++;
3962 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3965 if (name
!= name_buf
) heap_free(name
);
3969 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3971 systemfontfileenumerator_QueryInterface
,
3972 systemfontfileenumerator_AddRef
,
3973 systemfontfileenumerator_Release
,
3974 systemfontfileenumerator_MoveNext
,
3975 systemfontfileenumerator_GetCurrentFontFile
3978 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory5
*factory
, IDWriteFontFileEnumerator
**ret
)
3980 struct system_fontfile_enumerator
*enumerator
;
3981 static const WCHAR fontslistW
[] = {
3982 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3983 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3984 'F','o','n','t','s',0
3989 enumerator
= heap_alloc(sizeof(*enumerator
));
3991 return E_OUTOFMEMORY
;
3993 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3994 enumerator
->ref
= 1;
3995 enumerator
->factory
= factory
;
3996 enumerator
->index
= -1;
3997 enumerator
->filename_size
= MAX_PATH
* sizeof(*enumerator
->filename
);
3998 enumerator
->filename
= heap_alloc(enumerator
->filename_size
);
3999 if (!enumerator
->filename
) {
4000 heap_free(enumerator
);
4001 return E_OUTOFMEMORY
;
4004 IDWriteFactory5_AddRef(factory
);
4006 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
4007 ERR("failed to open fonts list key\n");
4008 IDWriteFactory5_Release(factory
);
4009 heap_free(enumerator
->filename
);
4010 heap_free(enumerator
);
4014 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4019 HRESULT
get_system_fontcollection(IDWriteFactory5
*factory
, IDWriteFontCollection1
**collection
)
4021 IDWriteFontFileEnumerator
*enumerator
;
4026 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4030 TRACE("building system font collection for factory %p\n", factory
);
4031 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
4032 IDWriteFontFileEnumerator_Release(enumerator
);
4036 static HRESULT
eudc_collection_add_family(IDWriteFactory5
*factory
, struct dwrite_fontcollection
*collection
,
4037 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4039 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};
4040 static const WCHAR emptyW
[] = {0};
4041 struct dwrite_fontfamily_data
*family_data
;
4042 IDWriteLocalizedStrings
*names
;
4043 DWRITE_FONT_FACE_TYPE face_type
;
4044 DWRITE_FONT_FILE_TYPE file_type
;
4045 IDWriteFontFileStream
*stream
;
4046 IDWriteFontFile
*file
;
4047 UINT32 face_count
, i
;
4051 /* create font file from this path */
4052 hr
= create_local_file_reference(factory
, pathW
, &file
);
4056 if (FAILED(get_filestream_from_file(file
, &stream
))) {
4057 IDWriteFontFile_Release(file
);
4061 /* Unsupported formats are skipped. */
4062 hr
= opentype_analyze_font(stream
, &supported
, &file_type
, &face_type
, &face_count
);
4063 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4064 TRACE("Unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4065 IDWriteFontFileStream_Release(stream
);
4066 IDWriteFontFile_Release(file
);
4070 /* create and init new family */
4072 /* Family names are added for non-specific locale, represented with empty string.
4073 Default family appears with empty family name. */
4074 create_localizedstrings(&names
);
4075 if (!strcmpiW(keynameW
, defaultfontW
))
4076 add_localizedstring(names
, emptyW
, emptyW
);
4078 add_localizedstring(names
, emptyW
, keynameW
);
4080 hr
= init_fontfamily_data(names
, &family_data
);
4081 IDWriteLocalizedStrings_Release(names
);
4083 IDWriteFontFile_Release(file
);
4087 /* fill with faces */
4088 for (i
= 0; i
< face_count
; i
++) {
4089 struct dwrite_font_data
*font_data
;
4090 struct fontface_desc desc
;
4092 /* alloc and init new font data structure */
4093 desc
.factory
= factory
;
4094 desc
.face_type
= face_type
;
4097 desc
.stream
= stream
;
4098 desc
.files_number
= 1;
4099 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4100 desc
.font_data
= NULL
;
4102 hr
= init_font_data(&desc
, &names
, &font_data
);
4106 IDWriteLocalizedStrings_Release(names
);
4108 /* add font to family */
4109 hr
= fontfamily_add_font(family_data
, font_data
);
4111 release_font_data(font_data
);
4114 /* add family to collection */
4115 hr
= fontcollection_add_family(collection
, family_data
);
4117 release_fontfamily_data(family_data
);
4118 IDWriteFontFileStream_Release(stream
);
4119 IDWriteFontFile_Release(file
);
4124 HRESULT
get_eudc_fontcollection(IDWriteFactory5
*factory
, IDWriteFontCollection1
**ret
)
4126 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4127 struct dwrite_fontcollection
*collection
;
4128 static const WCHAR emptyW
[] = {0};
4129 WCHAR eudckeypathW
[16];
4137 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4141 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4142 if (!collection
) return E_OUTOFMEMORY
;
4144 hr
= init_font_collection(collection
, FALSE
);
4146 heap_free(collection
);
4150 *ret
= &collection
->IDWriteFontCollection1_iface
;
4151 collection
->factory
= factory
;
4152 IDWriteFactory5_AddRef(factory
);
4154 /* return empty collection if EUDC fonts are not configured */
4155 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4156 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4159 retval
= ERROR_SUCCESS
;
4161 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4162 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4163 DWORD type
, path_len
, name_len
;
4165 path_len
= sizeof(pathW
)/sizeof(*pathW
);
4166 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
4167 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4168 if (retval
|| type
!= REG_SZ
)
4171 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4173 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4175 RegCloseKey(eudckey
);
4177 /* try to add global default if not defined for specific codepage */
4179 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
4181 if (FAILED(hr
) || !exists
) {
4182 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4183 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4185 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4188 /* EUDC collection offers simulated faces too */
4189 for (i
= 0; i
< collection
->family_count
; i
++) {
4190 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4191 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4197 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4199 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4201 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4203 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4206 IDWriteFontFile_AddRef(iface
);
4210 WARN("%s not implemented.\n", debugstr_guid(riid
));
4213 return E_NOINTERFACE
;
4216 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4218 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4219 ULONG ref
= InterlockedIncrement(&This
->ref
);
4220 TRACE("(%p)->(%d)\n", This
, ref
);
4224 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4226 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4227 ULONG ref
= InterlockedDecrement(&This
->ref
);
4229 TRACE("(%p)->(%d)\n", This
, ref
);
4233 IDWriteFontFileLoader_Release(This
->loader
);
4234 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4235 heap_free(This
->reference_key
);
4242 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4244 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4245 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4246 *fontFileReferenceKey
= This
->reference_key
;
4247 *fontFileReferenceKeySize
= This
->key_size
;
4252 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4254 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4255 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4256 *fontFileLoader
= This
->loader
;
4257 IDWriteFontFileLoader_AddRef(This
->loader
);
4262 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*is_supported
, DWRITE_FONT_FILE_TYPE
*file_type
,
4263 DWRITE_FONT_FACE_TYPE
*face_type
, UINT32
*face_count
)
4265 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4266 IDWriteFontFileStream
*stream
;
4269 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, is_supported
, file_type
, face_type
, face_count
);
4271 *is_supported
= FALSE
;
4272 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4274 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4277 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4281 hr
= opentype_analyze_font(stream
, is_supported
, file_type
, face_type
, face_count
);
4283 /* TODO: Further Analysis */
4284 IDWriteFontFileStream_Release(stream
);
4288 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4289 dwritefontfile_QueryInterface
,
4290 dwritefontfile_AddRef
,
4291 dwritefontfile_Release
,
4292 dwritefontfile_GetReferenceKey
,
4293 dwritefontfile_GetLoader
,
4294 dwritefontfile_Analyze
,
4297 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4298 IDWriteFontFile
**ret
)
4300 struct dwrite_fontfile
*file
;
4305 file
= heap_alloc(sizeof(*file
));
4306 key
= heap_alloc(key_size
);
4307 if (!file
|| !key
) {
4310 return E_OUTOFMEMORY
;
4313 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4315 IDWriteFontFileLoader_AddRef(loader
);
4316 file
->loader
= loader
;
4317 file
->stream
= NULL
;
4318 file
->reference_key
= key
;
4319 memcpy(file
->reference_key
, reference_key
, key_size
);
4320 file
->key_size
= key_size
;
4322 *ret
= &file
->IDWriteFontFile_iface
;
4327 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace4
**ret
)
4329 struct file_stream_desc stream_desc
;
4330 struct dwrite_fontface
*fontface
;
4337 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4339 return E_OUTOFMEMORY
;
4341 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4342 if (!fontface
->files
) {
4343 heap_free(fontface
);
4344 return E_OUTOFMEMORY
;
4347 fontface
->IDWriteFontFace4_iface
.lpVtbl
= &dwritefontfacevtbl
;
4349 fontface
->type
= desc
->face_type
;
4350 fontface
->file_count
= desc
->files_number
;
4351 fontface
->cmap
.exists
= TRUE
;
4352 fontface
->vdmx
.exists
= TRUE
;
4353 fontface
->gasp
.exists
= TRUE
;
4354 fontface
->cpal
.exists
= TRUE
;
4355 fontface
->colr
.exists
= TRUE
;
4356 fontface
->index
= desc
->index
;
4357 fontface
->simulations
= desc
->simulations
;
4358 IDWriteFactory5_AddRef(fontface
->factory
= desc
->factory
);
4360 for (i
= 0; i
< fontface
->file_count
; i
++) {
4361 fontface
->files
[i
] = desc
->files
[i
];
4362 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4364 fontface
->stream
= desc
->stream
;
4365 IDWriteFontFileStream_AddRef(fontface
->stream
);
4367 stream_desc
.stream
= fontface
->stream
;
4368 stream_desc
.face_type
= desc
->face_type
;
4369 stream_desc
.face_index
= desc
->index
;
4370 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4371 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4372 /* TODO: test what happens if caret is already slanted */
4373 if (fontface
->caret
.slopeRise
== 1) {
4374 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4375 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4379 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace4_iface
, &is_symbol
);
4381 fontface
->flags
|= FONTFACE_IS_SYMBOL
;
4382 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace4_iface
))
4383 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4384 if (freetype_is_monospaced(&fontface
->IDWriteFontFace4_iface
))
4385 fontface
->flags
|= FONTFACE_IS_MONOSPACED
;
4386 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace4_iface
))
4387 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4388 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace4_iface
);
4390 /* Font properties are reused from font object when 'normal' face creation path is used:
4391 collection -> family -> matching font -> fontface.
4393 If face is created directly from factory we have to go through properties resolution.
4395 if (desc
->font_data
) {
4396 fontface
->weight
= desc
->font_data
->weight
;
4397 fontface
->style
= desc
->font_data
->style
;
4398 fontface
->stretch
= desc
->font_data
->stretch
;
4399 fontface
->panose
= desc
->font_data
->panose
;
4400 fontface
->fontsig
= desc
->font_data
->fontsig
;
4401 fontface
->lf
= desc
->font_data
->lf
;
4404 IDWriteLocalizedStrings
*names
;
4405 struct dwrite_font_data
*data
;
4407 hr
= init_font_data(desc
, &names
, &data
);
4409 IDWriteFontFace4_Release(&fontface
->IDWriteFontFace4_iface
);
4413 fontface
->weight
= data
->weight
;
4414 fontface
->style
= data
->style
;
4415 fontface
->stretch
= data
->stretch
;
4416 fontface
->panose
= data
->panose
;
4417 fontface
->fontsig
= data
->fontsig
;
4418 fontface
->lf
= data
->lf
;
4420 IDWriteLocalizedStrings_Release(names
);
4421 release_font_data(data
);
4424 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace4_iface
);
4426 *ret
= &fontface
->IDWriteFontFace4_iface
;
4430 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4437 struct local_cached_stream
4440 IDWriteFontFileStream
*stream
;
4441 struct local_refkey
*key
;
4445 struct dwrite_localfontfilestream
4447 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4450 struct local_cached_stream
*entry
;
4451 const void *file_ptr
;
4455 struct dwrite_localfontfileloader
{
4456 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4459 struct list streams
;
4460 CRITICAL_SECTION cs
;
4463 static struct dwrite_localfontfileloader local_fontfile_loader
;
4465 struct dwrite_inmemory_stream_data
4473 struct dwrite_inmemory_filestream
4475 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4478 struct dwrite_inmemory_stream_data
*data
;
4481 struct dwrite_inmemory_fileloader
4483 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
4486 struct dwrite_inmemory_stream_data
**streams
;
4491 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4493 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4496 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4498 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4501 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
4503 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
4506 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4508 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
4511 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
4513 if (InterlockedDecrement(&stream
->ref
) == 0) {
4515 IUnknown_Release(stream
->owner
);
4517 heap_free(stream
->data
);
4522 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4524 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4526 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4528 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
4529 IsEqualIID(riid
, &IID_IUnknown
))
4532 if (InterlockedIncrement(&This
->ref
) == 1) {
4533 InterlockedDecrement(&This
->ref
);
4540 WARN("%s not implemented.\n", debugstr_guid(riid
));
4543 return E_NOINTERFACE
;
4546 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4548 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4549 ULONG ref
= InterlockedIncrement(&This
->ref
);
4550 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4554 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4556 list_remove(&stream
->entry
);
4557 heap_free(stream
->key
);
4561 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4563 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4564 ULONG ref
= InterlockedDecrement(&This
->ref
);
4566 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4569 UnmapViewOfFile(This
->file_ptr
);
4571 EnterCriticalSection(&local_fontfile_loader
.cs
);
4572 release_cached_stream(This
->entry
);
4573 LeaveCriticalSection(&local_fontfile_loader
.cs
);
4581 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
4582 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4584 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4586 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
4587 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4589 *fragment_context
= NULL
;
4591 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4592 *fragment_start
= NULL
;
4596 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4600 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4602 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4603 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4606 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4608 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4609 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4614 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4616 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4619 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4621 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4622 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4623 *last_writetime
= li
.QuadPart
;
4628 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4630 localfontfilestream_QueryInterface
,
4631 localfontfilestream_AddRef
,
4632 localfontfilestream_Release
,
4633 localfontfilestream_ReadFileFragment
,
4634 localfontfilestream_ReleaseFileFragment
,
4635 localfontfilestream_GetFileSize
,
4636 localfontfilestream_GetLastWriteTime
4639 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4641 struct dwrite_localfontfilestream
*This
;
4645 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4647 return E_OUTOFMEMORY
;
4649 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4652 This
->file_ptr
= file_ptr
;
4654 This
->entry
= entry
;
4656 *ret
= &This
->IDWriteFontFileStream_iface
;
4660 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4662 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4664 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4666 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
4667 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
4668 IsEqualIID(riid
, &IID_IUnknown
))
4671 IDWriteLocalFontFileLoader_AddRef(iface
);
4675 WARN("%s not implemented.\n", debugstr_guid(riid
));
4678 return E_NOINTERFACE
;
4681 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4683 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4684 ULONG ref
= InterlockedIncrement(&This
->ref
);
4685 TRACE("(%p)->(%d)\n", This
, ref
);
4689 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4691 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4692 ULONG ref
= InterlockedDecrement(&This
->ref
);
4694 TRACE("(%p)->(%d)\n", This
, ref
);
4699 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
4701 const struct local_refkey
*refkey
= key
;
4702 struct local_cached_stream
*stream
;
4703 IDWriteFontFileStream
*filestream
;
4704 HANDLE file
, mapping
;
4711 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4712 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4713 if (file
== INVALID_HANDLE_VALUE
) {
4714 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
4718 GetFileSizeEx(file
, &size
);
4719 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4724 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4725 CloseHandle(mapping
);
4727 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
4731 stream
= heap_alloc(sizeof(*stream
));
4733 UnmapViewOfFile(file_ptr
);
4734 return E_OUTOFMEMORY
;
4737 stream
->key
= heap_alloc(key_size
);
4739 UnmapViewOfFile(file_ptr
);
4741 return E_OUTOFMEMORY
;
4744 stream
->key_size
= key_size
;
4745 memcpy(stream
->key
, key
, key_size
);
4747 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4749 UnmapViewOfFile(file_ptr
);
4750 heap_free(stream
->key
);
4755 stream
->stream
= filestream
;
4762 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
4763 UINT32 key_size
, IDWriteFontFileStream
**ret
)
4765 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4766 const struct local_refkey
*refkey
= key
;
4767 struct local_cached_stream
*stream
;
4770 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, ret
);
4771 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4773 EnterCriticalSection(&This
->cs
);
4777 /* search cache first */
4778 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4779 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4780 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
4785 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
) {
4786 list_add_head(&This
->streams
, &stream
->entry
);
4787 *ret
= stream
->stream
;
4790 LeaveCriticalSection(&This
->cs
);
4795 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4797 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4798 const struct local_refkey
*refkey
= key
;
4800 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4802 *length
= strlenW(refkey
->name
);
4806 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4808 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4809 const struct local_refkey
*refkey
= key
;
4811 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4813 if (length
< strlenW(refkey
->name
))
4814 return E_INVALIDARG
;
4816 strcpyW(path
, refkey
->name
);
4820 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
4821 UINT32 key_size
, FILETIME
*writetime
)
4823 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4824 const struct local_refkey
*refkey
= key
;
4826 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, writetime
);
4828 *writetime
= refkey
->writetime
;
4832 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4833 localfontfileloader_QueryInterface
,
4834 localfontfileloader_AddRef
,
4835 localfontfileloader_Release
,
4836 localfontfileloader_CreateStreamFromKey
,
4837 localfontfileloader_GetFilePathLengthFromKey
,
4838 localfontfileloader_GetFilePathFromKey
,
4839 localfontfileloader_GetLastWriteTimeFromKey
4842 void init_local_fontfile_loader(void)
4844 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4845 local_fontfile_loader
.ref
= 1;
4846 list_init(&local_fontfile_loader
.streams
);
4847 InitializeCriticalSection(&local_fontfile_loader
.cs
);
4848 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
4851 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
4853 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
4856 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4858 struct local_refkey
*refkey
;
4861 return E_INVALIDARG
;
4863 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4866 refkey
= heap_alloc(*size
);
4868 return E_OUTOFMEMORY
;
4871 refkey
->writetime
= *writetime
;
4873 WIN32_FILE_ATTRIBUTE_DATA info
;
4875 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4876 refkey
->writetime
= info
.ftLastWriteTime
;
4878 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4880 strcpyW(refkey
->name
, path
);
4887 /* IDWriteGlyphRunAnalysis */
4888 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4890 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4892 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4894 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4895 IsEqualIID(riid
, &IID_IUnknown
))
4898 IDWriteGlyphRunAnalysis_AddRef(iface
);
4902 WARN("%s not implemented.\n", debugstr_guid(riid
));
4905 return E_NOINTERFACE
;
4908 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4910 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4911 ULONG ref
= InterlockedIncrement(&This
->ref
);
4912 TRACE("(%p)->(%u)\n", This
, ref
);
4916 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4918 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4919 ULONG ref
= InterlockedDecrement(&This
->ref
);
4921 TRACE("(%p)->(%u)\n", This
, ref
);
4924 if (This
->run
.fontFace
)
4925 IDWriteFontFace_Release(This
->run
.fontFace
);
4926 heap_free(This
->glyphs
);
4927 heap_free(This
->origins
);
4928 heap_free(This
->bitmap
);
4935 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
4939 case DWRITE_RENDERING_MODE1_NATURAL
:
4940 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
4941 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
4948 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
4950 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
4953 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4955 struct dwrite_glyphbitmap glyph_bitmap
;
4956 IDWriteFontFace4
*fontface
;
4960 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4961 *bounds
= analysis
->bounds
;
4965 if (analysis
->run
.isSideways
)
4966 FIXME("sideways runs are not supported.\n");
4968 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
4970 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
4972 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4973 glyph_bitmap
.fontface
= fontface
;
4974 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
4975 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
4976 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
4977 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4978 glyph_bitmap
.m
= &analysis
->m
;
4980 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4981 RECT
*bbox
= &glyph_bitmap
.bbox
;
4984 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4985 freetype_get_glyph_bbox(&glyph_bitmap
);
4987 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
4988 (bbox
->bottom
- bbox
->top
);
4989 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
4990 analysis
->max_glyph_bitmap_size
= bitmap_size
;
4992 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
4993 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4996 IDWriteFontFace4_Release(fontface
);
4998 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4999 *bounds
= analysis
->bounds
;
5002 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5004 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5006 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
5008 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5009 SetRectEmpty(bounds
);
5010 return E_INVALIDARG
;
5013 if (type
!= This
->texture_type
) {
5014 SetRectEmpty(bounds
);
5018 glyphrunanalysis_get_texturebounds(This
, bounds
);
5022 static inline int get_dib_stride( int width
, int bpp
)
5024 return ((width
* bpp
+ 31) >> 3) & ~3;
5027 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5029 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5030 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5031 (runbounds
->left
- bounds
->left
) * 3;
5033 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5034 runbounds
->left
- bounds
->left
;
5037 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5039 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5040 struct dwrite_glyphbitmap glyph_bitmap
;
5041 IDWriteFontFace4
*fontface
;
5042 D2D_POINT_2F origin
;
5047 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5049 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5053 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5054 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5056 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5057 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5058 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5059 IDWriteFontFace4_Release(fontface
);
5060 return E_OUTOFMEMORY
;
5063 origin
.x
= origin
.y
= 0.0f
;
5065 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5066 glyph_bitmap
.fontface
= fontface
;
5067 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5068 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5069 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5070 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5071 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5072 glyph_bitmap
.m
= &analysis
->m
;
5073 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5074 IDWriteFontFace4_Release(fontface
);
5075 return E_OUTOFMEMORY
;
5078 bbox
= &glyph_bitmap
.bbox
;
5080 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5081 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5082 int x
, y
, width
, height
;
5085 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
5086 freetype_get_glyph_bbox(&glyph_bitmap
);
5088 if (IsRectEmpty(bbox
))
5091 width
= bbox
->right
- bbox
->left
;
5092 height
= bbox
->bottom
- bbox
->top
;
5094 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5095 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5096 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5098 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5100 /* blit to analysis bitmap */
5101 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5104 /* convert 1bpp to 8bpp/24bpp */
5105 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5106 for (y
= 0; y
< height
; y
++) {
5107 for (x
= 0; x
< width
; x
++)
5108 if (src
[x
/ 8] & masks
[x
% 8])
5109 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5110 src
+= glyph_bitmap
.pitch
;
5111 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5115 for (y
= 0; y
< height
; y
++) {
5116 for (x
= 0; x
< width
; x
++)
5117 if (src
[x
/ 8] & masks
[x
% 8])
5118 dst
[x
] = DWRITE_ALPHA_MAX
;
5119 src
+= glyph_bitmap
.pitch
;
5120 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5125 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5126 for (y
= 0; y
< height
; y
++) {
5127 for (x
= 0; x
< width
; x
++)
5128 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5129 src
+= glyph_bitmap
.pitch
;
5130 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5134 for (y
= 0; y
< height
; y
++) {
5135 for (x
= 0; x
< width
; x
++)
5137 src
+= glyph_bitmap
.pitch
;
5138 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5143 heap_free(glyph_bitmap
.buf
);
5145 IDWriteFontFace4_Release(fontface
);
5147 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5149 /* we don't need this anymore */
5150 heap_free(analysis
->glyphs
);
5151 heap_free(analysis
->origins
);
5152 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5154 analysis
->glyphs
= NULL
;
5155 analysis
->origins
= NULL
;
5156 analysis
->run
.glyphIndices
= NULL
;
5157 analysis
->run
.fontFace
= NULL
;
5162 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5163 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5165 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5169 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5171 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5172 return E_INVALIDARG
;
5174 /* make sure buffer is large enough for requested texture type */
5175 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5176 if (This
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5179 if (size
< required
)
5180 return E_NOT_SUFFICIENT_BUFFER
;
5182 /* validate requested texture type */
5183 if (This
->texture_type
!= type
)
5184 return DWRITE_E_UNSUPPORTEDOPERATION
;
5186 memset(bitmap
, 0, size
);
5187 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5188 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5189 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5190 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5191 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5192 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5196 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5199 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5203 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5204 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5206 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5207 memcpy(dst
, src
, draw_width
);
5216 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5217 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5219 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5221 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5224 return E_INVALIDARG
;
5226 switch (This
->rendering_mode
)
5228 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5229 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5232 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5233 *gamma
= (FLOAT
)value
/ 1000.0f
;
5235 *cleartypelevel
= 1.0f
;
5238 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5239 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5241 case DWRITE_RENDERING_MODE1_ALIASED
:
5242 case DWRITE_RENDERING_MODE1_NATURAL
:
5243 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5244 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5245 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5246 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5255 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5256 glyphrunanalysis_QueryInterface
,
5257 glyphrunanalysis_AddRef
,
5258 glyphrunanalysis_Release
,
5259 glyphrunanalysis_GetAlphaTextureBounds
,
5260 glyphrunanalysis_CreateAlphaTexture
,
5261 glyphrunanalysis_GetAlphaBlendParams
5264 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5267 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5268 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5272 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5274 struct dwrite_glyphrunanalysis
*analysis
;
5275 DWRITE_FONT_METRICS metrics
;
5276 IDWriteFontFace1
*fontface1
;
5277 D2D_POINT_2F origin
;
5284 /* Check rendering, antialising, measuring, and grid fitting modes. */
5285 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5286 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5287 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5288 return E_INVALIDARG
;
5290 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5291 return E_INVALIDARG
;
5293 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5294 return E_INVALIDARG
;
5296 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5297 return E_INVALIDARG
;
5299 analysis
= heap_alloc(sizeof(*analysis
));
5301 return E_OUTOFMEMORY
;
5303 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5305 analysis
->rendering_mode
= desc
->rendering_mode
;
5307 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5308 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5309 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5311 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5313 analysis
->flags
= 0;
5314 analysis
->bitmap
= NULL
;
5315 analysis
->max_glyph_bitmap_size
= 0;
5316 SetRectEmpty(&analysis
->bounds
);
5317 analysis
->run
= *desc
->run
;
5318 analysis
->run
.fontEmSize
*= desc
->ppdip
;
5319 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5320 analysis
->glyphs
= heap_alloc(desc
->run
->glyphCount
* sizeof(*analysis
->glyphs
));
5321 analysis
->origins
= heap_alloc(desc
->run
->glyphCount
* sizeof(*analysis
->origins
));
5323 if (!analysis
->glyphs
|| !analysis
->origins
) {
5324 heap_free(analysis
->glyphs
);
5325 heap_free(analysis
->origins
);
5327 analysis
->glyphs
= NULL
;
5328 analysis
->origins
= NULL
;
5330 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5331 return E_OUTOFMEMORY
;
5334 /* check if transform is usable */
5335 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5336 analysis
->m
= *desc
->transform
;
5337 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5340 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5342 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5343 analysis
->run
.glyphAdvances
= NULL
;
5344 analysis
->run
.glyphOffsets
= NULL
;
5346 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5348 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5350 IDWriteFontFace_GetMetrics(desc
->run
->fontFace
, &metrics
);
5351 if (FAILED(hr
= IDWriteFontFace_QueryInterface(desc
->run
->fontFace
, &IID_IDWriteFontFace1
, (void **)&fontface1
)))
5352 WARN("Failed to get IDWriteFontFace1, %#x.\n", hr
);
5354 origin
.x
= desc
->origin_x
* desc
->ppdip
;
5355 origin
.y
= desc
->origin_y
* desc
->ppdip
;
5356 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5359 /* Use nominal advances if not provided by caller. */
5360 if (desc
->run
->glyphAdvances
)
5361 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
] * desc
->ppdip
;
5366 switch (desc
->measuring_mode
)
5368 case DWRITE_MEASURING_MODE_NATURAL
:
5369 if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, desc
->run
->glyphIndices
+ i
, &a
,
5370 desc
->run
->isSideways
)))
5371 advance
= rtl_factor
* get_scaled_advance_width(a
, desc
->run
->fontEmSize
, &metrics
) * desc
->ppdip
;
5373 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5374 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5375 if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, desc
->run
->fontEmSize
,
5376 desc
->ppdip
, desc
->transform
, desc
->measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
,
5377 desc
->run
->isSideways
, 1, desc
->run
->glyphIndices
+ i
, &a
)))
5378 advance
= rtl_factor
* floorf(a
* desc
->run
->fontEmSize
* desc
->ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
);
5385 analysis
->origins
[i
] = origin
;
5387 /* Offsets are optional, appled to pre-transformed origin. */
5388 if (desc
->run
->glyphOffsets
) {
5389 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
* desc
->ppdip
;
5390 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
* desc
->ppdip
;
5392 if (desc
->run
->isSideways
) {
5393 analysis
->origins
[i
].x
+= ascenderoffset
;
5394 analysis
->origins
[i
].y
+= advanceoffset
;
5397 analysis
->origins
[i
].x
+= advanceoffset
;
5398 analysis
->origins
[i
].y
+= ascenderoffset
;
5402 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5403 transform_point(analysis
->origins
+ i
, &analysis
->m
);
5405 if (desc
->run
->isSideways
)
5406 origin
.y
+= advance
;
5408 origin
.x
+= advance
;
5411 IDWriteFontFace1_Release(fontface1
);
5413 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5417 /* IDWriteColorGlyphRunEnumerator */
5418 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
5420 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5422 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5424 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5425 IsEqualIID(riid
, &IID_IUnknown
))
5428 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
5432 WARN("%s not implemented.\n", debugstr_guid(riid
));
5435 return E_NOINTERFACE
;
5438 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
5440 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5441 ULONG ref
= InterlockedIncrement(&This
->ref
);
5442 TRACE("(%p)->(%u)\n", This
, ref
);
5446 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
5448 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5449 ULONG ref
= InterlockedDecrement(&This
->ref
);
5451 TRACE("(%p)->(%u)\n", This
, ref
);
5454 heap_free(This
->advances
);
5455 heap_free(This
->color_advances
);
5456 heap_free(This
->offsets
);
5457 heap_free(This
->color_offsets
);
5458 heap_free(This
->glyphindices
);
5459 heap_free(This
->glyphs
);
5460 if (This
->colr
.context
)
5461 IDWriteFontFace4_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
5462 IDWriteFontFace4_Release(This
->fontface
);
5469 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5471 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5472 FLOAT origin
= 0.0f
;
5478 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5482 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5484 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5485 FLOAT advance_adj
= 0.0f
;
5486 BOOL got_palette_index
;
5489 /* start with regular glyphs */
5490 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5491 UINT32 first_glyph
= 0;
5493 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5494 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5495 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5496 first_glyph
= min(first_glyph
, g
);
5499 glyphenum
->glyphindices
[g
] = 1;
5500 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5501 if (glyphenum
->color_offsets
)
5502 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5505 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5506 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5507 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5508 colorrun
->paletteIndex
= 0xffff;
5509 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5510 glyphenum
->has_regular_glyphs
= FALSE
;
5514 colorrun
->glyphRun
.glyphCount
= 0;
5515 got_palette_index
= FALSE
;
5519 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5521 glyphenum
->glyphindices
[g
] = 1;
5523 /* all glyph layers were returned */
5524 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5525 advance_adj
+= glyphenum
->advances
[g
];
5529 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5530 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5531 if (!got_palette_index
) {
5532 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5533 /* use foreground color or request one from the font */
5534 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5535 if (colorrun
->paletteIndex
!= 0xffff) {
5536 HRESULT hr
= IDWriteFontFace4_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5537 1, &colorrun
->runColor
);
5539 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5540 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5542 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5543 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5544 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5545 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5546 got_palette_index
= TRUE
;
5549 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5550 /* offsets are relative to glyph origin, nothing to fix up */
5551 if (glyphenum
->color_offsets
)
5552 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5553 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5555 glyphenum
->color_advances
[index
-1] += advance_adj
;
5556 colorrun
->glyphRun
.glyphCount
++;
5560 advance_adj
+= glyphenum
->advances
[g
];
5563 /* reset last advance */
5564 if (colorrun
->glyphRun
.glyphCount
)
5565 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5567 return colorrun
->glyphRun
.glyphCount
> 0;
5570 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5572 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5574 TRACE("(%p)->(%p)\n", This
, has_run
);
5578 This
->colorrun
.glyphRun
.glyphCount
= 0;
5579 while (This
->current_layer
< This
->max_layer_num
) {
5580 if (colorglyphenum_build_color_run(This
))
5583 This
->current_layer
++;
5586 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5591 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5593 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5595 TRACE("(%p)->(%p)\n", This
, run
);
5597 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5599 return E_NOT_VALID_STATE
;
5602 *run
= &This
->colorrun
;
5606 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5607 colorglyphenum_QueryInterface
,
5608 colorglyphenum_AddRef
,
5609 colorglyphenum_Release
,
5610 colorglyphenum_MoveNext
,
5611 colorglyphenum_GetCurrentRun
5614 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5615 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5617 struct dwrite_colorglyphenum
*colorglyphenum
;
5618 BOOL colorfont
, has_colored_glyph
;
5619 IDWriteFontFace4
*fontface
;
5625 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace4
, (void**)&fontface
);
5627 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5631 colorfont
= IDWriteFontFace4_IsColorFont(fontface
) && IDWriteFontFace4_GetColorPaletteCount(fontface
) > palette
;
5633 hr
= DWRITE_E_NOCOLOR
;
5637 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5638 if (!colorglyphenum
) {
5643 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5644 colorglyphenum
->ref
= 1;
5645 colorglyphenum
->origin_x
= originX
;
5646 colorglyphenum
->origin_y
= originY
;
5647 colorglyphenum
->fontface
= fontface
;
5648 colorglyphenum
->glyphs
= NULL
;
5649 colorglyphenum
->run
= *run
;
5650 colorglyphenum
->run
.glyphIndices
= NULL
;
5651 colorglyphenum
->run
.glyphAdvances
= NULL
;
5652 colorglyphenum
->run
.glyphOffsets
= NULL
;
5653 colorglyphenum
->palette
= palette
;
5654 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5655 colorglyphenum
->colr
.exists
= TRUE
;
5656 get_fontface_table(fontface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5657 colorglyphenum
->current_layer
= 0;
5658 colorglyphenum
->max_layer_num
= 0;
5660 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5662 has_colored_glyph
= FALSE
;
5663 colorglyphenum
->has_regular_glyphs
= FALSE
;
5664 for (i
= 0; i
< run
->glyphCount
; i
++) {
5665 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5666 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5667 has_colored_glyph
= TRUE
;
5669 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5670 colorglyphenum
->has_regular_glyphs
= TRUE
;
5673 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5674 is supposed to proceed normally, like if font had no color info at all. */
5675 if (!has_colored_glyph
) {
5676 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5677 return DWRITE_E_NOCOLOR
;
5680 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5681 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5682 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5683 if (run
->glyphOffsets
) {
5684 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5685 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5686 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5689 colorglyphenum
->colorrun
.glyphRun
.fontFace
= (IDWriteFontFace
*)fontface
;
5690 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
5691 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5692 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5693 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5694 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5696 if (run
->glyphAdvances
)
5697 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5699 DWRITE_FONT_METRICS metrics
;
5701 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5702 for (i
= 0; i
< run
->glyphCount
; i
++) {
5706 switch (measuring_mode
)
5708 case DWRITE_MEASURING_MODE_NATURAL
:
5709 hr
= IDWriteFontFace4_GetDesignGlyphAdvances(fontface
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5712 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5714 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5715 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5716 hr
= IDWriteFontFace4_GetGdiCompatibleGlyphAdvances(fontface
, run
->fontEmSize
, 1.0f
, transform
,
5717 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5719 colorglyphenum
->advances
[i
] = 0.0f
;
5721 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5729 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5733 IDWriteFontFace4_Release(fontface
);
5737 /* IDWriteFontFaceReference */
5738 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
5740 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5742 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5744 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) || IsEqualIID(riid
, &IID_IUnknown
)) {
5746 IDWriteFontFaceReference_AddRef(iface
);
5750 WARN("%s not implemented.\n", debugstr_guid(riid
));
5754 return E_NOINTERFACE
;
5757 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference
*iface
)
5759 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5760 ULONG ref
= InterlockedIncrement(&This
->ref
);
5761 TRACE("(%p)->(%u)\n", This
, ref
);
5765 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference
*iface
)
5767 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5768 ULONG ref
= InterlockedDecrement(&This
->ref
);
5770 TRACE("(%p)->(%u)\n", This
, ref
);
5773 IDWriteFontFile_Release(This
->file
);
5774 IDWriteFactory5_Release(This
->factory
);
5781 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference
*iface
, IDWriteFontFace3
**fontface
)
5783 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5785 TRACE("(%p)->(%p)\n", This
, fontface
);
5787 return IDWriteFontFaceReference_CreateFontFaceWithSimulations(iface
, This
->simulations
, fontface
);
5790 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
5791 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
5793 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5794 DWRITE_FONT_FILE_TYPE file_type
;
5795 DWRITE_FONT_FACE_TYPE face_type
;
5796 IDWriteFontFace
*fontface
;
5801 TRACE("(%p)->(%d %p)\n", This
, simulations
, ret
);
5803 hr
= IDWriteFontFile_Analyze(This
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
5807 hr
= IDWriteFactory5_CreateFontFace(This
->factory
, face_type
, 1, &This
->file
, This
->index
, simulations
, &fontface
);
5808 if (SUCCEEDED(hr
)) {
5809 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
5810 IDWriteFontFace_Release(fontface
);
5816 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
5818 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5819 IDWriteFontFile
*file
;
5822 TRACE("(%p)->(%p)\n", This
, ref
);
5824 if (FAILED(IDWriteFontFaceReference_GetFontFile(ref
, &file
)))
5827 ret
= is_same_fontfile(This
->file
, file
) &&
5828 This
->index
== IDWriteFontFaceReference_GetFontFaceIndex(ref
) &&
5829 This
->simulations
== IDWriteFontFaceReference_GetSimulations(ref
);
5830 IDWriteFontFile_Release(file
);
5835 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
5837 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5839 TRACE("(%p)\n", This
);
5844 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference
*iface
)
5846 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5848 TRACE("(%p)\n", This
);
5850 return This
->simulations
;
5853 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
5855 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5856 IDWriteFontFileLoader
*loader
;
5861 TRACE("(%p)->(%p)\n", This
, file
);
5863 hr
= IDWriteFontFile_GetReferenceKey(This
->file
, &key
, &key_size
);
5867 hr
= IDWriteFontFile_GetLoader(This
->file
, &loader
);
5871 hr
= IDWriteFactory5_CreateCustomFontFileReference(This
->factory
, key
, key_size
, loader
, file
);
5872 IDWriteFontFileLoader_Release(loader
);
5877 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
5879 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5881 FIXME("(%p): stub\n", This
);
5886 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference
*iface
)
5888 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5890 FIXME("(%p): stub\n", This
);
5895 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
5897 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5899 FIXME("(%p)->(%p): stub\n", This
, writetime
);
5904 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference
*iface
)
5906 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5908 FIXME("(%p): stub\n", This
);
5910 return DWRITE_LOCALITY_LOCAL
;
5913 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
5915 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5917 FIXME("(%p): stub\n", This
);
5922 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
, WCHAR
const *chars
,
5925 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5927 FIXME("(%p)->(%s:%u): stub\n", This
, debugstr_wn(chars
, count
), count
);
5932 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
, UINT16
const *glyphs
,
5935 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5937 FIXME("(%p)->(%p %u): stub\n", This
, glyphs
, count
);
5942 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
5943 UINT64 offset
, UINT64 size
)
5945 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5947 FIXME("(%p)->(0x%s 0x%s): stub\n", This
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
5952 static const IDWriteFontFaceReferenceVtbl fontfacereferencevtbl
= {
5953 fontfacereference_QueryInterface
,
5954 fontfacereference_AddRef
,
5955 fontfacereference_Release
,
5956 fontfacereference_CreateFontFace
,
5957 fontfacereference_CreateFontFaceWithSimulations
,
5958 fontfacereference_Equals
,
5959 fontfacereference_GetFontFaceIndex
,
5960 fontfacereference_GetSimulations
,
5961 fontfacereference_GetFontFile
,
5962 fontfacereference_GetLocalFileSize
,
5963 fontfacereference_GetFileSize
,
5964 fontfacereference_GetFileTime
,
5965 fontfacereference_GetLocality
,
5966 fontfacereference_EnqueueFontDownloadRequest
,
5967 fontfacereference_EnqueueCharacterDownloadRequest
,
5968 fontfacereference_EnqueueGlyphDownloadRequest
,
5969 fontfacereference_EnqueueFileFragmentDownloadRequest
5972 HRESULT
create_fontfacereference(IDWriteFactory5
*factory
, IDWriteFontFile
*file
, UINT32 index
,
5973 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFaceReference
**ret
)
5975 struct dwrite_fontfacereference
*ref
;
5979 if (!is_simulation_valid(simulations
))
5980 return E_INVALIDARG
;
5982 ref
= heap_alloc(sizeof(*ref
));
5984 return E_OUTOFMEMORY
;
5986 ref
->IDWriteFontFaceReference_iface
.lpVtbl
= &fontfacereferencevtbl
;
5989 ref
->factory
= factory
;
5990 IDWriteFactory5_AddRef(ref
->factory
);
5992 IDWriteFontFile_AddRef(ref
->file
);
5994 ref
->simulations
= simulations
;
5995 *ret
= &ref
->IDWriteFontFaceReference_iface
;
6000 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6002 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6004 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6006 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6008 IDWriteFontFileStream_AddRef(iface
);
6014 WARN("%s not implemented.\n", debugstr_guid(riid
));
6015 return E_NOINTERFACE
;
6018 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6020 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6021 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6022 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6026 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6028 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6029 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6031 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6034 release_inmemory_stream(stream
->data
);
6041 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6042 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6044 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6046 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6047 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6049 *fragment_context
= NULL
;
6051 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6052 *fragment_start
= NULL
;
6056 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6060 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6062 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6064 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6067 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6069 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6071 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6073 *size
= stream
->data
->size
;
6078 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6080 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6082 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6084 *last_writetime
= 0;
6089 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6090 inmemoryfilestream_QueryInterface
,
6091 inmemoryfilestream_AddRef
,
6092 inmemoryfilestream_Release
,
6093 inmemoryfilestream_ReadFileFragment
,
6094 inmemoryfilestream_ReleaseFileFragment
,
6095 inmemoryfilestream_GetFileSize
,
6096 inmemoryfilestream_GetLastWriteTime
,
6099 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6100 REFIID riid
, void **obj
)
6102 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6104 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6106 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6107 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6108 IsEqualIID(riid
, &IID_IUnknown
))
6111 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6115 WARN("%s not implemented.\n", debugstr_guid(riid
));
6119 return E_NOINTERFACE
;
6122 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6124 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6125 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6126 TRACE("(%p)->(%u)\n", loader
, ref
);
6130 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6132 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6133 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6135 TRACE("(%p)->(%u)\n", loader
, ref
);
6140 for (i
= 0; i
< loader
->filecount
; i
++)
6141 release_inmemory_stream(loader
->streams
[i
]);
6142 heap_free(loader
->streams
);
6149 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6150 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6152 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6153 struct dwrite_inmemory_filestream
*stream
;
6156 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6160 if (key_size
!= sizeof(DWORD
))
6161 return E_INVALIDARG
;
6163 index
= *(DWORD
*)key
;
6165 if (index
>= loader
->filecount
)
6166 return E_INVALIDARG
;
6168 if (!(stream
= heap_alloc(sizeof(*stream
))))
6169 return E_OUTOFMEMORY
;
6171 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6173 stream
->data
= loader
->streams
[index
];
6174 InterlockedIncrement(&stream
->data
->ref
);
6176 *ret
= &stream
->IDWriteFontFileStream_iface
;
6181 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6182 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6184 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6185 struct dwrite_inmemory_stream_data
*stream
;
6188 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6192 if (loader
->filecount
== loader
->capacity
) {
6193 if (loader
->streams
) {
6194 struct dwrite_inmemory_stream_data
**ptr
;
6196 if (!(ptr
= heap_realloc(loader
->streams
, 2 * loader
->capacity
* sizeof(*loader
->streams
))))
6197 return E_OUTOFMEMORY
;
6199 loader
->streams
= ptr
;
6200 loader
->capacity
*= 2;
6203 loader
->capacity
= 16;
6204 loader
->streams
= heap_alloc(loader
->capacity
* sizeof(*loader
->streams
));
6208 if (!(stream
= heap_alloc(sizeof(*stream
))))
6209 return E_OUTOFMEMORY
;
6212 stream
->size
= data_size
;
6213 stream
->owner
= owner
;
6214 if (stream
->owner
) {
6215 IUnknown_AddRef(stream
->owner
);
6216 stream
->data
= (void *)data
;
6219 if (!(stream
->data
= heap_alloc(data_size
))) {
6221 return E_OUTOFMEMORY
;
6223 memcpy(stream
->data
, data
, data_size
);
6226 key
= loader
->filecount
;
6227 loader
->streams
[loader
->filecount
++] = stream
;
6229 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6230 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6233 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6235 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6237 TRACE("(%p)\n", loader
);
6239 return loader
->filecount
;
6242 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6244 inmemoryfontfileloader_QueryInterface
,
6245 inmemoryfontfileloader_AddRef
,
6246 inmemoryfontfileloader_Release
,
6247 inmemoryfontfileloader_CreateStreamFromKey
,
6248 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6249 inmemoryfontfileloader_GetFileCount
,
6252 HRESULT
create_inmemory_fileloader(IDWriteFontFileLoader
**ret
)
6254 struct dwrite_inmemory_fileloader
*loader
;
6258 loader
= heap_alloc_zero(sizeof(*loader
));
6260 return E_OUTOFMEMORY
;
6262 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6265 *ret
= (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
;