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
**streams
;
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
++) {
518 if (This
->streams
[i
])
519 IDWriteFontFileStream_Release(This
->streams
[i
]);
521 IDWriteFontFile_Release(This
->files
[i
]);
523 heap_free(This
->streams
);
524 heap_free(This
->files
);
526 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
527 heap_free(This
->glyphs
[i
]);
529 freetype_notify_cacheremove(iface
);
531 IDWriteFactory5_Release(This
->factory
);
538 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace4
*iface
)
540 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
541 TRACE("(%p)\n", This
);
545 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace4
*iface
, UINT32
*number_of_files
,
546 IDWriteFontFile
**fontfiles
)
548 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
551 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
552 if (fontfiles
== NULL
)
554 *number_of_files
= This
->file_count
;
557 if (*number_of_files
< This
->file_count
)
560 for (i
= 0; i
< This
->file_count
; i
++)
562 IDWriteFontFile_AddRef(This
->files
[i
]);
563 fontfiles
[i
] = This
->files
[i
];
569 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace4
*iface
)
571 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
572 TRACE("(%p)\n", This
);
576 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace4
*iface
)
578 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
579 TRACE("(%p)\n", This
);
580 return This
->simulations
;
583 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace4
*iface
)
585 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
586 TRACE("(%p)\n", This
);
587 return !!(This
->flags
& FONTFACE_IS_SYMBOL
);
590 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace4
*iface
, DWRITE_FONT_METRICS
*metrics
)
592 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
593 TRACE("(%p)->(%p)\n", This
, metrics
);
594 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
597 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace4
*iface
)
599 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
600 TRACE("(%p)\n", This
);
601 return freetype_get_glyphcount(iface
);
604 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace4
*iface
,
605 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
607 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
611 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
617 FIXME("sideways metrics are not supported.\n");
619 for (i
= 0; i
< glyph_count
; i
++) {
620 DWRITE_GLYPH_METRICS metrics
;
622 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
624 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
625 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
635 static HRESULT
fontface_get_glyphs(struct dwrite_fontface
*fontface
, UINT32
const *codepoints
,
636 UINT32 count
, UINT16
*glyphs
)
642 memset(glyphs
, 0, count
* sizeof(*glyphs
));
646 freetype_get_glyphs(&fontface
->IDWriteFontFace4_iface
, fontface
->charmap
, codepoints
, count
, glyphs
);
650 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace4
*iface
, UINT32
const *codepoints
,
651 UINT32 count
, UINT16
*glyphs
)
653 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
655 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyphs
);
657 return fontface_get_glyphs(This
, codepoints
, count
, glyphs
);
660 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace4
*iface
, UINT32 table_tag
,
661 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
663 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
664 struct file_stream_desc stream_desc
;
666 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
668 stream_desc
.stream
= This
->streams
[0];
669 stream_desc
.face_type
= This
->type
;
670 stream_desc
.face_index
= This
->index
;
671 return opentype_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
674 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace4
*iface
, void *table_context
)
676 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
678 TRACE("(%p)->(%p)\n", This
, table_context
);
680 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
683 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace4
*iface
, FLOAT emSize
,
684 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
685 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
687 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
689 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
690 count
, is_sideways
, is_rtl
, sink
);
692 if (!glyphs
|| !sink
)
696 FIXME("sideways mode is not supported.\n");
698 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
701 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
702 FLOAT ppem
, WORD gasp
)
704 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
708 case DWRITE_MEASURING_MODE_NATURAL
:
710 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
711 mode
= DWRITE_RENDERING_MODE_NATURAL
;
713 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
716 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
717 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
719 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
720 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
729 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
,
730 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
732 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
737 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
740 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
744 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
745 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
748 ppem
= emSize
* ppdip
;
750 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
751 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
755 ptr
= get_fontface_gasp(This
, &size
);
756 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
757 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
761 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
762 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
764 DWRITE_FONT_METRICS1 metrics1
;
765 HRESULT hr
= IDWriteFontFace4_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
766 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
770 static inline int round_metric(FLOAT metric
)
772 return (int)floorf(metric
+ 0.5f
);
775 static UINT32
fontface_get_horz_metric_adjustment(const struct dwrite_fontface
*fontface
)
777 if (!(fontface
->simulations
& DWRITE_FONT_SIMULATIONS_BOLD
))
780 return (fontface
->metrics
.designUnitsPerEm
+ 49) / 50;
783 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT ppdip
,
784 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
785 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
787 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
788 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
789 DWRITE_MEASURING_MODE mode
;
794 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
795 glyph_count
, metrics
, is_sideways
);
797 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
798 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
800 size
= emSize
* ppdip
;
801 scale
= size
/ This
->metrics
.designUnitsPerEm
;
802 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
804 for (i
= 0; i
< glyph_count
; i
++) {
805 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
806 DWRITE_GLYPH_METRICS design
;
809 hr
= IDWriteFontFace4_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
813 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
, &has_contours
);
815 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
+ adjustment
);
817 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
819 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
820 SCALE_METRIC(leftSideBearing
);
821 SCALE_METRIC(rightSideBearing
);
822 SCALE_METRIC(topSideBearing
);
823 SCALE_METRIC(advanceHeight
);
824 SCALE_METRIC(bottomSideBearing
);
825 SCALE_METRIC(verticalOriginY
);
832 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace4
*iface
, DWRITE_FONT_METRICS1
*metrics
)
834 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
835 TRACE("(%p)->(%p)\n", This
, metrics
);
836 *metrics
= This
->metrics
;
839 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace4
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
840 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
842 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
843 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
844 UINT16 ascent
, descent
;
847 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
849 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
850 memset(metrics
, 0, sizeof(*metrics
));
854 em_size
*= pixels_per_dip
;
855 if (m
&& m
->m22
!= 0.0f
)
856 em_size
*= fabs(m
->m22
);
858 scale
= em_size
/ design
->designUnitsPerEm
;
859 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
860 ascent
= round_metric(design
->ascent
* scale
);
861 descent
= round_metric(design
->descent
* scale
);
864 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
865 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
866 metrics
->ascent
= round_metric(ascent
/ scale
);
867 metrics
->descent
= round_metric(descent
/ scale
);
869 SCALE_METRIC(lineGap
);
870 SCALE_METRIC(capHeight
);
871 SCALE_METRIC(xHeight
);
872 SCALE_METRIC(underlinePosition
);
873 SCALE_METRIC(underlineThickness
);
874 SCALE_METRIC(strikethroughPosition
);
875 SCALE_METRIC(strikethroughThickness
);
876 SCALE_METRIC(glyphBoxLeft
);
877 SCALE_METRIC(glyphBoxTop
);
878 SCALE_METRIC(glyphBoxRight
);
879 SCALE_METRIC(glyphBoxBottom
);
880 SCALE_METRIC(subscriptPositionX
);
881 SCALE_METRIC(subscriptPositionY
);
882 SCALE_METRIC(subscriptSizeX
);
883 SCALE_METRIC(subscriptSizeY
);
884 SCALE_METRIC(superscriptPositionX
);
885 SCALE_METRIC(superscriptPositionY
);
886 SCALE_METRIC(superscriptSizeX
);
887 SCALE_METRIC(superscriptSizeY
);
889 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
895 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace4
*iface
, DWRITE_CARET_METRICS
*metrics
)
897 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
898 TRACE("(%p)->(%p)\n", This
, metrics
);
899 *metrics
= This
->caret
;
902 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace4
*iface
, UINT32 max_count
,
903 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
905 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
907 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
910 if (max_count
&& !ranges
)
913 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
916 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace4
*iface
)
918 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
919 TRACE("(%p)\n", This
);
920 return !!(This
->flags
& FONTFACE_IS_MONOSPACED
);
923 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace4
*iface
,
924 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
926 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
927 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
930 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
933 FIXME("sideways mode not supported\n");
935 for (i
= 0; i
< glyph_count
; i
++) {
938 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
],
939 DWRITE_MEASURING_MODE_NATURAL
, &has_contours
);
941 advances
[i
] += adjustment
;
947 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace4
*iface
,
948 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
949 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
951 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
952 UINT32 adjustment
= fontface_get_horz_metric_adjustment(This
);
953 DWRITE_MEASURING_MODE mode
;
956 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
957 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
959 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
960 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
965 if (em_size
== 0.0f
) {
966 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
970 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
971 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
973 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
974 for (i
= 0; i
< glyph_count
; i
++) {
977 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
, &has_contours
);
979 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
+ adjustment
);
981 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
987 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace4
*iface
, UINT32 count
,
988 const UINT16
*indices
, INT32
*adjustments
)
990 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
993 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
995 if (!(indices
|| adjustments
) || !count
)
998 if (!indices
|| count
== 1) {
999 memset(adjustments
, 0, count
*sizeof(INT32
));
1000 return E_INVALIDARG
;
1003 if (!(This
->flags
& FONTFACE_HAS_KERNING_PAIRS
)) {
1004 memset(adjustments
, 0, count
*sizeof(INT32
));
1008 for (i
= 0; i
< count
-1; i
++)
1009 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
1010 adjustments
[count
-1] = 0;
1015 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace4
*iface
)
1017 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1018 TRACE("(%p)\n", This
);
1019 return !!(This
->flags
& FONTFACE_HAS_KERNING_PAIRS
);
1022 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
,
1023 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1024 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1026 DWRITE_GRID_FIT_MODE gridfitmode
;
1027 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
1028 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1031 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace4
*iface
, UINT32 glyph_count
,
1032 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
1034 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1035 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
1039 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace4
*iface
)
1041 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1042 TRACE("(%p)\n", This
);
1043 return !!(This
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
1046 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace4
*iface
)
1048 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1049 TRACE("(%p)\n", This
);
1050 return get_fontface_cpal(This
) && get_fontface_colr(This
);
1053 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace4
*iface
)
1055 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1056 TRACE("(%p)\n", This
);
1057 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
1060 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace4
*iface
)
1062 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1063 TRACE("(%p)\n", This
);
1064 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
1067 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace4
*iface
, UINT32 palette_index
,
1068 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1070 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1071 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
1072 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
1075 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
,
1076 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1077 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1078 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1080 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1085 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1086 measuringmode
, params
, renderingmode
, gridfitmode
);
1089 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1092 FIXME("sideways mode not supported\n");
1094 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1096 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1097 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1099 IDWriteRenderingParams2
*params2
;
1102 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1104 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1105 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1106 IDWriteRenderingParams2_Release(params2
);
1109 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1112 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1114 ptr
= get_fontface_gasp(This
, &size
);
1115 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1117 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1118 if (emSize
>= emthreshold
)
1119 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1121 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1124 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1125 if (emSize
>= emthreshold
)
1126 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1127 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1128 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1130 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1136 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace4
*iface
, IDWriteFontFaceReference
**ref
)
1138 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1139 FIXME("(%p)->(%p): stub\n", This
, ref
);
1143 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace4
*iface
, DWRITE_PANOSE
*panose
)
1145 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1146 TRACE("(%p)->(%p)\n", This
, panose
);
1147 *panose
= This
->panose
;
1150 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace4
*iface
)
1152 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1153 TRACE("(%p)\n", This
);
1154 return This
->weight
;
1157 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace4
*iface
)
1159 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1160 TRACE("(%p)\n", This
);
1161 return This
->stretch
;
1164 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace4
*iface
)
1166 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1167 TRACE("(%p)\n", This
);
1171 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace4
*iface
, IDWriteLocalizedStrings
**names
)
1173 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1174 FIXME("(%p)->(%p): stub\n", This
, names
);
1178 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace4
*iface
, IDWriteLocalizedStrings
**names
)
1180 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1181 FIXME("(%p)->(%p): stub\n", This
, names
);
1185 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace4
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1186 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1188 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1189 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1193 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace4
*iface
, UINT32 ch
)
1195 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1198 TRACE("(%p)->(%#x)\n", This
, ch
);
1201 if (FAILED(fontface_get_glyphs(This
, &ch
, 1, &index
)))
1207 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace4
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1208 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1209 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1211 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1216 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1217 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1220 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1223 FIXME("sideways mode not supported\n");
1225 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1227 *rendering_mode
= DWRITE_RENDERING_MODE1_DEFAULT
;
1228 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1230 IDWriteRenderingParams3
*params3
;
1233 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1235 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1236 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1237 IDWriteRenderingParams3_Release(params3
);
1240 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1243 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1245 ptr
= get_fontface_gasp(This
, &size
);
1246 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1248 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1249 if (emSize
>= emthreshold
)
1250 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1252 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, gasp
);
1255 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1256 if (emSize
>= emthreshold
)
1257 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1258 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1259 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1261 *gridfit_mode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1267 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace4
*iface
, UINT32 ch
)
1269 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1270 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1274 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace4
*iface
, UINT16 glyph
)
1276 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1277 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1281 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace4
*iface
, WCHAR
const *text
,
1282 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1284 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1285 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1289 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace4
*iface
, UINT16
const *glyphs
,
1290 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1292 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1293 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1297 static HRESULT WINAPI
dwritefontface4_GetGlyphImageFormats_(IDWriteFontFace4
*iface
, UINT16 glyph
,
1298 UINT32 ppem_first
, UINT32 ppem_last
, DWRITE_GLYPH_IMAGE_FORMATS
*formats
)
1300 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1301 FIXME("(%p)->(%u %u %u %p): stub\n", This
, glyph
, ppem_first
, ppem_last
, formats
);
1305 static DWRITE_GLYPH_IMAGE_FORMATS WINAPI
dwritefontface4_GetGlyphImageFormats(IDWriteFontFace4
*iface
)
1307 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1309 TRACE("(%p)\n", This
);
1311 return This
->glyph_image_formats
;
1314 static HRESULT WINAPI
dwritefontface4_GetGlyphImageData(IDWriteFontFace4
*iface
, UINT16 glyph
,
1315 UINT32 ppem
, DWRITE_GLYPH_IMAGE_FORMATS format
, DWRITE_GLYPH_IMAGE_DATA
*data
, void **context
)
1317 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1318 FIXME("(%p)->(%u %u %d %p %p): stub\n", This
, glyph
, ppem
, format
, data
, context
);
1322 static void WINAPI
dwritefontface4_ReleaseGlyphImageData(IDWriteFontFace4
*iface
, void *context
)
1324 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace4(iface
);
1325 FIXME("(%p)->(%p): stub\n", This
, context
);
1328 static const IDWriteFontFace4Vtbl dwritefontfacevtbl
= {
1329 dwritefontface_QueryInterface
,
1330 dwritefontface_AddRef
,
1331 dwritefontface_Release
,
1332 dwritefontface_GetType
,
1333 dwritefontface_GetFiles
,
1334 dwritefontface_GetIndex
,
1335 dwritefontface_GetSimulations
,
1336 dwritefontface_IsSymbolFont
,
1337 dwritefontface_GetMetrics
,
1338 dwritefontface_GetGlyphCount
,
1339 dwritefontface_GetDesignGlyphMetrics
,
1340 dwritefontface_GetGlyphIndices
,
1341 dwritefontface_TryGetFontTable
,
1342 dwritefontface_ReleaseFontTable
,
1343 dwritefontface_GetGlyphRunOutline
,
1344 dwritefontface_GetRecommendedRenderingMode
,
1345 dwritefontface_GetGdiCompatibleMetrics
,
1346 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1347 dwritefontface1_GetMetrics
,
1348 dwritefontface1_GetGdiCompatibleMetrics
,
1349 dwritefontface1_GetCaretMetrics
,
1350 dwritefontface1_GetUnicodeRanges
,
1351 dwritefontface1_IsMonospacedFont
,
1352 dwritefontface1_GetDesignGlyphAdvances
,
1353 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1354 dwritefontface1_GetKerningPairAdjustments
,
1355 dwritefontface1_HasKerningPairs
,
1356 dwritefontface1_GetRecommendedRenderingMode
,
1357 dwritefontface1_GetVerticalGlyphVariants
,
1358 dwritefontface1_HasVerticalGlyphVariants
,
1359 dwritefontface2_IsColorFont
,
1360 dwritefontface2_GetColorPaletteCount
,
1361 dwritefontface2_GetPaletteEntryCount
,
1362 dwritefontface2_GetPaletteEntries
,
1363 dwritefontface2_GetRecommendedRenderingMode
,
1364 dwritefontface3_GetFontFaceReference
,
1365 dwritefontface3_GetPanose
,
1366 dwritefontface3_GetWeight
,
1367 dwritefontface3_GetStretch
,
1368 dwritefontface3_GetStyle
,
1369 dwritefontface3_GetFamilyNames
,
1370 dwritefontface3_GetFaceNames
,
1371 dwritefontface3_GetInformationalStrings
,
1372 dwritefontface3_HasCharacter
,
1373 dwritefontface3_GetRecommendedRenderingMode
,
1374 dwritefontface3_IsCharacterLocal
,
1375 dwritefontface3_IsGlyphLocal
,
1376 dwritefontface3_AreCharactersLocal
,
1377 dwritefontface3_AreGlyphsLocal
,
1378 dwritefontface4_GetGlyphImageFormats_
,
1379 dwritefontface4_GetGlyphImageFormats
,
1380 dwritefontface4_GetGlyphImageData
,
1381 dwritefontface4_ReleaseGlyphImageData
1384 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace4
**fontface
)
1386 struct dwrite_font_data
*data
= font
->data
;
1387 struct fontface_desc desc
;
1388 struct list
*cached_list
;
1393 hr
= factory_get_cached_fontface(font
->family
->collection
->factory
, &data
->file
, data
->face_index
,
1394 font
->data
->simulations
, &cached_list
, &IID_IDWriteFontFace4
, (void **)fontface
);
1398 desc
.factory
= font
->family
->collection
->factory
;
1399 desc
.face_type
= data
->face_type
;
1400 desc
.files
= &data
->file
;
1401 desc
.files_number
= 1;
1402 desc
.index
= data
->face_index
;
1403 desc
.simulations
= data
->simulations
;
1404 desc
.font_data
= data
;
1405 return create_fontface(&desc
, cached_list
, fontface
);
1408 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1410 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1412 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1414 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1415 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1416 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1417 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1418 IsEqualIID(riid
, &IID_IUnknown
))
1421 IDWriteFont3_AddRef(iface
);
1425 WARN("%s not implemented.\n", debugstr_guid(riid
));
1428 return E_NOINTERFACE
;
1431 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1433 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1434 ULONG ref
= InterlockedIncrement(&This
->ref
);
1435 TRACE("(%p)->(%d)\n", This
, ref
);
1439 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1441 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1442 ULONG ref
= InterlockedDecrement(&This
->ref
);
1444 TRACE("(%p)->(%d)\n", This
, ref
);
1447 IDWriteFontFamily1_Release(&This
->family
->IDWriteFontFamily1_iface
);
1448 release_font_data(This
->data
);
1455 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1457 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1458 TRACE("(%p)->(%p)\n", This
, family
);
1460 *family
= (IDWriteFontFamily
*)This
->family
;
1461 IDWriteFontFamily_AddRef(*family
);
1465 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1467 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1468 TRACE("(%p)\n", This
);
1469 return This
->data
->weight
;
1472 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1474 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1475 TRACE("(%p)\n", This
);
1476 return This
->data
->stretch
;
1479 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1481 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1482 TRACE("(%p)\n", This
);
1486 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1488 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1489 IDWriteFontFace4
*fontface
;
1493 TRACE("(%p)\n", This
);
1495 hr
= get_fontface_from_font(This
, &fontface
);
1499 ret
= IDWriteFontFace4_IsSymbolFont(fontface
);
1500 IDWriteFontFace4_Release(fontface
);
1504 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1506 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1507 TRACE("(%p)->(%p)\n", This
, names
);
1508 return clone_localizedstring(This
->data
->names
, names
);
1511 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1512 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1514 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1515 struct dwrite_font_data
*data
= This
->data
;
1518 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1523 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1526 if (!data
->info_strings
[stringid
]) {
1527 IDWriteFontFace4
*fontface
;
1528 const void *table_data
;
1533 hr
= get_fontface_from_font(This
, &fontface
);
1537 table_exists
= FALSE
;
1538 hr
= IDWriteFontFace4_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1539 if (FAILED(hr
) || !table_exists
)
1540 WARN("no NAME table found.\n");
1543 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1544 IDWriteFontFace4_ReleaseFontTable(fontface
, context
);
1545 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1548 IDWriteFontFace4_Release(fontface
);
1551 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1559 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1561 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1562 TRACE("(%p)\n", This
);
1563 return This
->data
->simulations
;
1566 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1568 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1570 TRACE("(%p)->(%p)\n", This
, metrics
);
1571 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1574 static HRESULT
font_has_character(struct dwrite_font
*font
, UINT32 ch
, BOOL
*exists
)
1576 IDWriteFontFace4
*fontface
;
1582 hr
= get_fontface_from_font(font
, &fontface
);
1587 hr
= IDWriteFontFace4_GetGlyphIndices(fontface
, &ch
, 1, &index
);
1588 IDWriteFontFace4_Release(fontface
);
1592 *exists
= index
!= 0;
1596 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
, BOOL
*exists
)
1598 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1600 TRACE("(%p)->(%#x %p)\n", This
, ch
, exists
);
1602 return font_has_character(This
, ch
, exists
);
1605 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1607 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1608 TRACE("(%p)->(%p)\n", This
, fontface
);
1609 return IDWriteFont3_CreateFontFace(iface
, (IDWriteFontFace3
**)fontface
);
1612 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1614 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1615 TRACE("(%p)->(%p)\n", This
, metrics
);
1616 *metrics
= This
->data
->metrics
;
1619 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1621 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1622 TRACE("(%p)->(%p)\n", This
, panose
);
1623 *panose
= This
->data
->panose
;
1626 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1628 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1629 IDWriteFontFace4
*fontface
;
1632 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1634 hr
= get_fontface_from_font(This
, &fontface
);
1638 hr
= IDWriteFontFace4_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1639 IDWriteFontFace4_Release(fontface
);
1643 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1645 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1646 IDWriteFontFace4
*fontface
;
1650 TRACE("(%p)\n", This
);
1652 hr
= get_fontface_from_font(This
, &fontface
);
1656 ret
= IDWriteFontFace4_IsMonospacedFont(fontface
);
1657 IDWriteFontFace4_Release(fontface
);
1661 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1663 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1664 IDWriteFontFace4
*fontface
;
1668 TRACE("(%p)\n", This
);
1670 hr
= get_fontface_from_font(This
, &fontface
);
1674 ret
= IDWriteFontFace4_IsColorFont(fontface
);
1675 IDWriteFontFace4_Release(fontface
);
1679 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1681 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1683 TRACE("(%p)->(%p)\n", This
, fontface
);
1685 return get_fontface_from_font(This
, (IDWriteFontFace4
**)fontface
);
1688 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1690 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1691 FIXME("(%p)->(%p): stub\n", This
, font
);
1695 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1697 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1699 TRACE("(%p)->(%p)\n", This
, reference
);
1701 return IDWriteFactory5_CreateFontFaceReference_(This
->family
->collection
->factory
, This
->data
->file
,
1702 This
->data
->face_index
, This
->data
->simulations
, reference
);
1705 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1707 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1710 TRACE("(%p)->(%#x)\n", This
, ch
);
1712 return font_has_character(This
, ch
, &ret
) == S_OK
&& ret
;
1715 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1717 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1718 FIXME("(%p): stub\n", This
);
1719 return DWRITE_LOCALITY_LOCAL
;
1722 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1723 dwritefont_QueryInterface
,
1726 dwritefont_GetFontFamily
,
1727 dwritefont_GetWeight
,
1728 dwritefont_GetStretch
,
1729 dwritefont_GetStyle
,
1730 dwritefont_IsSymbolFont
,
1731 dwritefont_GetFaceNames
,
1732 dwritefont_GetInformationalStrings
,
1733 dwritefont_GetSimulations
,
1734 dwritefont_GetMetrics
,
1735 dwritefont_HasCharacter
,
1736 dwritefont_CreateFontFace
,
1737 dwritefont1_GetMetrics
,
1738 dwritefont1_GetPanose
,
1739 dwritefont1_GetUnicodeRanges
,
1740 dwritefont1_IsMonospacedFont
,
1741 dwritefont2_IsColorFont
,
1742 dwritefont3_CreateFontFace
,
1744 dwritefont3_GetFontFaceReference
,
1745 dwritefont3_HasCharacter
,
1746 dwritefont3_GetLocality
1749 static struct dwrite_font
*unsafe_impl_from_IDWriteFont(IDWriteFont
*iface
)
1753 assert(iface
->lpVtbl
== (IDWriteFontVtbl
*)&dwritefontvtbl
);
1754 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
1757 static struct dwrite_fontface
*unsafe_impl_from_IDWriteFontFace(IDWriteFontFace
*iface
)
1761 assert(iface
->lpVtbl
== (IDWriteFontFaceVtbl
*)&dwritefontfacevtbl
);
1762 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace4_iface
);
1765 void get_logfont_from_font(IDWriteFont
*iface
, LOGFONTW
*lf
)
1767 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1768 *lf
= font
->data
->lf
;
1771 void get_logfont_from_fontface(IDWriteFontFace
*iface
, LOGFONTW
*lf
)
1773 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1777 HRESULT
get_fontsig_from_font(IDWriteFont
*iface
, FONTSIGNATURE
*fontsig
)
1779 struct dwrite_font
*font
= unsafe_impl_from_IDWriteFont(iface
);
1780 *fontsig
= font
->data
->fontsig
;
1784 HRESULT
get_fontsig_from_fontface(IDWriteFontFace
*iface
, FONTSIGNATURE
*fontsig
)
1786 struct dwrite_fontface
*fontface
= unsafe_impl_from_IDWriteFontFace(iface
);
1787 *fontsig
= fontface
->fontsig
;
1791 static HRESULT
create_font(struct dwrite_fontfamily
*family
, UINT32 index
, IDWriteFont3
**font
)
1793 struct dwrite_font
*This
;
1797 This
= heap_alloc(sizeof(*This
));
1799 return E_OUTOFMEMORY
;
1801 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1803 This
->family
= family
;
1804 IDWriteFontFamily1_AddRef(&family
->IDWriteFontFamily1_iface
);
1805 This
->data
= family
->data
->fonts
[index
];
1806 This
->style
= This
->data
->style
;
1807 addref_font_data(This
->data
);
1809 *font
= &This
->IDWriteFont3_iface
;
1814 /* IDWriteFontList1 */
1815 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList1
*iface
, REFIID riid
, void **obj
)
1817 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1819 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1821 if (IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1822 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1823 IsEqualIID(riid
, &IID_IUnknown
))
1826 IDWriteFontList1_AddRef(iface
);
1830 WARN("%s not implemented.\n", debugstr_guid(riid
));
1833 return E_NOINTERFACE
;
1836 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList1
*iface
)
1838 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1839 ULONG ref
= InterlockedIncrement(&This
->ref
);
1840 TRACE("(%p)->(%d)\n", This
, ref
);
1844 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList1
*iface
)
1846 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1847 ULONG ref
= InterlockedDecrement(&This
->ref
);
1849 TRACE("(%p)->(%d)\n", This
, ref
);
1854 for (i
= 0; i
< This
->font_count
; i
++)
1855 release_font_data(This
->fonts
[i
]);
1856 IDWriteFontFamily1_Release(&This
->family
->IDWriteFontFamily1_iface
);
1857 heap_free(This
->fonts
);
1864 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList1
*iface
, IDWriteFontCollection
**collection
)
1866 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1867 return IDWriteFontFamily1_GetFontCollection(&This
->family
->IDWriteFontFamily1_iface
, collection
);
1870 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList1
*iface
)
1872 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1873 TRACE("(%p)\n", This
);
1874 return This
->font_count
;
1877 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont
**font
)
1879 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1881 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1885 if (This
->font_count
== 0)
1888 if (index
>= This
->font_count
)
1889 return E_INVALIDARG
;
1891 return create_font(This
->family
, index
, (IDWriteFont3
**)font
);
1894 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList1
*iface
, UINT32 index
)
1896 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1898 FIXME("(%p)->(%u): stub\n", This
, index
);
1900 return DWRITE_LOCALITY_LOCAL
;
1903 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1905 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1907 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1911 if (This
->font_count
== 0)
1914 if (index
>= This
->font_count
)
1917 return create_font(This
->family
, index
, font
);
1920 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList1
*iface
, UINT32 index
,
1921 IDWriteFontFaceReference
**reference
)
1923 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1927 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
1931 hr
= IDWriteFontList1_GetFont(iface
, index
, &font
);
1935 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
1936 IDWriteFont3_Release(font
);
1941 static const IDWriteFontList1Vtbl dwritefontlistvtbl
= {
1942 dwritefontlist_QueryInterface
,
1943 dwritefontlist_AddRef
,
1944 dwritefontlist_Release
,
1945 dwritefontlist_GetFontCollection
,
1946 dwritefontlist_GetFontCount
,
1947 dwritefontlist_GetFont
,
1948 dwritefontlist1_GetFontLocality
,
1949 dwritefontlist1_GetFont
,
1950 dwritefontlist1_GetFontFaceReference
1953 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1955 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1957 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1959 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1960 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1961 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1962 IsEqualIID(riid
, &IID_IUnknown
))
1965 IDWriteFontFamily1_AddRef(iface
);
1969 WARN("%s not implemented.\n", debugstr_guid(riid
));
1972 return E_NOINTERFACE
;
1975 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1977 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1978 ULONG ref
= InterlockedIncrement(&This
->ref
);
1979 TRACE("(%p)->(%d)\n", This
, ref
);
1983 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1985 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1986 ULONG ref
= InterlockedDecrement(&This
->ref
);
1988 TRACE("(%p)->(%d)\n", This
, ref
);
1992 IDWriteFontCollection1_Release(&This
->collection
->IDWriteFontCollection1_iface
);
1993 release_fontfamily_data(This
->data
);
2000 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
2002 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2004 TRACE("(%p)->(%p)\n", This
, collection
);
2006 *collection
= (IDWriteFontCollection
*)This
->collection
;
2007 IDWriteFontCollection_AddRef(*collection
);
2011 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
2013 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2014 TRACE("(%p)\n", This
);
2015 return This
->data
->font_count
;
2018 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
2020 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2022 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
2026 if (This
->data
->font_count
== 0)
2029 if (index
>= This
->data
->font_count
)
2030 return E_INVALIDARG
;
2032 return create_font(This
, index
, (IDWriteFont3
**)font
);
2035 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
2037 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2038 return clone_localizedstring(This
->data
->familyname
, names
);
2041 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
2042 const struct dwrite_font_propvec
*req
)
2044 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
2045 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
2046 FLOAT cur_req_prod
, next_req_prod
;
2048 if (next_to_req
< cur_to_req
)
2051 if (next_to_req
> cur_to_req
)
2054 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
2055 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
2057 if (next_req_prod
> cur_req_prod
)
2060 if (next_req_prod
< cur_req_prod
)
2063 if (next
->stretch
> cur
->stretch
)
2065 if (next
->stretch
< cur
->stretch
)
2068 if (next
->style
> cur
->style
)
2070 if (next
->style
< cur
->style
)
2073 if (next
->weight
> cur
->weight
)
2075 if (next
->weight
< cur
->weight
)
2078 /* full match, no reason to prefer new variant */
2082 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
2083 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
2085 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2086 struct dwrite_font_propvec req
;
2089 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
2091 if (This
->data
->font_count
== 0) {
2093 return DWRITE_E_NOFONT
;
2096 init_font_prop_vec(weight
, stretch
, style
, &req
);
2099 for (i
= 1; i
< This
->data
->font_count
; i
++) {
2100 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &This
->data
->fonts
[match
]->propvec
, &req
))
2104 return create_font(This
, match
, (IDWriteFont3
**)font
);
2107 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
2109 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
2111 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2114 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
2116 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
2119 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
2121 UINT32 b
= fonts
->font_count
- 1, j
, t
;
2126 for (j
= 0; j
< b
; j
++) {
2127 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
2128 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
2129 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
2130 fonts
->fonts
[j
+1] = s
;
2141 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
2142 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
2144 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2145 matching_filter_func func
= NULL
;
2146 struct dwrite_font_propvec req
;
2147 struct dwrite_fontlist
*fonts
;
2150 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
2154 fonts
= heap_alloc(sizeof(*fonts
));
2156 return E_OUTOFMEMORY
;
2158 /* Allocate as many as family has, not all of them will be necessary used. */
2159 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
2160 if (!fonts
->fonts
) {
2162 return E_OUTOFMEMORY
;
2165 fonts
->IDWriteFontList1_iface
.lpVtbl
= &dwritefontlistvtbl
;
2167 fonts
->family
= This
;
2168 IDWriteFontFamily1_AddRef(&fonts
->family
->IDWriteFontFamily1_iface
);
2169 fonts
->font_count
= 0;
2171 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2172 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2173 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
2174 func
= is_font_acceptable_for_normal
;
2176 else /* requested oblique or italic */ {
2177 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
2178 func
= is_font_acceptable_for_oblique_italic
;
2181 for (i
= 0; i
< This
->data
->font_count
; i
++) {
2182 if (!func
|| func(This
->data
->fonts
[i
])) {
2183 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
2184 addref_font_data(This
->data
->fonts
[i
]);
2185 fonts
->font_count
++;
2189 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2190 init_font_prop_vec(weight
, stretch
, style
, &req
);
2191 matchingfonts_sort(fonts
, &req
);
2193 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList1_iface
;
2197 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
2199 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2201 FIXME("(%p)->(%u): stub\n", This
, index
);
2203 return DWRITE_LOCALITY_LOCAL
;
2206 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
2208 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2210 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
2214 if (This
->data
->font_count
== 0)
2217 if (index
>= This
->data
->font_count
)
2220 return create_font(This
, index
, font
);
2223 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
2224 IDWriteFontFaceReference
**reference
)
2226 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2230 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
2234 hr
= IDWriteFontFamily1_GetFont(iface
, index
, &font
);
2238 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2239 IDWriteFont3_Release(font
);
2244 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
2245 dwritefontfamily_QueryInterface
,
2246 dwritefontfamily_AddRef
,
2247 dwritefontfamily_Release
,
2248 dwritefontfamily_GetFontCollection
,
2249 dwritefontfamily_GetFontCount
,
2250 dwritefontfamily_GetFont
,
2251 dwritefontfamily_GetFamilyNames
,
2252 dwritefontfamily_GetFirstMatchingFont
,
2253 dwritefontfamily_GetMatchingFonts
,
2254 dwritefontfamily1_GetFontLocality
,
2255 dwritefontfamily1_GetFont
,
2256 dwritefontfamily1_GetFontFaceReference
2259 static HRESULT
create_fontfamily(struct dwrite_fontcollection
*collection
, UINT32 index
, IDWriteFontFamily1
**family
)
2261 struct dwrite_fontfamily
*This
;
2265 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
2266 if (!This
) return E_OUTOFMEMORY
;
2268 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
2270 This
->collection
= collection
;
2271 IDWriteFontCollection1_AddRef(&collection
->IDWriteFontCollection1_iface
);
2272 This
->data
= collection
->family_data
[index
];
2273 InterlockedIncrement(&This
->data
->ref
);
2275 *family
= &This
->IDWriteFontFamily1_iface
;
2280 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2283 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
2286 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2288 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2289 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2291 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2292 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2293 IsEqualIID(riid
, &IID_IUnknown
))
2296 IDWriteFontCollection1_AddRef(iface
);
2302 if (IsEqualIID(riid
, &IID_issystemcollection
))
2305 WARN("%s not implemented.\n", debugstr_guid(riid
));
2307 return E_NOINTERFACE
;
2310 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2312 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2313 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2315 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2316 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2317 IsEqualIID(riid
, &IID_IUnknown
))
2320 IDWriteFontCollection1_AddRef(iface
);
2324 WARN("%s not implemented.\n", debugstr_guid(riid
));
2328 return E_NOINTERFACE
;
2331 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2333 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2334 ULONG ref
= InterlockedIncrement(&This
->ref
);
2335 TRACE("(%p)->(%d)\n", This
, ref
);
2339 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2341 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2342 ULONG ref
= InterlockedDecrement(&This
->ref
);
2344 TRACE("(%p)->(%d)\n", This
, ref
);
2349 factory_detach_fontcollection(This
->factory
, iface
);
2350 for (i
= 0; i
< This
->family_count
; i
++)
2351 release_fontfamily_data(This
->family_data
[i
]);
2352 heap_free(This
->family_data
);
2359 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2361 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2362 TRACE("(%p)\n", This
);
2363 return This
->family_count
;
2366 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2368 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2370 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2372 if (index
>= This
->family_count
) {
2377 return create_fontfamily(This
, index
, (IDWriteFontFamily1
**)family
);
2380 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2384 for (i
= 0; i
< collection
->family_count
; i
++) {
2385 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2386 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2389 for (j
= 0; j
< count
; j
++) {
2391 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2392 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2400 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2402 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2403 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2404 *index
= collection_find_family(This
, name
);
2405 *exists
= *index
!= ~0u;
2409 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2411 UINT32 left_key_size
, right_key_size
;
2412 const void *left_key
, *right_key
;
2418 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2422 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2426 if (left_key_size
!= right_key_size
)
2429 return !memcmp(left_key
, right_key
, left_key_size
);
2432 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2434 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2435 IDWriteFontFamily1
*family
;
2436 UINT32 i
, j
, face_index
;
2437 BOOL found_font
= FALSE
;
2438 IDWriteFontFile
*file
;
2441 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2446 return E_INVALIDARG
;
2449 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2452 face_index
= IDWriteFontFace_GetIndex(face
);
2455 for (i
= 0; i
< This
->family_count
; i
++) {
2456 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2458 for (j
= 0; j
< family_data
->font_count
; j
++) {
2459 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2461 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2470 IDWriteFontFile_Release(file
);
2473 return DWRITE_E_NOFONT
;
2475 hr
= create_fontfamily(This
, i
, &family
);
2479 hr
= create_font(impl_from_IDWriteFontFamily1(family
), j
, (IDWriteFont3
**)font
);
2480 IDWriteFontFamily1_Release(family
);
2484 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2486 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2488 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2493 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2495 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2497 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2499 if (index
>= This
->family_count
) {
2504 return create_fontfamily(This
, index
, family
);
2507 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2508 dwritefontcollection_QueryInterface
,
2509 dwritefontcollection_AddRef
,
2510 dwritefontcollection_Release
,
2511 dwritefontcollection_GetFontFamilyCount
,
2512 dwritefontcollection_GetFontFamily
,
2513 dwritefontcollection_FindFamilyName
,
2514 dwritefontcollection_GetFontFromFontFace
,
2515 dwritefontcollection1_GetFontSet
,
2516 dwritefontcollection1_GetFontFamily
2519 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2520 dwritesystemfontcollection_QueryInterface
,
2521 dwritefontcollection_AddRef
,
2522 dwritefontcollection_Release
,
2523 dwritefontcollection_GetFontFamilyCount
,
2524 dwritefontcollection_GetFontFamily
,
2525 dwritefontcollection_FindFamilyName
,
2526 dwritefontcollection_GetFontFromFontFace
,
2527 dwritefontcollection1_GetFontSet
,
2528 dwritefontcollection1_GetFontFamily
2531 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2533 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2534 struct dwrite_font_data
**new_list
;
2537 new_alloc
= family_data
->font_alloc
* 2;
2538 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2540 return E_OUTOFMEMORY
;
2541 family_data
->fonts
= new_list
;
2542 family_data
->font_alloc
= new_alloc
;
2545 family_data
->fonts
[family_data
->font_count
] = font_data
;
2546 family_data
->font_count
++;
2547 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2548 family_data
->has_normal_face
= 1;
2549 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2550 family_data
->has_oblique_face
= 1;
2552 family_data
->has_italic_face
= 1;
2556 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2558 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2559 struct dwrite_fontfamily_data
**new_list
;
2562 new_alloc
= collection
->family_alloc
* 2;
2563 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2565 return E_OUTOFMEMORY
;
2567 collection
->family_alloc
= new_alloc
;
2568 collection
->family_data
= new_list
;
2571 collection
->family_data
[collection
->family_count
++] = family
;
2575 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2577 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2578 collection
->ref
= 1;
2579 collection
->family_count
= 0;
2580 collection
->family_alloc
= is_system
? 30 : 5;
2581 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2582 if (!collection
->family_data
)
2583 return E_OUTOFMEMORY
;
2588 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2590 IDWriteFontFileLoader
*loader
;
2597 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2601 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2605 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2606 IDWriteFontFileLoader_Release(loader
);
2613 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2615 BOOL exists
= FALSE
;
2620 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2621 if (FAILED(hr
) || !exists
)
2624 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2627 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2631 while (isspaceW(*in
))
2635 if (!(len
= strlenW(in
)))
2638 while (isspaceW(in
[len
-1]))
2641 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2650 INT len
; /* token length */
2651 INT fulllen
; /* full length including following separators */
2654 static inline BOOL
is_name_separator_char(WCHAR ch
)
2656 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2659 struct name_pattern
{
2660 const WCHAR
*part1
; /* NULL indicates end of list */
2661 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2664 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2666 const struct name_pattern
*pattern
;
2667 struct name_token
*token
;
2670 while ((pattern
= &patterns
[i
++])->part1
) {
2671 int len_part1
= strlenW(pattern
->part1
);
2672 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2674 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2675 if (len_part2
== 0) {
2676 /* simple case with single part pattern */
2677 if (token
->len
!= len_part1
)
2680 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2681 if (match
) *match
= *token
;
2682 list_remove(&token
->entry
);
2688 struct name_token
*next_token
;
2689 struct list
*next_entry
;
2691 /* pattern parts are stored in reading order, tokens list is reversed */
2692 if (token
->len
< len_part2
)
2695 /* it's possible to have combined string as a token, like ExtraCondensed */
2696 if (token
->len
== len_part1
+ len_part2
) {
2697 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2700 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2703 /* combined string match */
2704 if (match
) *match
= *token
;
2705 list_remove(&token
->entry
);
2710 /* now it's only possible to have two tokens matched to respective pattern parts */
2711 if (token
->len
!= len_part2
)
2714 next_entry
= list_next(tokens
, &token
->entry
);
2716 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2717 if (next_token
->len
!= len_part1
)
2720 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2723 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2726 /* both parts matched, remove tokens */
2728 match
->ptr
= next_token
->ptr
;
2729 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2731 list_remove(&token
->entry
);
2732 list_remove(&next_token
->entry
);
2733 heap_free(next_token
);
2748 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2750 static const WCHAR itaW
[] = {'i','t','a',0};
2751 static const WCHAR italW
[] = {'i','t','a','l',0};
2752 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2753 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2755 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2756 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2757 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2758 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2760 static const struct name_pattern italic_patterns
[] = {
2769 static const struct name_pattern oblique_patterns
[] = {
2778 /* italic patterns first */
2779 if (match_pattern_list(tokens
, italic_patterns
, match
))
2780 return DWRITE_FONT_STYLE_ITALIC
;
2782 /* oblique patterns */
2783 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2784 return DWRITE_FONT_STYLE_OBLIQUE
;
2789 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2790 struct name_token
*match
)
2792 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2793 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2794 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2795 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2796 static const WCHAR wideW
[] = {'w','i','d','e',0};
2797 static const WCHAR condW
[] = {'c','o','n','d',0};
2799 static const struct name_pattern ultracondensed_patterns
[] = {
2800 { extraW
, compressedW
},
2801 { extW
, compressedW
},
2802 { ultraW
, compressedW
},
2803 { ultraW
, condensedW
},
2808 static const struct name_pattern extracondensed_patterns
[] = {
2810 { extraW
, condensedW
},
2811 { extW
, condensedW
},
2817 static const struct name_pattern semicondensed_patterns
[] = {
2820 { semiW
, condensedW
},
2825 static const struct name_pattern semiexpanded_patterns
[] = {
2827 { semiW
, expandedW
},
2828 { semiW
, extendedW
},
2832 static const struct name_pattern extraexpanded_patterns
[] = {
2833 { extraW
, expandedW
},
2834 { extW
, expandedW
},
2835 { extraW
, extendedW
},
2836 { extW
, extendedW
},
2840 static const struct name_pattern ultraexpanded_patterns
[] = {
2841 { ultraW
, expandedW
},
2842 { ultraW
, extendedW
},
2846 static const struct name_pattern condensed_patterns
[] = {
2852 static const struct name_pattern expanded_patterns
[] = {
2858 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2859 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2861 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2862 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2864 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2865 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2867 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2868 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2870 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2871 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2873 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2874 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2876 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2877 return DWRITE_FONT_STRETCH_CONDENSED
;
2879 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2880 return DWRITE_FONT_STRETCH_EXPANDED
;
2885 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2886 struct name_token
*match
)
2888 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2889 static const WCHAR nordW
[] = {'n','o','r','d',0};
2891 static const struct name_pattern thin_patterns
[] = {
2898 static const struct name_pattern extralight_patterns
[] = {
2905 static const struct name_pattern semilight_patterns
[] = {
2910 static const struct name_pattern demibold_patterns
[] = {
2916 static const struct name_pattern extrabold_patterns
[] = {
2923 static const struct name_pattern extrablack_patterns
[] = {
2930 static const struct name_pattern bold_patterns
[] = {
2935 static const struct name_pattern thin2_patterns
[] = {
2940 static const struct name_pattern light_patterns
[] = {
2945 static const struct name_pattern medium_patterns
[] = {
2950 static const struct name_pattern black_patterns
[] = {
2957 static const struct name_pattern demibold2_patterns
[] = {
2962 static const struct name_pattern extrabold2_patterns
[] = {
2967 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2968 matching pattern. */
2970 if (match_pattern_list(tokens
, thin_patterns
, match
))
2971 return DWRITE_FONT_WEIGHT_THIN
;
2973 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2974 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2976 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2977 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2979 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2980 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2982 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2983 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2985 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2986 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2988 if (match_pattern_list(tokens
, bold_patterns
, match
))
2989 return DWRITE_FONT_WEIGHT_BOLD
;
2991 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2992 return DWRITE_FONT_WEIGHT_THIN
;
2994 if (match_pattern_list(tokens
, light_patterns
, match
))
2995 return DWRITE_FONT_WEIGHT_LIGHT
;
2997 if (match_pattern_list(tokens
, medium_patterns
, match
))
2998 return DWRITE_FONT_WEIGHT_MEDIUM
;
3000 if (match_pattern_list(tokens
, black_patterns
, match
))
3001 return DWRITE_FONT_WEIGHT_BLACK
;
3003 if (match_pattern_list(tokens
, black_patterns
, match
))
3004 return DWRITE_FONT_WEIGHT_BLACK
;
3006 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
3007 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
3009 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
3010 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
3012 /* FIXME: use abbreviated names to extract weight */
3017 struct knownweight_entry
{
3019 DWRITE_FONT_WEIGHT weight
;
3022 static int compare_knownweights(const void *a
, const void* b
)
3024 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
3025 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
3028 if (target
> entry
->weight
)
3030 else if (target
< entry
->weight
)
3036 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
3038 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
3039 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
3040 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
3041 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
3042 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
3043 const struct knownweight_entry
*ptr
;
3045 static const struct knownweight_entry knownweights
[] = {
3046 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
3047 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
3048 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
3049 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
3050 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
3051 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
3052 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
3053 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
3054 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
3055 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
3058 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
3059 compare_knownweights
);
3065 strcpyW(nameW
, ptr
->nameW
);
3069 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
3071 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
3072 strW
[name
->len
] = 0;
3075 /* Modifies facenameW string, and returns pointer to regular term that was removed */
3076 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
3078 static const WCHAR bookW
[] = {'B','o','o','k',0};
3079 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
3080 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
3081 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
3082 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
3084 static const WCHAR
*regular_patterns
[] = {
3093 const WCHAR
*regular_ptr
= NULL
, *ptr
;
3097 len
= strlenW(facenameW
);
3099 /* remove rightmost regular variant from face name */
3100 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
3101 int pattern_len
= strlenW(ptr
);
3104 if (pattern_len
> len
)
3107 src
= facenameW
+ len
- pattern_len
;
3108 while (src
>= facenameW
) {
3109 if (!strncmpiW(src
, ptr
, pattern_len
)) {
3110 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
3111 len
= strlenW(facenameW
);
3123 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
3131 struct name_token
*token
= heap_alloc(sizeof(*token
));
3136 while (*ptr
&& !is_name_separator_char(*ptr
)) {
3142 /* skip separators */
3143 while (is_name_separator_char(*ptr
)) {
3148 list_add_head(tokens
, &token
->entry
);
3152 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
3154 struct name_token
*token
, *token2
;
3155 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
3158 list_remove(&token
->entry
);
3160 /* don't include last separator */
3161 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
3162 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3170 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3172 struct name_token stretch_name
, weight_name
, style_name
;
3173 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3174 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3175 const WCHAR
*regular_ptr
= NULL
;
3176 DWRITE_FONT_STRETCH stretch
;
3177 DWRITE_FONT_WEIGHT weight
;
3181 /* remove leading and trailing spaces from family and face name */
3182 trim_spaces(familyW
, familynameW
);
3183 len
= trim_spaces(faceW
, facenameW
);
3185 /* remove rightmost regular variant from face name */
3186 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3188 /* append face name to family name, FIXME check if face name is a substring of family name */
3190 strcatW(familynameW
, spaceW
);
3191 strcatW(familynameW
, facenameW
);
3194 /* tokenize with " .-_" */
3195 fontname_tokenize(&tokens
, familynameW
);
3197 /* extract and resolve style */
3198 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3200 /* extract stretch */
3201 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3203 /* extract weight */
3204 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3206 /* resolve weight */
3207 if (weight
!= font
->weight
) {
3208 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3209 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3210 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3211 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3212 !(abs(weight
- font
->weight
) <= 150 &&
3213 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3214 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3215 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3217 font
->weight
= weight
;
3221 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3222 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3223 stretch itself is normal (extracted stretch is never normal). */
3224 if (stretch
!= font
->stretch
) {
3225 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3226 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3227 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3229 font
->stretch
= stretch
;
3233 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3235 /* get final combined string from what's left in token list, list is released */
3236 fontname_tokens_to_str(&tokens
, finalW
);
3238 if (!strcmpW(familyW
, finalW
))
3241 /* construct face name */
3242 strcpyW(familyW
, finalW
);
3244 /* resolved weight name */
3245 if (weight_name
.ptr
)
3246 font_name_token_to_str(&weight_name
, weightW
);
3247 /* ignore normal weight */
3248 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3250 /* for known weight values use appropriate names */
3251 else if (is_known_weight_value(font
->weight
, weightW
)) {
3253 /* use Wnnn format as a fallback in case weight is not one of known values */
3255 static const WCHAR fmtW
[] = {'W','%','d',0};
3256 sprintfW(weightW
, fmtW
, font
->weight
);
3259 /* resolved stretch name */
3260 if (stretch_name
.ptr
)
3261 font_name_token_to_str(&stretch_name
, stretchW
);
3262 /* ignore normal stretch */
3263 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3265 /* use predefined stretch names */
3267 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3268 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3269 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3270 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3271 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3272 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3274 static const WCHAR
*stretchnamesW
[] = {
3275 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3280 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3286 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3289 /* resolved style name */
3291 font_name_token_to_str(&style_name
, styleW
);
3292 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3294 /* use predefined names */
3296 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3297 strcpyW(styleW
, italicW
);
3299 strcpyW(styleW
, obliqueW
);
3302 /* use Regular match if it was found initially */
3303 if (!*weightW
&& !*stretchW
&& !*styleW
)
3304 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3308 strcpyW(faceW
, stretchW
);
3311 strcatW(faceW
, spaceW
);
3312 strcatW(faceW
, weightW
);
3316 strcatW(faceW
, spaceW
);
3317 strcatW(faceW
, styleW
);
3321 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3325 static HRESULT
init_font_data(const struct fontface_desc
*desc
, IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
3327 struct file_stream_desc stream_desc
;
3328 struct dwrite_font_props props
;
3329 struct dwrite_font_data
*data
;
3330 IDWriteFontFileStream
*stream
;
3331 WCHAR familyW
[255], faceW
[255];
3335 data
= heap_alloc_zero(sizeof(*data
));
3337 return E_OUTOFMEMORY
;
3339 hr
= get_filestream_from_file(desc
->files
[0], &stream
);
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
= 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
);
3363 IDWriteFontFileStream_Release(stream
);
3365 WARN("unable to get family name from font\n");
3366 release_font_data(data
);
3370 data
->style
= props
.style
;
3371 data
->stretch
= props
.stretch
;
3372 data
->weight
= props
.weight
;
3373 data
->panose
= props
.panose
;
3374 data
->fontsig
= props
.fontsig
;
3375 data
->lf
= props
.lf
;
3377 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3378 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3379 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3380 set_en_localizedstring(*family_name
, familyW
);
3381 set_en_localizedstring(data
->names
, faceW
);
3384 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3390 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
,
3391 const WCHAR
*facenameW
, struct dwrite_font_data
**ret
)
3393 struct dwrite_font_data
*data
;
3397 data
= heap_alloc_zero(sizeof(*data
));
3399 return E_OUTOFMEMORY
;
3403 data
->simulations
|= sim
;
3404 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3405 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3406 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3407 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3408 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3410 IDWriteFontFile_AddRef(data
->file
);
3412 create_localizedstrings(&data
->names
);
3413 add_localizedstring(data
->names
, enusW
, facenameW
);
3415 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3421 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3423 struct dwrite_fontfamily_data
*data
;
3425 data
= heap_alloc(sizeof(*data
));
3427 return E_OUTOFMEMORY
;
3430 data
->font_count
= 0;
3431 data
->font_alloc
= 2;
3432 data
->has_normal_face
= 0;
3433 data
->has_oblique_face
= 0;
3434 data
->has_italic_face
= 0;
3436 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3439 return E_OUTOFMEMORY
;
3442 data
->familyname
= familyname
;
3443 IDWriteLocalizedStrings_AddRef(familyname
);
3449 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3451 UINT32 i
, j
, heaviest
;
3453 for (i
= 0; i
< family
->font_count
; i
++) {
3454 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3457 if (family
->fonts
[i
]->bold_sim_tested
)
3460 family
->fonts
[i
]->bold_sim_tested
= 1;
3461 for (j
= i
; j
< family
->font_count
; j
++) {
3462 if (family
->fonts
[j
]->bold_sim_tested
)
3465 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3466 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3467 if (family
->fonts
[j
]->weight
> weight
) {
3468 weight
= family
->fonts
[j
]->weight
;
3471 family
->fonts
[j
]->bold_sim_tested
= 1;
3475 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3476 static const struct name_pattern weightsim_patterns
[] = {
3491 WCHAR facenameW
[255], initialW
[255];
3492 struct dwrite_font_data
*boldface
;
3495 /* add Bold simulation based on heaviest face data */
3497 /* Simulated face name should only contain Bold as weight term,
3498 so remove existing regular and weight terms. */
3499 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3500 facename_remove_regular_term(initialW
, -1);
3502 /* remove current weight pattern */
3503 fontname_tokenize(&tokens
, initialW
);
3504 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3505 fontname_tokens_to_str(&tokens
, facenameW
);
3507 /* Bold suffix for new name */
3509 strcatW(facenameW
, spaceW
);
3510 strcatW(facenameW
, boldW
);
3512 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3513 boldface
->bold_sim_tested
= 1;
3514 boldface
->lf
.lfWeight
+= (FW_BOLD
- FW_REGULAR
) / 2 + 1;
3515 fontfamily_add_font(family
, boldface
);
3521 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3525 for (i
= 0; i
< family
->font_count
; i
++) {
3526 UINT32 regular
= ~0u, oblique
= ~0u;
3527 struct dwrite_font_data
*obliqueface
;
3528 WCHAR facenameW
[255];
3530 if (family
->fonts
[i
]->oblique_sim_tested
)
3533 family
->fonts
[i
]->oblique_sim_tested
= 1;
3534 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3536 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3539 /* find regular style with same weight/stretch values */
3540 for (j
= i
; j
< family
->font_count
; j
++) {
3541 if (family
->fonts
[j
]->oblique_sim_tested
)
3544 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3545 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3547 family
->fonts
[j
]->oblique_sim_tested
= 1;
3548 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3551 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3555 if (regular
!= ~0u && oblique
!= ~0u)
3559 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3563 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3567 /* add oblique simulation based on this regular face */
3569 /* remove regular term if any, append 'Oblique' */
3570 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3571 facename_remove_regular_term(facenameW
, -1);
3574 strcatW(facenameW
, spaceW
);
3575 strcatW(facenameW
, obliqueW
);
3577 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3578 obliqueface
->oblique_sim_tested
= 1;
3579 obliqueface
->lf
.lfItalic
= 1;
3580 fontfamily_add_font(family
, obliqueface
);
3585 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3586 const WCHAR
*replacement_name
)
3588 UINT32 i
= collection_find_family(collection
, replacement_name
);
3589 struct dwrite_fontfamily_data
*target
;
3590 IDWriteLocalizedStrings
*strings
;
3593 /* replacement does not exist */
3597 hr
= create_localizedstrings(&strings
);
3601 /* add a new family with target name, reuse font data from replacement */
3602 add_localizedstring(strings
, enusW
, target_name
);
3603 hr
= init_fontfamily_data(strings
, &target
);
3605 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3608 for (i
= 0; i
< replacement
->font_count
; i
++) {
3609 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3610 addref_font_data(replacement
->fonts
[i
]);
3613 fontcollection_add_family(collection
, target
);
3614 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3615 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3617 IDWriteLocalizedStrings_Release(strings
);
3621 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3622 system font collections. */
3623 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3625 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3630 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3633 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3638 max_namelen
++; /* returned value doesn't include room for '\0' */
3639 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3640 data
= heap_alloc(max_datalen
);
3642 datalen
= max_datalen
;
3643 namelen
= max_namelen
;
3644 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3645 if (collection_find_family(collection
, name
) == ~0u) {
3646 if (type
== REG_MULTI_SZ
) {
3647 WCHAR
*replacement
= data
;
3648 while (*replacement
) {
3649 if (fontcollection_add_replacement(collection
, name
, replacement
))
3651 replacement
+= strlenW(replacement
) + 1;
3654 else if (type
== REG_SZ
)
3655 fontcollection_add_replacement(collection
, name
, data
);
3658 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3660 datalen
= max_datalen
;
3661 namelen
= max_namelen
;
3669 HRESULT
create_font_collection(IDWriteFactory5
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
3670 IDWriteFontCollection1
**ret
)
3672 struct fontfile_enum
{
3674 IDWriteFontFile
*file
;
3676 struct fontfile_enum
*fileenum
, *fileenum2
;
3677 struct dwrite_fontcollection
*collection
;
3678 struct list scannedfiles
;
3679 BOOL current
= FALSE
;
3685 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3686 if (!collection
) return E_OUTOFMEMORY
;
3688 hr
= init_font_collection(collection
, is_system
);
3690 heap_free(collection
);
3694 *ret
= &collection
->IDWriteFontCollection1_iface
;
3696 TRACE("building font collection:\n");
3698 list_init(&scannedfiles
);
3699 while (hr
== S_OK
) {
3700 DWRITE_FONT_FACE_TYPE face_type
;
3701 DWRITE_FONT_FILE_TYPE file_type
;
3702 BOOL supported
, same
= FALSE
;
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 /* failed font files are skipped */
3727 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3728 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3729 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3730 IDWriteFontFile_Release(file
);
3735 /* add to scanned list */
3736 fileenum
= heap_alloc(sizeof(*fileenum
));
3737 fileenum
->file
= file
;
3738 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3740 for (i
= 0; i
< face_count
; i
++) {
3741 IDWriteLocalizedStrings
*family_name
= NULL
;
3742 struct dwrite_font_data
*font_data
;
3743 struct fontface_desc desc
;
3747 desc
.factory
= factory
;
3748 desc
.face_type
= face_type
;
3750 desc
.files_number
= 1;
3752 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3753 desc
.font_data
= NULL
;
3755 /* alloc and init new font data structure */
3756 hr
= init_font_data(&desc
, &family_name
, &font_data
);
3758 /* move to next one */
3763 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3765 /* ignore dot named faces */
3766 if (familyW
[0] == '.') {
3767 WARN("Ignoring face %s\n", debugstr_w(familyW
));
3768 IDWriteLocalizedStrings_Release(family_name
);
3769 release_font_data(font_data
);
3773 index
= collection_find_family(collection
, familyW
);
3775 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3777 struct dwrite_fontfamily_data
*family_data
;
3779 /* create and init new family */
3780 hr
= init_fontfamily_data(family_name
, &family_data
);
3782 /* add font to family, family - to collection */
3783 hr
= fontfamily_add_font(family_data
, font_data
);
3785 hr
= fontcollection_add_family(collection
, family_data
);
3788 release_fontfamily_data(family_data
);
3792 IDWriteLocalizedStrings_Release(family_name
);
3799 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3800 IDWriteFontFile_Release(fileenum
->file
);
3801 list_remove(&fileenum
->entry
);
3802 heap_free(fileenum
);
3805 for (i
= 0; i
< collection
->family_count
; i
++) {
3806 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3807 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3811 fontcollection_add_replacements(collection
);
3813 collection
->factory
= factory
;
3814 IDWriteFactory5_AddRef(factory
);
3819 struct system_fontfile_enumerator
3821 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3824 IDWriteFactory5
*factory
;
3829 DWORD max_val_count
;
3832 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3834 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3837 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3839 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3840 IDWriteFontFileEnumerator_AddRef(iface
);
3845 WARN("%s not implemented.\n", debugstr_guid(riid
));
3849 return E_NOINTERFACE
;
3852 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3854 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3855 return InterlockedIncrement(&enumerator
->ref
);
3858 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3860 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3861 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3864 IDWriteFactory5_Release(enumerator
->factory
);
3865 RegCloseKey(enumerator
->hkey
);
3866 heap_free(enumerator
->value
);
3867 heap_free(enumerator
);
3873 static HRESULT
create_local_file_reference(IDWriteFactory5
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3877 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3878 if (!strchrW(filename
, '\\')) {
3879 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3880 WCHAR fullpathW
[MAX_PATH
];
3882 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3883 strcatW(fullpathW
, fontsW
);
3884 strcatW(fullpathW
, filename
);
3886 hr
= IDWriteFactory5_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3889 hr
= IDWriteFactory5_CreateFontFileReference(factory
, filename
, NULL
, file
);
3894 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3896 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3897 DWORD ret
, type
, val_count
, count
;
3898 WCHAR
*value
, *filename
;
3903 if (enumerator
->index
< 0)
3906 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3907 if (ret
!= ERROR_SUCCESS
)
3911 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3912 filename
= heap_alloc(count
);
3913 if (!value
|| !filename
) {
3915 heap_free(filename
);
3916 return E_OUTOFMEMORY
;
3919 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3922 heap_free(filename
);
3926 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3929 heap_free(filename
);
3933 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3935 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3938 enumerator
->index
++;
3940 if (!enumerator
->value
) {
3941 if (RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
3942 &enumerator
->max_val_count
, NULL
, NULL
, NULL
))
3945 enumerator
->max_val_count
++;
3946 if (!(enumerator
->value
= heap_alloc(enumerator
->max_val_count
* sizeof(*enumerator
->value
))))
3947 return E_OUTOFMEMORY
;
3950 /* iterate until we find next string value */
3952 DWORD type
= 0, count
, val_count
;
3954 val_count
= enumerator
->max_val_count
;
3955 *enumerator
->value
= 0;
3956 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, enumerator
->value
, &val_count
,
3957 NULL
, &type
, NULL
, &count
))
3959 if (type
== REG_SZ
&& *enumerator
->value
&& *enumerator
->value
!= '@') {
3963 enumerator
->index
++;
3966 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3970 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3972 systemfontfileenumerator_QueryInterface
,
3973 systemfontfileenumerator_AddRef
,
3974 systemfontfileenumerator_Release
,
3975 systemfontfileenumerator_MoveNext
,
3976 systemfontfileenumerator_GetCurrentFontFile
3979 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory5
*factory
, IDWriteFontFileEnumerator
**ret
)
3981 struct system_fontfile_enumerator
*enumerator
;
3982 static const WCHAR fontslistW
[] = {
3983 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3984 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3985 'F','o','n','t','s',0
3990 enumerator
= heap_alloc(sizeof(*enumerator
));
3992 return E_OUTOFMEMORY
;
3994 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3995 enumerator
->ref
= 1;
3996 enumerator
->factory
= factory
;
3997 enumerator
->index
= -1;
3998 enumerator
->value
= NULL
;
3999 enumerator
->max_val_count
= 0;
4000 IDWriteFactory5_AddRef(factory
);
4002 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
4003 ERR("failed to open fonts list key\n");
4004 IDWriteFactory5_Release(factory
);
4005 heap_free(enumerator
);
4009 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
4014 HRESULT
get_system_fontcollection(IDWriteFactory5
*factory
, IDWriteFontCollection1
**collection
)
4016 IDWriteFontFileEnumerator
*enumerator
;
4021 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
4025 TRACE("building system font collection for factory %p\n", factory
);
4026 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
4027 IDWriteFontFileEnumerator_Release(enumerator
);
4031 static HRESULT
eudc_collection_add_family(IDWriteFactory5
*factory
, struct dwrite_fontcollection
*collection
,
4032 const WCHAR
*keynameW
, const WCHAR
*pathW
)
4034 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};
4035 static const WCHAR emptyW
[] = {0};
4036 IDWriteLocalizedStrings
*names
;
4037 DWRITE_FONT_FACE_TYPE face_type
;
4038 DWRITE_FONT_FILE_TYPE file_type
;
4040 UINT32 face_count
, i
;
4041 IDWriteFontFile
*file
;
4043 struct dwrite_fontfamily_data
*family_data
;
4045 /* create font file from this path */
4046 hr
= create_local_file_reference(factory
, pathW
, &file
);
4050 /* failed font files are skipped */
4051 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
4052 if (FAILED(hr
) || !supported
|| face_count
== 0) {
4053 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
4054 IDWriteFontFile_Release(file
);
4058 /* create and init new family */
4060 /* Family names are added for non-specific locale, represented with empty string.
4061 Default family appears with empty family name. */
4062 create_localizedstrings(&names
);
4063 if (!strcmpiW(keynameW
, defaultfontW
))
4064 add_localizedstring(names
, emptyW
, emptyW
);
4066 add_localizedstring(names
, emptyW
, keynameW
);
4068 hr
= init_fontfamily_data(names
, &family_data
);
4069 IDWriteLocalizedStrings_Release(names
);
4071 IDWriteFontFile_Release(file
);
4075 /* fill with faces */
4076 for (i
= 0; i
< face_count
; i
++) {
4077 struct dwrite_font_data
*font_data
;
4078 struct fontface_desc desc
;
4080 /* alloc and init new font data structure */
4081 desc
.factory
= factory
;
4082 desc
.face_type
= face_type
;
4085 desc
.files_number
= 1;
4086 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
4087 desc
.font_data
= NULL
;
4089 hr
= init_font_data(&desc
, &names
, &font_data
);
4093 IDWriteLocalizedStrings_Release(names
);
4095 /* add font to family */
4096 hr
= fontfamily_add_font(family_data
, font_data
);
4098 release_font_data(font_data
);
4101 /* add family to collection */
4102 hr
= fontcollection_add_family(collection
, family_data
);
4104 release_fontfamily_data(family_data
);
4105 IDWriteFontFile_Release(file
);
4110 HRESULT
get_eudc_fontcollection(IDWriteFactory5
*factory
, IDWriteFontCollection1
**ret
)
4112 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
4113 struct dwrite_fontcollection
*collection
;
4114 static const WCHAR emptyW
[] = {0};
4115 WCHAR eudckeypathW
[16];
4123 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
4127 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
4128 if (!collection
) return E_OUTOFMEMORY
;
4130 hr
= init_font_collection(collection
, FALSE
);
4132 heap_free(collection
);
4136 *ret
= &collection
->IDWriteFontCollection1_iface
;
4137 collection
->factory
= factory
;
4138 IDWriteFactory5_AddRef(factory
);
4140 /* return empty collection if EUDC fonts are not configured */
4141 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
4142 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
4145 retval
= ERROR_SUCCESS
;
4147 while (retval
!= ERROR_NO_MORE_ITEMS
) {
4148 WCHAR keynameW
[64], pathW
[MAX_PATH
];
4149 DWORD type
, path_len
, name_len
;
4151 path_len
= sizeof(pathW
)/sizeof(*pathW
);
4152 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
4153 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
4154 if (retval
|| type
!= REG_SZ
)
4157 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
4159 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
4161 RegCloseKey(eudckey
);
4163 /* try to add global default if not defined for specific codepage */
4165 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
4167 if (FAILED(hr
) || !exists
) {
4168 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
4169 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
4171 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
4174 /* EUDC collection offers simulated faces too */
4175 for (i
= 0; i
< collection
->family_count
; i
++) {
4176 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
4177 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4183 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4185 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4187 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4189 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4192 IDWriteFontFile_AddRef(iface
);
4196 WARN("%s not implemented.\n", debugstr_guid(riid
));
4199 return E_NOINTERFACE
;
4202 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4204 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4205 ULONG ref
= InterlockedIncrement(&This
->ref
);
4206 TRACE("(%p)->(%d)\n", This
, ref
);
4210 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4212 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4213 ULONG ref
= InterlockedDecrement(&This
->ref
);
4215 TRACE("(%p)->(%d)\n", This
, ref
);
4219 IDWriteFontFileLoader_Release(This
->loader
);
4220 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4221 heap_free(This
->reference_key
);
4228 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4230 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4231 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4232 *fontFileReferenceKey
= This
->reference_key
;
4233 *fontFileReferenceKeySize
= This
->key_size
;
4238 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4240 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4241 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4242 *fontFileLoader
= This
->loader
;
4243 IDWriteFontFileLoader_AddRef(This
->loader
);
4248 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
4249 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
4251 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4252 IDWriteFontFileStream
*stream
;
4255 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
4257 *isSupportedFontType
= FALSE
;
4258 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4260 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4263 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4267 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
4269 /* TODO: Further Analysis */
4270 IDWriteFontFileStream_Release(stream
);
4274 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4275 dwritefontfile_QueryInterface
,
4276 dwritefontfile_AddRef
,
4277 dwritefontfile_Release
,
4278 dwritefontfile_GetReferenceKey
,
4279 dwritefontfile_GetLoader
,
4280 dwritefontfile_Analyze
,
4283 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
,
4284 IDWriteFontFile
**ret
)
4286 struct dwrite_fontfile
*file
;
4291 file
= heap_alloc(sizeof(*file
));
4292 key
= heap_alloc(key_size
);
4293 if (!file
|| !key
) {
4296 return E_OUTOFMEMORY
;
4299 file
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4301 IDWriteFontFileLoader_AddRef(loader
);
4302 file
->loader
= loader
;
4303 file
->stream
= NULL
;
4304 file
->reference_key
= key
;
4305 memcpy(file
->reference_key
, reference_key
, key_size
);
4306 file
->key_size
= key_size
;
4308 *ret
= &file
->IDWriteFontFile_iface
;
4313 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
4315 IDWriteFontFileLoader
*loader
;
4321 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4325 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
4327 IDWriteFontFileLoader_Release(loader
);
4331 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
4332 IDWriteFontFileLoader_Release(loader
);
4337 HRESULT
create_fontface(const struct fontface_desc
*desc
, struct list
*cached_list
, IDWriteFontFace4
**ret
)
4339 struct file_stream_desc stream_desc
;
4340 struct dwrite_fontface
*fontface
;
4347 fontface
= heap_alloc_zero(sizeof(struct dwrite_fontface
));
4349 return E_OUTOFMEMORY
;
4351 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4352 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * desc
->files_number
);
4354 if (!fontface
->files
|| !fontface
->streams
) {
4355 heap_free(fontface
->files
);
4356 heap_free(fontface
->streams
);
4357 heap_free(fontface
);
4358 return E_OUTOFMEMORY
;
4361 fontface
->IDWriteFontFace4_iface
.lpVtbl
= &dwritefontfacevtbl
;
4363 fontface
->type
= desc
->face_type
;
4364 fontface
->file_count
= desc
->files_number
;
4365 fontface
->cmap
.exists
= TRUE
;
4366 fontface
->vdmx
.exists
= TRUE
;
4367 fontface
->gasp
.exists
= TRUE
;
4368 fontface
->cpal
.exists
= TRUE
;
4369 fontface
->colr
.exists
= TRUE
;
4370 fontface
->index
= desc
->index
;
4371 fontface
->simulations
= desc
->simulations
;
4372 IDWriteFactory5_AddRef(fontface
->factory
= desc
->factory
);
4374 for (i
= 0; i
< fontface
->file_count
; i
++) {
4375 hr
= get_stream_from_file(desc
->files
[i
], &fontface
->streams
[i
]);
4377 IDWriteFontFace4_Release(&fontface
->IDWriteFontFace4_iface
);
4381 fontface
->files
[i
] = desc
->files
[i
];
4382 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4385 stream_desc
.stream
= fontface
->streams
[0];
4386 stream_desc
.face_type
= desc
->face_type
;
4387 stream_desc
.face_index
= desc
->index
;
4388 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4389 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4390 /* TODO: test what happens if caret is already slanted */
4391 if (fontface
->caret
.slopeRise
== 1) {
4392 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4393 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4397 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace4_iface
, &is_symbol
);
4399 fontface
->flags
|= FONTFACE_IS_SYMBOL
;
4400 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace4_iface
))
4401 fontface
->flags
|= FONTFACE_HAS_KERNING_PAIRS
;
4402 if (freetype_is_monospaced(&fontface
->IDWriteFontFace4_iface
))
4403 fontface
->flags
|= FONTFACE_IS_MONOSPACED
;
4404 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace4_iface
))
4405 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4406 fontface
->glyph_image_formats
= opentype_get_glyph_image_formats(&fontface
->IDWriteFontFace4_iface
);
4408 /* Font properties are reused from font object when 'normal' face creation path is used:
4409 collection -> family -> matching font -> fontface.
4411 If face is created directly from factory we have to go through properties resolution.
4413 if (desc
->font_data
) {
4414 fontface
->weight
= desc
->font_data
->weight
;
4415 fontface
->style
= desc
->font_data
->style
;
4416 fontface
->stretch
= desc
->font_data
->stretch
;
4417 fontface
->panose
= desc
->font_data
->panose
;
4418 fontface
->fontsig
= desc
->font_data
->fontsig
;
4419 fontface
->lf
= desc
->font_data
->lf
;
4422 IDWriteLocalizedStrings
*names
;
4423 struct dwrite_font_data
*data
;
4425 hr
= init_font_data(desc
, &names
, &data
);
4427 IDWriteFontFace4_Release(&fontface
->IDWriteFontFace4_iface
);
4431 fontface
->weight
= data
->weight
;
4432 fontface
->style
= data
->style
;
4433 fontface
->stretch
= data
->stretch
;
4434 fontface
->panose
= data
->panose
;
4435 fontface
->fontsig
= data
->fontsig
;
4436 fontface
->lf
= data
->lf
;
4438 IDWriteLocalizedStrings_Release(names
);
4439 release_font_data(data
);
4442 fontface
->cached
= factory_cache_fontface(fontface
->factory
, cached_list
, &fontface
->IDWriteFontFace4_iface
);
4444 *ret
= &fontface
->IDWriteFontFace4_iface
;
4448 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4455 struct local_cached_stream
4458 IDWriteFontFileStream
*stream
;
4459 struct local_refkey
*key
;
4463 struct dwrite_localfontfilestream
4465 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4468 struct local_cached_stream
*entry
;
4469 const void *file_ptr
;
4473 struct dwrite_localfontfileloader
{
4474 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4477 struct list streams
;
4478 CRITICAL_SECTION cs
;
4481 static struct dwrite_localfontfileloader local_fontfile_loader
;
4483 struct dwrite_inmemory_stream_data
4491 struct dwrite_inmemory_filestream
4493 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4496 struct dwrite_inmemory_stream_data
*data
;
4499 struct dwrite_inmemory_fileloader
4501 IDWriteInMemoryFontFileLoader IDWriteInMemoryFontFileLoader_iface
;
4504 struct dwrite_inmemory_stream_data
**streams
;
4509 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4511 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4514 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4516 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4519 static inline struct dwrite_inmemory_fileloader
*impl_from_IDWriteInMemoryFontFileLoader(IDWriteInMemoryFontFileLoader
*iface
)
4521 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_fileloader
, IDWriteInMemoryFontFileLoader_iface
);
4524 static inline struct dwrite_inmemory_filestream
*inmemory_impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4526 return CONTAINING_RECORD(iface
, struct dwrite_inmemory_filestream
, IDWriteFontFileStream_iface
);
4529 static void release_inmemory_stream(struct dwrite_inmemory_stream_data
*stream
)
4531 if (InterlockedDecrement(&stream
->ref
) == 0) {
4533 IUnknown_Release(stream
->owner
);
4535 heap_free(stream
->data
);
4540 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4542 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4544 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4546 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) ||
4547 IsEqualIID(riid
, &IID_IUnknown
))
4550 if (InterlockedIncrement(&This
->ref
) == 1) {
4551 InterlockedDecrement(&This
->ref
);
4558 WARN("%s not implemented.\n", debugstr_guid(riid
));
4561 return E_NOINTERFACE
;
4564 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4566 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4567 ULONG ref
= InterlockedIncrement(&This
->ref
);
4568 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4572 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4574 list_remove(&stream
->entry
);
4575 heap_free(stream
->key
);
4579 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4581 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4582 ULONG ref
= InterlockedDecrement(&This
->ref
);
4584 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4587 UnmapViewOfFile(This
->file_ptr
);
4589 EnterCriticalSection(&local_fontfile_loader
.cs
);
4590 release_cached_stream(This
->entry
);
4591 LeaveCriticalSection(&local_fontfile_loader
.cs
);
4599 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
4600 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4602 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4604 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", This
, fragment_start
,
4605 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4607 *fragment_context
= NULL
;
4609 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4610 *fragment_start
= NULL
;
4614 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4618 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4620 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4621 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4624 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4626 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4627 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4632 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4634 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4637 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4639 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4640 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4641 *last_writetime
= li
.QuadPart
;
4646 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4648 localfontfilestream_QueryInterface
,
4649 localfontfilestream_AddRef
,
4650 localfontfilestream_Release
,
4651 localfontfilestream_ReadFileFragment
,
4652 localfontfilestream_ReleaseFileFragment
,
4653 localfontfilestream_GetFileSize
,
4654 localfontfilestream_GetLastWriteTime
4657 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4659 struct dwrite_localfontfilestream
*This
;
4663 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4665 return E_OUTOFMEMORY
;
4667 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4670 This
->file_ptr
= file_ptr
;
4672 This
->entry
= entry
;
4674 *ret
= &This
->IDWriteFontFileStream_iface
;
4678 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4680 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4682 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4684 if (IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
) ||
4685 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
4686 IsEqualIID(riid
, &IID_IUnknown
))
4689 IDWriteLocalFontFileLoader_AddRef(iface
);
4693 WARN("%s not implemented.\n", debugstr_guid(riid
));
4696 return E_NOINTERFACE
;
4699 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4701 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4702 ULONG ref
= InterlockedIncrement(&This
->ref
);
4703 TRACE("(%p)->(%d)\n", This
, ref
);
4707 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4709 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4710 ULONG ref
= InterlockedDecrement(&This
->ref
);
4712 TRACE("(%p)->(%d)\n", This
, ref
);
4717 static HRESULT
create_local_cached_stream(const void *key
, UINT32 key_size
, struct local_cached_stream
**ret
)
4719 const struct local_refkey
*refkey
= key
;
4720 struct local_cached_stream
*stream
;
4721 IDWriteFontFileStream
*filestream
;
4722 HANDLE file
, mapping
;
4729 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4730 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4731 if (file
== INVALID_HANDLE_VALUE
) {
4732 WARN_(dwrite_file
)("Failed to open the file %s, error %d.\n", debugstr_w(refkey
->name
), GetLastError());
4736 GetFileSizeEx(file
, &size
);
4737 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4742 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4743 CloseHandle(mapping
);
4745 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
4749 stream
= heap_alloc(sizeof(*stream
));
4751 UnmapViewOfFile(file_ptr
);
4752 return E_OUTOFMEMORY
;
4755 stream
->key
= heap_alloc(key_size
);
4757 UnmapViewOfFile(file_ptr
);
4759 return E_OUTOFMEMORY
;
4762 stream
->key_size
= key_size
;
4763 memcpy(stream
->key
, key
, key_size
);
4765 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4767 UnmapViewOfFile(file_ptr
);
4768 heap_free(stream
->key
);
4773 stream
->stream
= filestream
;
4780 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
,
4781 UINT32 key_size
, IDWriteFontFileStream
**ret
)
4783 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4784 const struct local_refkey
*refkey
= key
;
4785 struct local_cached_stream
*stream
;
4788 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, ret
);
4789 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4791 EnterCriticalSection(&This
->cs
);
4795 /* search cache first */
4796 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4797 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4798 IDWriteFontFileStream_QueryInterface(stream
->stream
, &IID_IDWriteFontFileStream
, (void **)ret
);
4803 if (*ret
== NULL
&& (hr
= create_local_cached_stream(key
, key_size
, &stream
)) == S_OK
) {
4804 list_add_head(&This
->streams
, &stream
->entry
);
4805 *ret
= stream
->stream
;
4808 LeaveCriticalSection(&This
->cs
);
4813 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4815 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4816 const struct local_refkey
*refkey
= key
;
4818 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4820 *length
= strlenW(refkey
->name
);
4824 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4826 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4827 const struct local_refkey
*refkey
= key
;
4829 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4831 if (length
< strlenW(refkey
->name
))
4832 return E_INVALIDARG
;
4834 strcpyW(path
, refkey
->name
);
4838 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
,
4839 UINT32 key_size
, FILETIME
*writetime
)
4841 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4842 const struct local_refkey
*refkey
= key
;
4844 TRACE("(%p)->(%p, %u, %p)\n", This
, key
, key_size
, writetime
);
4846 *writetime
= refkey
->writetime
;
4850 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4851 localfontfileloader_QueryInterface
,
4852 localfontfileloader_AddRef
,
4853 localfontfileloader_Release
,
4854 localfontfileloader_CreateStreamFromKey
,
4855 localfontfileloader_GetFilePathLengthFromKey
,
4856 localfontfileloader_GetFilePathFromKey
,
4857 localfontfileloader_GetLastWriteTimeFromKey
4860 void init_local_fontfile_loader(void)
4862 local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4863 local_fontfile_loader
.ref
= 1;
4864 list_init(&local_fontfile_loader
.streams
);
4865 InitializeCriticalSection(&local_fontfile_loader
.cs
);
4866 local_fontfile_loader
.cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": localfileloader.lock");
4869 IDWriteFontFileLoader
*get_local_fontfile_loader(void)
4871 return (IDWriteFontFileLoader
*)&local_fontfile_loader
.IDWriteLocalFontFileLoader_iface
;
4874 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4876 struct local_refkey
*refkey
;
4879 return E_INVALIDARG
;
4881 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4884 refkey
= heap_alloc(*size
);
4886 return E_OUTOFMEMORY
;
4889 refkey
->writetime
= *writetime
;
4891 WIN32_FILE_ATTRIBUTE_DATA info
;
4893 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4894 refkey
->writetime
= info
.ftLastWriteTime
;
4896 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4898 strcpyW(refkey
->name
, path
);
4905 /* IDWriteGlyphRunAnalysis */
4906 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4908 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4910 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4912 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4913 IsEqualIID(riid
, &IID_IUnknown
))
4916 IDWriteGlyphRunAnalysis_AddRef(iface
);
4920 WARN("%s not implemented.\n", debugstr_guid(riid
));
4923 return E_NOINTERFACE
;
4926 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4928 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4929 ULONG ref
= InterlockedIncrement(&This
->ref
);
4930 TRACE("(%p)->(%u)\n", This
, ref
);
4934 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4936 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4937 ULONG ref
= InterlockedDecrement(&This
->ref
);
4939 TRACE("(%p)->(%u)\n", This
, ref
);
4942 if (This
->run
.fontFace
)
4943 IDWriteFontFace_Release(This
->run
.fontFace
);
4944 heap_free(This
->glyphs
);
4945 heap_free(This
->origins
);
4946 heap_free(This
->bitmap
);
4953 static BOOL
is_natural_rendering_mode(DWRITE_RENDERING_MODE1 mode
)
4957 case DWRITE_RENDERING_MODE1_NATURAL
:
4958 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
4959 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
4966 static UINT32
get_glyph_bitmap_pitch(DWRITE_RENDERING_MODE1 rendering_mode
, INT width
)
4968 return rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
? ((width
+ 31) >> 5) << 2 : (width
+ 3) / 4 * 4;
4971 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4973 struct dwrite_glyphbitmap glyph_bitmap
;
4974 IDWriteFontFace4
*fontface
;
4978 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4979 *bounds
= analysis
->bounds
;
4983 if (analysis
->run
.isSideways
)
4984 FIXME("sideways runs are not supported.\n");
4986 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
4988 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
4990 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4991 glyph_bitmap
.fontface
= fontface
;
4992 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
4993 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
4994 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
4995 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4996 glyph_bitmap
.m
= &analysis
->m
;
4998 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4999 RECT
*bbox
= &glyph_bitmap
.bbox
;
5002 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
5003 freetype_get_glyph_bbox(&glyph_bitmap
);
5005 bitmap_size
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, bbox
->right
- bbox
->left
) *
5006 (bbox
->bottom
- bbox
->top
);
5007 if (bitmap_size
> analysis
->max_glyph_bitmap_size
)
5008 analysis
->max_glyph_bitmap_size
= bitmap_size
;
5010 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5011 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
5014 IDWriteFontFace4_Release(fontface
);
5016 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
5017 *bounds
= analysis
->bounds
;
5020 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
5022 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5024 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
5026 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5027 SetRectEmpty(bounds
);
5028 return E_INVALIDARG
;
5031 if (type
!= This
->texture_type
) {
5032 SetRectEmpty(bounds
);
5036 glyphrunanalysis_get_texturebounds(This
, bounds
);
5040 static inline int get_dib_stride( int width
, int bpp
)
5042 return ((width
* bpp
+ 31) >> 3) & ~3;
5045 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
5047 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5048 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
5049 (runbounds
->left
- bounds
->left
) * 3;
5051 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
5052 runbounds
->left
- bounds
->left
;
5055 static HRESULT
glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
)
5057 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
5058 struct dwrite_glyphbitmap glyph_bitmap
;
5059 IDWriteFontFace4
*fontface
;
5060 D2D_POINT_2F origin
;
5065 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace4
, (void **)&fontface
);
5067 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5071 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
5072 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5074 if (!(analysis
->bitmap
= heap_alloc_zero(size
))) {
5075 WARN("Failed to allocate run bitmap, %s, type %s.\n", wine_dbgstr_rect(&analysis
->bounds
),
5076 analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? "3x1" : "1x1");
5077 IDWriteFontFace4_Release(fontface
);
5078 return E_OUTOFMEMORY
;
5081 origin
.x
= origin
.y
= 0.0f
;
5083 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
5084 glyph_bitmap
.fontface
= fontface
;
5085 glyph_bitmap
.simulations
= IDWriteFontFace4_GetSimulations(fontface
);
5086 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
;
5087 glyph_bitmap
.nohint
= is_natural_rendering_mode(analysis
->rendering_mode
);
5088 glyph_bitmap
.aliased
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
;
5089 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5090 glyph_bitmap
.m
= &analysis
->m
;
5091 if (!(glyph_bitmap
.buf
= heap_alloc(analysis
->max_glyph_bitmap_size
))) {
5092 IDWriteFontFace4_Release(fontface
);
5093 return E_OUTOFMEMORY
;
5096 bbox
= &glyph_bitmap
.bbox
;
5098 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
5099 BYTE
*src
= glyph_bitmap
.buf
, *dst
;
5100 int x
, y
, width
, height
;
5103 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
5104 freetype_get_glyph_bbox(&glyph_bitmap
);
5106 if (IsRectEmpty(bbox
))
5109 width
= bbox
->right
- bbox
->left
;
5110 height
= bbox
->bottom
- bbox
->top
;
5112 glyph_bitmap
.pitch
= get_glyph_bitmap_pitch(analysis
->rendering_mode
, width
);
5113 memset(src
, 0, height
* glyph_bitmap
.pitch
);
5114 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
5116 OffsetRect(bbox
, analysis
->origins
[i
].x
, analysis
->origins
[i
].y
);
5118 /* blit to analysis bitmap */
5119 dst
= get_pixel_ptr(analysis
->bitmap
, analysis
->texture_type
, bbox
, &analysis
->bounds
);
5122 /* convert 1bpp to 8bpp/24bpp */
5123 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5124 for (y
= 0; y
< height
; y
++) {
5125 for (x
= 0; x
< width
; x
++)
5126 if (src
[x
/ 8] & masks
[x
% 8])
5127 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
5128 src
+= glyph_bitmap
.pitch
;
5129 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5133 for (y
= 0; y
< height
; y
++) {
5134 for (x
= 0; x
< width
; x
++)
5135 if (src
[x
/ 8] & masks
[x
% 8])
5136 dst
[x
] = DWRITE_ALPHA_MAX
;
5137 src
+= glyph_bitmap
.pitch
;
5138 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5143 if (analysis
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
5144 for (y
= 0; y
< height
; y
++) {
5145 for (x
= 0; x
< width
; x
++)
5146 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
5147 src
+= glyph_bitmap
.pitch
;
5148 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
5152 for (y
= 0; y
< height
; y
++) {
5153 for (x
= 0; x
< width
; x
++)
5155 src
+= glyph_bitmap
.pitch
;
5156 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
5161 heap_free(glyph_bitmap
.buf
);
5163 IDWriteFontFace4_Release(fontface
);
5165 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
5167 /* we don't need this anymore */
5168 heap_free(analysis
->glyphs
);
5169 heap_free(analysis
->origins
);
5170 IDWriteFontFace_Release(analysis
->run
.fontFace
);
5172 analysis
->glyphs
= NULL
;
5173 analysis
->origins
= NULL
;
5174 analysis
->run
.glyphIndices
= NULL
;
5175 analysis
->run
.fontFace
= NULL
;
5180 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
5181 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
5183 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5187 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
5189 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
5190 return E_INVALIDARG
;
5192 /* make sure buffer is large enough for requested texture type */
5193 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
5194 if (This
->texture_type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
5197 if (size
< required
)
5198 return E_NOT_SUFFICIENT_BUFFER
;
5200 /* validate requested texture type */
5201 if (This
->texture_type
!= type
)
5202 return DWRITE_E_UNSUPPORTEDOPERATION
;
5204 memset(bitmap
, 0, size
);
5205 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
5206 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
5207 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
5208 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
5209 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
5210 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
5214 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
)) {
5217 if (FAILED(hr
= glyphrunanalysis_render(This
)))
5221 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
5222 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
5224 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
5225 memcpy(dst
, src
, draw_width
);
5234 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
5235 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
5237 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
5239 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
5242 return E_INVALIDARG
;
5244 switch (This
->rendering_mode
)
5246 case DWRITE_RENDERING_MODE1_GDI_CLASSIC
:
5247 case DWRITE_RENDERING_MODE1_GDI_NATURAL
:
5250 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5251 *gamma
= (FLOAT
)value
/ 1000.0f
;
5253 *cleartypelevel
= 1.0f
;
5256 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
:
5257 WARN("NATURAL_SYMMETRIC_DOWNSAMPLED mode is ignored.\n");
5259 case DWRITE_RENDERING_MODE1_ALIASED
:
5260 case DWRITE_RENDERING_MODE1_NATURAL
:
5261 case DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC
:
5262 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5263 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5264 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5273 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5274 glyphrunanalysis_QueryInterface
,
5275 glyphrunanalysis_AddRef
,
5276 glyphrunanalysis_Release
,
5277 glyphrunanalysis_GetAlphaTextureBounds
,
5278 glyphrunanalysis_CreateAlphaTexture
,
5279 glyphrunanalysis_GetAlphaBlendParams
5282 static inline void transform_point(D2D_POINT_2F
*point
, const DWRITE_MATRIX
*m
)
5285 ret
.x
= point
->x
* m
->m11
+ point
->y
* m
->m21
+ m
->dx
;
5286 ret
.y
= point
->x
* m
->m12
+ point
->y
* m
->m22
+ m
->dy
;
5290 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5292 struct dwrite_glyphrunanalysis
*analysis
;
5293 DWRITE_FONT_METRICS metrics
;
5294 IDWriteFontFace1
*fontface1
;
5295 D2D_POINT_2F origin
;
5302 /* Check rendering, antialising, measuring, and grid fitting modes. */
5303 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED
||
5304 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_OUTLINE
||
5305 desc
->rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
)
5306 return E_INVALIDARG
;
5308 if ((UINT32
)desc
->aa_mode
> DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5309 return E_INVALIDARG
;
5311 if ((UINT32
)desc
->gridfit_mode
> DWRITE_GRID_FIT_MODE_ENABLED
)
5312 return E_INVALIDARG
;
5314 if ((UINT32
)desc
->measuring_mode
> DWRITE_MEASURING_MODE_GDI_NATURAL
)
5315 return E_INVALIDARG
;
5317 analysis
= heap_alloc(sizeof(*analysis
));
5319 return E_OUTOFMEMORY
;
5321 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5323 analysis
->rendering_mode
= desc
->rendering_mode
;
5325 if (desc
->rendering_mode
== DWRITE_RENDERING_MODE1_ALIASED
5326 || desc
->aa_mode
== DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
)
5327 analysis
->texture_type
= DWRITE_TEXTURE_ALIASED_1x1
;
5329 analysis
->texture_type
= DWRITE_TEXTURE_CLEARTYPE_3x1
;
5331 analysis
->flags
= 0;
5332 analysis
->bitmap
= NULL
;
5333 analysis
->max_glyph_bitmap_size
= 0;
5334 SetRectEmpty(&analysis
->bounds
);
5335 analysis
->run
= *desc
->run
;
5336 analysis
->run
.fontEmSize
*= desc
->ppdip
;
5337 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5338 analysis
->glyphs
= heap_alloc(desc
->run
->glyphCount
* sizeof(*analysis
->glyphs
));
5339 analysis
->origins
= heap_alloc(desc
->run
->glyphCount
* sizeof(*analysis
->origins
));
5341 if (!analysis
->glyphs
|| !analysis
->origins
) {
5342 heap_free(analysis
->glyphs
);
5343 heap_free(analysis
->origins
);
5345 analysis
->glyphs
= NULL
;
5346 analysis
->origins
= NULL
;
5348 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5349 return E_OUTOFMEMORY
;
5352 /* check if transform is usable */
5353 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5354 analysis
->m
= *desc
->transform
;
5355 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5358 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5360 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5361 analysis
->run
.glyphAdvances
= NULL
;
5362 analysis
->run
.glyphOffsets
= NULL
;
5364 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5366 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5368 IDWriteFontFace_GetMetrics(desc
->run
->fontFace
, &metrics
);
5369 if (FAILED(hr
= IDWriteFontFace_QueryInterface(desc
->run
->fontFace
, &IID_IDWriteFontFace1
, (void **)&fontface1
)))
5370 WARN("Failed to get IDWriteFontFace1, %#x.\n", hr
);
5372 origin
.x
= desc
->origin_x
* desc
->ppdip
;
5373 origin
.y
= desc
->origin_y
* desc
->ppdip
;
5374 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5377 /* Use nominal advances if not provided by caller. */
5378 if (desc
->run
->glyphAdvances
)
5379 advance
= rtl_factor
* desc
->run
->glyphAdvances
[i
] * desc
->ppdip
;
5384 switch (desc
->measuring_mode
)
5386 case DWRITE_MEASURING_MODE_NATURAL
:
5387 if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, desc
->run
->glyphIndices
+ i
, &a
,
5388 desc
->run
->isSideways
)))
5389 advance
= rtl_factor
* get_scaled_advance_width(a
, desc
->run
->fontEmSize
, &metrics
) * desc
->ppdip
;
5391 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5392 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5393 if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, desc
->run
->fontEmSize
,
5394 desc
->ppdip
, desc
->transform
, desc
->measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
,
5395 desc
->run
->isSideways
, 1, desc
->run
->glyphIndices
+ i
, &a
)))
5396 advance
= rtl_factor
* floorf(a
* desc
->run
->fontEmSize
* desc
->ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
);
5403 analysis
->origins
[i
] = origin
;
5405 /* Offsets are optional, appled to pre-transformed origin. */
5406 if (desc
->run
->glyphOffsets
) {
5407 FLOAT advanceoffset
= rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
* desc
->ppdip
;
5408 FLOAT ascenderoffset
= -desc
->run
->glyphOffsets
[i
].ascenderOffset
* desc
->ppdip
;
5410 if (desc
->run
->isSideways
) {
5411 analysis
->origins
[i
].x
+= ascenderoffset
;
5412 analysis
->origins
[i
].y
+= advanceoffset
;
5415 analysis
->origins
[i
].x
+= advanceoffset
;
5416 analysis
->origins
[i
].y
+= ascenderoffset
;
5420 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5421 transform_point(analysis
->origins
+ i
, &analysis
->m
);
5423 if (desc
->run
->isSideways
)
5424 origin
.y
+= advance
;
5426 origin
.x
+= advance
;
5429 IDWriteFontFace1_Release(fontface1
);
5431 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5435 /* IDWriteColorGlyphRunEnumerator */
5436 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
5438 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5440 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5442 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5443 IsEqualIID(riid
, &IID_IUnknown
))
5446 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
5450 WARN("%s not implemented.\n", debugstr_guid(riid
));
5453 return E_NOINTERFACE
;
5456 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
5458 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5459 ULONG ref
= InterlockedIncrement(&This
->ref
);
5460 TRACE("(%p)->(%u)\n", This
, ref
);
5464 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
5466 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5467 ULONG ref
= InterlockedDecrement(&This
->ref
);
5469 TRACE("(%p)->(%u)\n", This
, ref
);
5472 heap_free(This
->advances
);
5473 heap_free(This
->color_advances
);
5474 heap_free(This
->offsets
);
5475 heap_free(This
->color_offsets
);
5476 heap_free(This
->glyphindices
);
5477 heap_free(This
->glyphs
);
5478 if (This
->colr
.context
)
5479 IDWriteFontFace4_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
5480 IDWriteFontFace4_Release(This
->fontface
);
5487 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5489 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5490 FLOAT origin
= 0.0f
;
5496 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5500 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5502 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5503 FLOAT advance_adj
= 0.0f
;
5504 BOOL got_palette_index
;
5507 /* start with regular glyphs */
5508 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5509 UINT32 first_glyph
= 0;
5511 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5512 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5513 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5514 first_glyph
= min(first_glyph
, g
);
5517 glyphenum
->glyphindices
[g
] = 1;
5518 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5519 if (glyphenum
->color_offsets
)
5520 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5523 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5524 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5525 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5526 colorrun
->paletteIndex
= 0xffff;
5527 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5528 glyphenum
->has_regular_glyphs
= FALSE
;
5532 colorrun
->glyphRun
.glyphCount
= 0;
5533 got_palette_index
= FALSE
;
5537 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5539 glyphenum
->glyphindices
[g
] = 1;
5541 /* all glyph layers were returned */
5542 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5543 advance_adj
+= glyphenum
->advances
[g
];
5547 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5548 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5549 if (!got_palette_index
) {
5550 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5551 /* use foreground color or request one from the font */
5552 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5553 if (colorrun
->paletteIndex
!= 0xffff) {
5554 HRESULT hr
= IDWriteFontFace4_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5555 1, &colorrun
->runColor
);
5557 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5558 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5560 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5561 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5562 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5563 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5564 got_palette_index
= TRUE
;
5567 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5568 /* offsets are relative to glyph origin, nothing to fix up */
5569 if (glyphenum
->color_offsets
)
5570 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5571 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5573 glyphenum
->color_advances
[index
-1] += advance_adj
;
5574 colorrun
->glyphRun
.glyphCount
++;
5578 advance_adj
+= glyphenum
->advances
[g
];
5581 /* reset last advance */
5582 if (colorrun
->glyphRun
.glyphCount
)
5583 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5585 return colorrun
->glyphRun
.glyphCount
> 0;
5588 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5590 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5592 TRACE("(%p)->(%p)\n", This
, has_run
);
5596 This
->colorrun
.glyphRun
.glyphCount
= 0;
5597 while (This
->current_layer
< This
->max_layer_num
) {
5598 if (colorglyphenum_build_color_run(This
))
5601 This
->current_layer
++;
5604 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5609 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5611 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5613 TRACE("(%p)->(%p)\n", This
, run
);
5615 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5617 return E_NOT_VALID_STATE
;
5620 *run
= &This
->colorrun
;
5624 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5625 colorglyphenum_QueryInterface
,
5626 colorglyphenum_AddRef
,
5627 colorglyphenum_Release
,
5628 colorglyphenum_MoveNext
,
5629 colorglyphenum_GetCurrentRun
5632 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5633 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5635 struct dwrite_colorglyphenum
*colorglyphenum
;
5636 BOOL colorfont
, has_colored_glyph
;
5637 IDWriteFontFace4
*fontface
;
5643 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace4
, (void**)&fontface
);
5645 WARN("failed to get IDWriteFontFace4, 0x%08x\n", hr
);
5649 colorfont
= IDWriteFontFace4_IsColorFont(fontface
) && IDWriteFontFace4_GetColorPaletteCount(fontface
) > palette
;
5651 hr
= DWRITE_E_NOCOLOR
;
5655 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5656 if (!colorglyphenum
) {
5661 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5662 colorglyphenum
->ref
= 1;
5663 colorglyphenum
->origin_x
= originX
;
5664 colorglyphenum
->origin_y
= originY
;
5665 colorglyphenum
->fontface
= fontface
;
5666 colorglyphenum
->glyphs
= NULL
;
5667 colorglyphenum
->run
= *run
;
5668 colorglyphenum
->run
.glyphIndices
= NULL
;
5669 colorglyphenum
->run
.glyphAdvances
= NULL
;
5670 colorglyphenum
->run
.glyphOffsets
= NULL
;
5671 colorglyphenum
->palette
= palette
;
5672 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5673 colorglyphenum
->colr
.exists
= TRUE
;
5674 get_fontface_table(fontface
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5675 colorglyphenum
->current_layer
= 0;
5676 colorglyphenum
->max_layer_num
= 0;
5678 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5680 has_colored_glyph
= FALSE
;
5681 colorglyphenum
->has_regular_glyphs
= FALSE
;
5682 for (i
= 0; i
< run
->glyphCount
; i
++) {
5683 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5684 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5685 has_colored_glyph
= TRUE
;
5687 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5688 colorglyphenum
->has_regular_glyphs
= TRUE
;
5691 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5692 is supposed to proceed normally, like if font had no color info at all. */
5693 if (!has_colored_glyph
) {
5694 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5695 return DWRITE_E_NOCOLOR
;
5698 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5699 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5700 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5701 if (run
->glyphOffsets
) {
5702 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5703 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5704 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5707 colorglyphenum
->colorrun
.glyphRun
.fontFace
= (IDWriteFontFace
*)fontface
;
5708 colorglyphenum
->colorrun
.glyphRun
.fontEmSize
= run
->fontEmSize
;
5709 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5710 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5711 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5712 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5714 if (run
->glyphAdvances
)
5715 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5717 DWRITE_FONT_METRICS metrics
;
5719 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5720 for (i
= 0; i
< run
->glyphCount
; i
++) {
5724 switch (measuring_mode
)
5726 case DWRITE_MEASURING_MODE_NATURAL
:
5727 hr
= IDWriteFontFace4_GetDesignGlyphAdvances(fontface
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5730 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5732 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5733 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5734 hr
= IDWriteFontFace4_GetGdiCompatibleGlyphAdvances(fontface
, run
->fontEmSize
, 1.0f
, transform
,
5735 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5737 colorglyphenum
->advances
[i
] = 0.0f
;
5739 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5747 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5751 IDWriteFontFace4_Release(fontface
);
5755 /* IDWriteFontFaceReference */
5756 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
5758 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5760 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5762 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) || IsEqualIID(riid
, &IID_IUnknown
)) {
5764 IDWriteFontFaceReference_AddRef(iface
);
5768 WARN("%s not implemented.\n", debugstr_guid(riid
));
5772 return E_NOINTERFACE
;
5775 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference
*iface
)
5777 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5778 ULONG ref
= InterlockedIncrement(&This
->ref
);
5779 TRACE("(%p)->(%u)\n", This
, ref
);
5783 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference
*iface
)
5785 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5786 ULONG ref
= InterlockedDecrement(&This
->ref
);
5788 TRACE("(%p)->(%u)\n", This
, ref
);
5791 IDWriteFontFile_Release(This
->file
);
5792 IDWriteFactory5_Release(This
->factory
);
5799 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference
*iface
, IDWriteFontFace3
**fontface
)
5801 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5803 TRACE("(%p)->(%p)\n", This
, fontface
);
5805 return IDWriteFontFaceReference_CreateFontFaceWithSimulations(iface
, This
->simulations
, fontface
);
5808 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
5809 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
5811 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5812 DWRITE_FONT_FILE_TYPE file_type
;
5813 DWRITE_FONT_FACE_TYPE face_type
;
5814 IDWriteFontFace
*fontface
;
5819 TRACE("(%p)->(%d %p)\n", This
, simulations
, ret
);
5821 hr
= IDWriteFontFile_Analyze(This
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
5825 hr
= IDWriteFactory5_CreateFontFace(This
->factory
, face_type
, 1, &This
->file
, This
->index
, simulations
, &fontface
);
5826 if (SUCCEEDED(hr
)) {
5827 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void **)ret
);
5828 IDWriteFontFace_Release(fontface
);
5834 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
5836 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5837 IDWriteFontFile
*file
;
5840 TRACE("(%p)->(%p)\n", This
, ref
);
5842 if (FAILED(IDWriteFontFaceReference_GetFontFile(ref
, &file
)))
5845 ret
= is_same_fontfile(This
->file
, file
) &&
5846 This
->index
== IDWriteFontFaceReference_GetFontFaceIndex(ref
) &&
5847 This
->simulations
== IDWriteFontFaceReference_GetSimulations(ref
);
5848 IDWriteFontFile_Release(file
);
5853 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
5855 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5857 TRACE("(%p)\n", This
);
5862 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference
*iface
)
5864 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5866 TRACE("(%p)\n", This
);
5868 return This
->simulations
;
5871 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
5873 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5874 IDWriteFontFileLoader
*loader
;
5879 TRACE("(%p)->(%p)\n", This
, file
);
5881 hr
= IDWriteFontFile_GetReferenceKey(This
->file
, &key
, &key_size
);
5885 hr
= IDWriteFontFile_GetLoader(This
->file
, &loader
);
5889 hr
= IDWriteFactory5_CreateCustomFontFileReference(This
->factory
, key
, key_size
, loader
, file
);
5890 IDWriteFontFileLoader_Release(loader
);
5895 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
5897 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5899 FIXME("(%p): stub\n", This
);
5904 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference
*iface
)
5906 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5908 FIXME("(%p): stub\n", This
);
5913 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
5915 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5917 FIXME("(%p)->(%p): stub\n", This
, writetime
);
5922 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference
*iface
)
5924 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5926 FIXME("(%p): stub\n", This
);
5928 return DWRITE_LOCALITY_LOCAL
;
5931 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
5933 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5935 FIXME("(%p): stub\n", This
);
5940 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
, WCHAR
const *chars
,
5943 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5945 FIXME("(%p)->(%s:%u): stub\n", This
, debugstr_wn(chars
, count
), count
);
5950 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
, UINT16
const *glyphs
,
5953 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5955 FIXME("(%p)->(%p %u): stub\n", This
, glyphs
, count
);
5960 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
5961 UINT64 offset
, UINT64 size
)
5963 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5965 FIXME("(%p)->(0x%s 0x%s): stub\n", This
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
5970 static const IDWriteFontFaceReferenceVtbl fontfacereferencevtbl
= {
5971 fontfacereference_QueryInterface
,
5972 fontfacereference_AddRef
,
5973 fontfacereference_Release
,
5974 fontfacereference_CreateFontFace
,
5975 fontfacereference_CreateFontFaceWithSimulations
,
5976 fontfacereference_Equals
,
5977 fontfacereference_GetFontFaceIndex
,
5978 fontfacereference_GetSimulations
,
5979 fontfacereference_GetFontFile
,
5980 fontfacereference_GetLocalFileSize
,
5981 fontfacereference_GetFileSize
,
5982 fontfacereference_GetFileTime
,
5983 fontfacereference_GetLocality
,
5984 fontfacereference_EnqueueFontDownloadRequest
,
5985 fontfacereference_EnqueueCharacterDownloadRequest
,
5986 fontfacereference_EnqueueGlyphDownloadRequest
,
5987 fontfacereference_EnqueueFileFragmentDownloadRequest
5990 HRESULT
create_fontfacereference(IDWriteFactory5
*factory
, IDWriteFontFile
*file
, UINT32 index
,
5991 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFaceReference
**ret
)
5993 struct dwrite_fontfacereference
*ref
;
5997 if (!is_simulation_valid(simulations
))
5998 return E_INVALIDARG
;
6000 ref
= heap_alloc(sizeof(*ref
));
6002 return E_OUTOFMEMORY
;
6004 ref
->IDWriteFontFaceReference_iface
.lpVtbl
= &fontfacereferencevtbl
;
6007 ref
->factory
= factory
;
6008 IDWriteFactory5_AddRef(ref
->factory
);
6010 IDWriteFontFile_AddRef(ref
->file
);
6012 ref
->simulations
= simulations
;
6013 *ret
= &ref
->IDWriteFontFaceReference_iface
;
6018 static HRESULT WINAPI
inmemoryfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
6020 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6022 TRACE_(dwrite_file
)("(%p)->(%s, %p)\n", stream
, debugstr_guid(riid
), obj
);
6024 if (IsEqualIID(riid
, &IID_IDWriteFontFileStream
) || IsEqualIID(riid
, &IID_IUnknown
)) {
6026 IDWriteFontFileStream_AddRef(iface
);
6032 WARN("%s not implemented.\n", debugstr_guid(riid
));
6033 return E_NOINTERFACE
;
6036 static ULONG WINAPI
inmemoryfilestream_AddRef(IDWriteFontFileStream
*iface
)
6038 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6039 ULONG ref
= InterlockedIncrement(&stream
->ref
);
6040 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6044 static ULONG WINAPI
inmemoryfilestream_Release(IDWriteFontFileStream
*iface
)
6046 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6047 ULONG ref
= InterlockedDecrement(&stream
->ref
);
6049 TRACE_(dwrite_file
)("(%p)->(%u)\n", stream
, ref
);
6052 release_inmemory_stream(stream
->data
);
6059 static HRESULT WINAPI
inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
,
6060 UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
6062 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6064 TRACE_(dwrite_file
)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream
, fragment_start
,
6065 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
6067 *fragment_context
= NULL
;
6069 if ((offset
>= stream
->data
->size
- 1) || (fragment_size
> stream
->data
->size
- offset
)) {
6070 *fragment_start
= NULL
;
6074 *fragment_start
= (char *)stream
->data
->data
+ offset
;
6078 static void WINAPI
inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
6080 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6082 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, fragment_context
);
6085 static HRESULT WINAPI
inmemoryfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
6087 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6089 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, size
);
6091 *size
= stream
->data
->size
;
6096 static HRESULT WINAPI
inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
6098 struct dwrite_inmemory_filestream
*stream
= inmemory_impl_from_IDWriteFontFileStream(iface
);
6100 TRACE_(dwrite_file
)("(%p)->(%p)\n", stream
, last_writetime
);
6102 *last_writetime
= 0;
6107 static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl
= {
6108 inmemoryfilestream_QueryInterface
,
6109 inmemoryfilestream_AddRef
,
6110 inmemoryfilestream_Release
,
6111 inmemoryfilestream_ReadFileFragment
,
6112 inmemoryfilestream_ReleaseFileFragment
,
6113 inmemoryfilestream_GetFileSize
,
6114 inmemoryfilestream_GetLastWriteTime
,
6117 static HRESULT WINAPI
inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader
*iface
,
6118 REFIID riid
, void **obj
)
6120 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6122 TRACE("(%p)->(%s, %p)\n", loader
, debugstr_guid(riid
), obj
);
6124 if (IsEqualIID(riid
, &IID_IDWriteInMemoryFontFileLoader
) ||
6125 IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) ||
6126 IsEqualIID(riid
, &IID_IUnknown
))
6129 IDWriteInMemoryFontFileLoader_AddRef(iface
);
6133 WARN("%s not implemented.\n", debugstr_guid(riid
));
6137 return E_NOINTERFACE
;
6140 static ULONG WINAPI
inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader
*iface
)
6142 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6143 ULONG ref
= InterlockedIncrement(&loader
->ref
);
6144 TRACE("(%p)->(%u)\n", loader
, ref
);
6148 static ULONG WINAPI
inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader
*iface
)
6150 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6151 ULONG ref
= InterlockedDecrement(&loader
->ref
);
6153 TRACE("(%p)->(%u)\n", loader
, ref
);
6158 for (i
= 0; i
< loader
->filecount
; i
++)
6159 release_inmemory_stream(loader
->streams
[i
]);
6160 heap_free(loader
->streams
);
6167 static HRESULT WINAPI
inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader
*iface
,
6168 void const *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
6170 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6171 struct dwrite_inmemory_filestream
*stream
;
6174 TRACE("(%p)->(%p, %u, %p)\n", loader
, key
, key_size
, ret
);
6178 if (key_size
!= sizeof(DWORD
))
6179 return E_INVALIDARG
;
6181 index
= *(DWORD
*)key
;
6183 if (index
>= loader
->filecount
)
6184 return E_INVALIDARG
;
6186 if (!(stream
= heap_alloc(sizeof(*stream
))))
6187 return E_OUTOFMEMORY
;
6189 stream
->IDWriteFontFileStream_iface
.lpVtbl
= &inmemoryfilestreamvtbl
;
6191 stream
->data
= loader
->streams
[index
];
6192 InterlockedIncrement(&stream
->data
->ref
);
6194 *ret
= &stream
->IDWriteFontFileStream_iface
;
6199 static HRESULT WINAPI
inmemoryfontfileloader_CreateInMemoryFontFileReference(IDWriteInMemoryFontFileLoader
*iface
,
6200 IDWriteFactory
*factory
, void const *data
, UINT32 data_size
, IUnknown
*owner
, IDWriteFontFile
**fontfile
)
6202 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6203 struct dwrite_inmemory_stream_data
*stream
;
6206 TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader
, factory
, data
, data_size
, owner
, fontfile
);
6210 if (loader
->filecount
== loader
->capacity
) {
6211 if (loader
->streams
) {
6212 struct dwrite_inmemory_stream_data
**ptr
;
6214 if (!(ptr
= heap_realloc(loader
->streams
, 2 * loader
->capacity
* sizeof(*loader
->streams
))))
6215 return E_OUTOFMEMORY
;
6217 loader
->streams
= ptr
;
6218 loader
->capacity
*= 2;
6221 loader
->capacity
= 16;
6222 loader
->streams
= heap_alloc(loader
->capacity
* sizeof(*loader
->streams
));
6226 if (!(stream
= heap_alloc(sizeof(*stream
))))
6227 return E_OUTOFMEMORY
;
6230 stream
->size
= data_size
;
6231 stream
->owner
= owner
;
6232 if (stream
->owner
) {
6233 IUnknown_AddRef(stream
->owner
);
6234 stream
->data
= (void *)data
;
6237 if (!(stream
->data
= heap_alloc(data_size
))) {
6239 return E_OUTOFMEMORY
;
6241 memcpy(stream
->data
, data
, data_size
);
6244 key
= loader
->filecount
;
6245 loader
->streams
[loader
->filecount
++] = stream
;
6247 return IDWriteFactory_CreateCustomFontFileReference(factory
, &key
, sizeof(key
),
6248 (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
, fontfile
);
6251 static UINT32 WINAPI
inmemoryfontfileloader_GetFileCount(IDWriteInMemoryFontFileLoader
*iface
)
6253 struct dwrite_inmemory_fileloader
*loader
= impl_from_IDWriteInMemoryFontFileLoader(iface
);
6255 TRACE("(%p)\n", loader
);
6257 return loader
->filecount
;
6260 static const IDWriteInMemoryFontFileLoaderVtbl inmemoryfontfileloadervtbl
=
6262 inmemoryfontfileloader_QueryInterface
,
6263 inmemoryfontfileloader_AddRef
,
6264 inmemoryfontfileloader_Release
,
6265 inmemoryfontfileloader_CreateStreamFromKey
,
6266 inmemoryfontfileloader_CreateInMemoryFontFileReference
,
6267 inmemoryfontfileloader_GetFileCount
,
6270 HRESULT
create_inmemory_fileloader(IDWriteFontFileLoader
**ret
)
6272 struct dwrite_inmemory_fileloader
*loader
;
6276 loader
= heap_alloc_zero(sizeof(*loader
));
6278 return E_OUTOFMEMORY
;
6280 loader
->IDWriteInMemoryFontFileLoader_iface
.lpVtbl
= &inmemoryfontfileloadervtbl
;
6283 *ret
= (IDWriteFontFileLoader
*)&loader
->IDWriteInMemoryFontFileLoader_iface
;