4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2016 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
26 #include "dwrite_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
29 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
31 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
32 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
33 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
34 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
35 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
36 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
37 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
38 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
40 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
42 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
43 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
44 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
46 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
47 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
48 static const WCHAR semiW
[] = {'s','e','m','i',0};
49 static const WCHAR extW
[] = {'e','x','t',0};
50 static const WCHAR thinW
[] = {'t','h','i','n',0};
51 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
52 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
53 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
54 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
55 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
56 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
57 static const WCHAR boldW
[] = {'B','o','l','d',0};
58 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
59 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
60 static const WCHAR demiW
[] = {'d','e','m','i',0};
61 static const WCHAR spaceW
[] = {' ',0};
62 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
64 struct dwrite_font_propvec
{
70 struct dwrite_font_data
{
73 DWRITE_FONT_STYLE style
;
74 DWRITE_FONT_STRETCH stretch
;
75 DWRITE_FONT_WEIGHT weight
;
77 struct dwrite_font_propvec propvec
;
79 DWRITE_FONT_METRICS1 metrics
;
80 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
81 IDWriteLocalizedStrings
*names
;
83 /* data needed to create fontface instance */
84 IDWriteFactory3
*factory
;
85 DWRITE_FONT_FACE_TYPE face_type
;
86 IDWriteFontFile
*file
;
93 /* used to mark font as tested when scanning for simulation candidate */
94 BOOL bold_sim_tested
: 1;
95 BOOL oblique_sim_tested
: 1;
98 struct dwrite_fontlist
{
99 IDWriteFontList1 IDWriteFontList1_iface
;
102 IDWriteFontFamily1
*family
;
103 struct dwrite_font_data
**fonts
;
107 struct dwrite_fontfamily_data
{
110 IDWriteLocalizedStrings
*familyname
;
112 struct dwrite_font_data
**fonts
;
115 BOOL has_normal_face
: 1;
116 BOOL has_oblique_face
: 1;
117 BOOL has_italic_face
: 1;
120 struct dwrite_fontcollection
{
121 IDWriteFontCollection1 IDWriteFontCollection1_iface
;
124 struct dwrite_fontfamily_data
**family_data
;
129 struct dwrite_fontfamily
{
130 IDWriteFontFamily1 IDWriteFontFamily1_iface
;
133 struct dwrite_fontfamily_data
*data
;
135 IDWriteFontCollection1
*collection
;
139 IDWriteFont3 IDWriteFont3_iface
;
142 IDWriteFontFamily1
*family
;
144 DWRITE_FONT_STYLE style
;
145 struct dwrite_font_data
*data
;
148 struct dwrite_fonttable
{
155 enum runanalysis_flags
{
156 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
157 RUNANALYSIS_BITMAP_READY
= 1 << 1,
158 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
161 struct dwrite_glyphrunanalysis
{
162 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
165 DWRITE_RENDERING_MODE rendering_mode
;
166 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
171 D2D_POINT_2F
*advances
;
172 D2D_POINT_2F
*advanceoffsets
;
173 D2D_POINT_2F
*ascenderoffsets
;
180 struct dwrite_colorglyphenum
{
181 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
184 FLOAT origin_x
; /* original run origin */
187 IDWriteFontFace3
*fontface
; /* for convenience */
188 DWRITE_COLOR_GLYPH_RUN colorrun
; /* returned with GetCurrentRun() */
189 DWRITE_GLYPH_RUN run
; /* base run */
190 UINT32 palette
; /* palette index to get layer color from */
191 FLOAT
*advances
; /* original or measured advances for base glyphs */
192 FLOAT
*color_advances
; /* returned color run points to this */
193 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
194 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
195 UINT16
*glyphindices
; /* returned color run points to this */
196 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
197 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
198 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
199 UINT16 max_layer_num
; /* max number of layers for this run */
200 struct dwrite_fonttable colr
; /* used to access layers */
203 #define GLYPH_BLOCK_SHIFT 8
204 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
205 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
206 #define GLYPH_MAX 65536
208 enum fontface_flags
{
209 FONTFACE_IS_SYMBOL
= 1 << 0,
210 FONTFACE_IS_MONOSPACED
= 1 << 1,
211 FONTFACE_HAS_KERN_PAIRS
= 1 << 2,
212 FONTFACE_HAS_VERTICAL_VARIANTS
= 1 << 3
215 struct dwrite_fontface
{
216 IDWriteFontFace3 IDWriteFontFace3_iface
;
219 IDWriteFontFileStream
**streams
;
220 IDWriteFontFile
**files
;
225 DWRITE_FONT_FACE_TYPE type
;
226 DWRITE_FONT_METRICS1 metrics
;
227 DWRITE_CARET_METRICS caret
;
231 struct dwrite_fonttable cmap
;
232 struct dwrite_fonttable vdmx
;
233 struct dwrite_fonttable gasp
;
234 struct dwrite_fonttable cpal
;
235 struct dwrite_fonttable colr
;
236 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
238 DWRITE_FONT_STYLE style
;
239 DWRITE_FONT_STRETCH stretch
;
240 DWRITE_FONT_WEIGHT weight
;
241 DWRITE_PANOSE panose
;
244 struct dwrite_fontfile
{
245 IDWriteFontFile IDWriteFontFile_iface
;
248 IDWriteFontFileLoader
*loader
;
251 IDWriteFontFileStream
*stream
;
254 struct dwrite_fontfacereference
{
255 IDWriteFontFaceReference IDWriteFontFaceReference_iface
;
258 IDWriteFontFile
*file
;
261 IDWriteFactory3
*factory
;
264 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace3(IDWriteFontFace3
*iface
)
266 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace3_iface
);
269 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
271 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
274 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
276 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
279 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
281 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
284 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection1(IDWriteFontCollection1
*iface
)
286 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection1_iface
);
289 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
291 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
294 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
296 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
299 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList1(IDWriteFontList1
*iface
)
301 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList1_iface
);
304 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
306 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference_iface
);
309 static inline const char *debugstr_tag(UINT32 tag
)
311 return debugstr_an((char*)&tag
, 4);
314 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
316 static const DWRITE_GLYPH_METRICS nil
;
317 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
319 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
320 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
324 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
326 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
329 /* start new block */
330 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
332 return E_OUTOFMEMORY
;
335 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
339 static void* get_fontface_table(IDWriteFontFace3
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
343 if (table
->data
|| !table
->exists
)
346 table
->exists
= FALSE
;
347 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
349 if (FAILED(hr
) || !table
->exists
) {
350 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
357 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
358 struct dwrite_font_propvec
*vec
)
360 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
361 vec
->style
= style
* 7.0f
;
362 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
365 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
367 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
370 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
372 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
375 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
377 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
380 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
382 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
385 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
387 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_GASP_TAG
, &fontface
->gasp
);
388 *size
= fontface
->gasp
.size
;
392 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
394 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
397 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
399 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_COLR_TAG
, &fontface
->colr
);
402 static void release_font_data(struct dwrite_font_data
*data
)
406 if (InterlockedDecrement(&data
->ref
) > 0)
409 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
410 if (data
->info_strings
[i
])
411 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
414 IDWriteLocalizedStrings_Release(data
->names
);
416 IDWriteFontFile_Release(data
->file
);
417 IDWriteFactory3_Release(data
->factory
);
418 heap_free(data
->facename
);
422 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
426 if (InterlockedDecrement(&data
->ref
) > 0)
429 for (i
= 0; i
< data
->font_count
; i
++)
430 release_font_data(data
->fonts
[i
]);
431 heap_free(data
->fonts
);
432 IDWriteLocalizedStrings_Release(data
->familyname
);
436 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace3
*iface
, REFIID riid
, void **obj
)
438 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
440 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
442 if (IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
443 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
444 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
445 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
446 IsEqualIID(riid
, &IID_IUnknown
))
449 IDWriteFontFace3_AddRef(iface
);
454 return E_NOINTERFACE
;
457 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace3
*iface
)
459 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
460 ULONG ref
= InterlockedIncrement(&This
->ref
);
461 TRACE("(%p)->(%d)\n", This
, ref
);
465 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace3
*iface
)
467 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
468 ULONG ref
= InterlockedDecrement(&This
->ref
);
470 TRACE("(%p)->(%d)\n", This
, ref
);
475 if (This
->cmap
.context
)
476 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cmap
.context
);
477 if (This
->vdmx
.context
)
478 IDWriteFontFace3_ReleaseFontTable(iface
, This
->vdmx
.context
);
479 if (This
->gasp
.context
)
480 IDWriteFontFace3_ReleaseFontTable(iface
, This
->gasp
.context
);
481 if (This
->cpal
.context
)
482 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cpal
.context
);
483 if (This
->colr
.context
)
484 IDWriteFontFace3_ReleaseFontTable(iface
, This
->colr
.context
);
485 for (i
= 0; i
< This
->file_count
; i
++) {
486 if (This
->streams
[i
])
487 IDWriteFontFileStream_Release(This
->streams
[i
]);
489 IDWriteFontFile_Release(This
->files
[i
]);
491 heap_free(This
->streams
);
492 heap_free(This
->files
);
494 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
495 heap_free(This
->glyphs
[i
]);
497 freetype_notify_cacheremove(iface
);
504 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace3
*iface
)
506 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
507 TRACE("(%p)\n", This
);
511 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace3
*iface
, UINT32
*number_of_files
,
512 IDWriteFontFile
**fontfiles
)
514 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
517 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
518 if (fontfiles
== NULL
)
520 *number_of_files
= This
->file_count
;
523 if (*number_of_files
< This
->file_count
)
526 for (i
= 0; i
< This
->file_count
; i
++)
528 IDWriteFontFile_AddRef(This
->files
[i
]);
529 fontfiles
[i
] = This
->files
[i
];
535 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace3
*iface
)
537 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
538 TRACE("(%p)\n", This
);
542 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace3
*iface
)
544 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
545 TRACE("(%p)\n", This
);
546 return This
->simulations
;
549 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace3
*iface
)
551 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
552 TRACE("(%p)\n", This
);
553 return !!(This
->flags
& FONTFACE_IS_SYMBOL
);
556 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS
*metrics
)
558 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
559 TRACE("(%p)->(%p)\n", This
, metrics
);
560 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
563 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace3
*iface
)
565 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
566 TRACE("(%p)\n", This
);
567 return freetype_get_glyphcount(iface
);
570 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace3
*iface
,
571 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
573 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
577 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
583 FIXME("sideways metrics are not supported.\n");
585 for (i
= 0; i
< glyph_count
; i
++) {
586 DWRITE_GLYPH_METRICS metrics
;
588 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
590 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
591 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
601 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace3
*iface
, UINT32
const *codepoints
,
602 UINT32 count
, UINT16
*glyph_indices
)
604 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
606 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
612 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
616 freetype_get_glyphs(iface
, This
->charmap
, codepoints
, count
, glyph_indices
);
620 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace3
*iface
, UINT32 table_tag
,
621 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
623 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
624 struct file_stream_desc stream_desc
;
626 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
628 stream_desc
.stream
= This
->streams
[0];
629 stream_desc
.face_type
= This
->type
;
630 stream_desc
.face_index
= This
->index
;
631 return opentype_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
634 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace3
*iface
, void *table_context
)
636 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
638 TRACE("(%p)->(%p)\n", This
, table_context
);
640 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
643 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace3
*iface
, FLOAT emSize
,
644 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
645 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
647 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
649 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
650 count
, is_sideways
, is_rtl
, sink
);
652 if (!glyphs
|| !sink
)
656 FIXME("sideways mode is not supported.\n");
658 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
661 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
662 FLOAT ppem
, WORD gasp
)
664 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
668 case DWRITE_MEASURING_MODE_NATURAL
:
670 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
671 mode
= DWRITE_RENDERING_MODE_NATURAL
;
673 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
676 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
677 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
679 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
680 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
689 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
690 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
692 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
697 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
700 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
704 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
705 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
708 ppem
= emSize
* ppdip
;
710 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
711 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
715 ptr
= get_fontface_gasp(This
, &size
);
716 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
717 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
721 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
722 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
724 DWRITE_FONT_METRICS1 metrics1
;
725 HRESULT hr
= IDWriteFontFace3_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
726 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
730 static inline int round_metric(FLOAT metric
)
732 return (int)floorf(metric
+ 0.5f
);
735 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT ppdip
,
736 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
737 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
739 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
740 DWRITE_MEASURING_MODE mode
;
745 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
746 glyph_count
, metrics
, is_sideways
);
748 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
749 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
751 size
= emSize
* ppdip
;
752 scale
= size
/ This
->metrics
.designUnitsPerEm
;
753 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
755 for (i
= 0; i
< glyph_count
; i
++) {
756 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
757 DWRITE_GLYPH_METRICS design
;
759 hr
= IDWriteFontFace3_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
763 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
);
764 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
766 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
767 SCALE_METRIC(leftSideBearing
);
768 SCALE_METRIC(rightSideBearing
);
769 SCALE_METRIC(topSideBearing
);
770 SCALE_METRIC(advanceHeight
);
771 SCALE_METRIC(bottomSideBearing
);
772 SCALE_METRIC(verticalOriginY
);
779 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
781 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
782 TRACE("(%p)->(%p)\n", This
, metrics
);
783 *metrics
= This
->metrics
;
786 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
787 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
789 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
790 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
791 UINT16 ascent
, descent
;
794 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
796 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
797 memset(metrics
, 0, sizeof(*metrics
));
801 em_size
*= pixels_per_dip
;
802 if (m
&& m
->m22
!= 0.0f
)
803 em_size
*= fabs(m
->m22
);
805 scale
= em_size
/ design
->designUnitsPerEm
;
806 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
807 ascent
= round_metric(design
->ascent
* scale
);
808 descent
= round_metric(design
->descent
* scale
);
811 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
812 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
813 metrics
->ascent
= round_metric(ascent
/ scale
);
814 metrics
->descent
= round_metric(descent
/ scale
);
816 SCALE_METRIC(lineGap
);
817 SCALE_METRIC(capHeight
);
818 SCALE_METRIC(xHeight
);
819 SCALE_METRIC(underlinePosition
);
820 SCALE_METRIC(underlineThickness
);
821 SCALE_METRIC(strikethroughPosition
);
822 SCALE_METRIC(strikethroughThickness
);
823 SCALE_METRIC(glyphBoxLeft
);
824 SCALE_METRIC(glyphBoxTop
);
825 SCALE_METRIC(glyphBoxRight
);
826 SCALE_METRIC(glyphBoxBottom
);
827 SCALE_METRIC(subscriptPositionX
);
828 SCALE_METRIC(subscriptPositionY
);
829 SCALE_METRIC(subscriptSizeX
);
830 SCALE_METRIC(subscriptSizeY
);
831 SCALE_METRIC(superscriptPositionX
);
832 SCALE_METRIC(superscriptPositionY
);
833 SCALE_METRIC(superscriptSizeX
);
834 SCALE_METRIC(superscriptSizeY
);
836 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
842 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace3
*iface
, DWRITE_CARET_METRICS
*metrics
)
844 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
845 TRACE("(%p)->(%p)\n", This
, metrics
);
846 *metrics
= This
->caret
;
849 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace3
*iface
, UINT32 max_count
,
850 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
852 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
854 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
857 if (max_count
&& !ranges
)
860 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
863 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace3
*iface
)
865 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
866 TRACE("(%p)\n", This
);
867 return !!(This
->flags
& FONTFACE_IS_MONOSPACED
);
870 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3
*iface
,
871 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
873 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
876 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
879 FIXME("sideways mode not supported\n");
881 for (i
= 0; i
< glyph_count
; i
++)
882 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], DWRITE_MEASURING_MODE_NATURAL
);
887 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace3
*iface
,
888 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
889 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
891 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
892 DWRITE_MEASURING_MODE mode
;
895 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
896 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
898 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
899 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
904 if (em_size
== 0.0f
) {
905 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
909 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
910 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
912 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
913 for (i
= 0; i
< glyph_count
; i
++) {
914 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
);
915 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
921 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace3
*iface
, UINT32 count
,
922 const UINT16
*indices
, INT32
*adjustments
)
924 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
927 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
929 if (!(indices
|| adjustments
) || !count
)
932 if (!indices
|| count
== 1) {
933 memset(adjustments
, 0, count
*sizeof(INT32
));
937 if (This
->flags
& FONTFACE_HAS_KERN_PAIRS
) {
938 memset(adjustments
, 0, count
*sizeof(INT32
));
942 for (i
= 0; i
< count
-1; i
++)
943 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
944 adjustments
[count
-1] = 0;
949 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace3
*iface
)
951 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
952 TRACE("(%p)\n", This
);
953 return !!(This
->flags
& FONTFACE_HAS_KERN_PAIRS
);
956 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
,
957 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
958 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
960 DWRITE_GRID_FIT_MODE gridfitmode
;
961 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
962 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
965 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace3
*iface
, UINT32 glyph_count
,
966 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
968 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
969 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
973 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3
*iface
)
975 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
976 TRACE("(%p)\n", This
);
977 return !!(This
->flags
& FONTFACE_HAS_VERTICAL_VARIANTS
);
980 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace3
*iface
)
982 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
983 TRACE("(%p)\n", This
);
984 return get_fontface_cpal(This
) && get_fontface_colr(This
);
987 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace3
*iface
)
989 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
990 TRACE("(%p)\n", This
);
991 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
994 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace3
*iface
)
996 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
997 TRACE("(%p)\n", This
);
998 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
1001 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace3
*iface
, UINT32 palette_index
,
1002 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1004 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1005 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
1006 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
1009 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
1010 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1011 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1012 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1014 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1019 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1020 measuringmode
, params
, renderingmode
, gridfitmode
);
1023 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1026 FIXME("sideways mode not supported\n");
1028 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1030 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1031 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1033 IDWriteRenderingParams2
*params2
;
1036 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1038 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1039 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1040 IDWriteRenderingParams2_Release(params2
);
1043 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1046 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1048 ptr
= get_fontface_gasp(This
, &size
);
1049 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1051 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1052 if (emSize
>= emthreshold
)
1053 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1055 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1058 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1059 if (emSize
>= emthreshold
)
1060 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1061 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1062 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1064 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1070 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace3
*iface
, IDWriteFontFaceReference
**ref
)
1072 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1073 FIXME("(%p)->(%p): stub\n", This
, ref
);
1077 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace3
*iface
, DWRITE_PANOSE
*panose
)
1079 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1080 TRACE("(%p)->(%p)\n", This
, panose
);
1081 *panose
= This
->panose
;
1084 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace3
*iface
)
1086 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1087 TRACE("(%p)\n", This
);
1088 return This
->weight
;
1091 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace3
*iface
)
1093 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1094 TRACE("(%p)\n", This
);
1095 return This
->stretch
;
1098 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace3
*iface
)
1100 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1101 TRACE("(%p)\n", This
);
1105 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1107 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1108 FIXME("(%p)->(%p): stub\n", This
, names
);
1112 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1114 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1115 FIXME("(%p)->(%p): stub\n", This
, names
);
1119 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace3
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1120 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1122 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1123 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1127 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace3
*iface
, UINT32 ch
)
1129 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1133 TRACE("(%p)->(0x%08x)\n", This
, ch
);
1136 hr
= IDWriteFontFace3_GetGlyphIndices(iface
, &ch
, 1, &index
);
1143 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT dpiX
, FLOAT dpiY
,
1144 DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1145 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1147 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1152 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1153 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1156 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1159 FIXME("sideways mode not supported\n");
1161 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1163 *rendering_mode
= DWRITE_RENDERING_MODE_DEFAULT
;
1164 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1166 IDWriteRenderingParams3
*params3
;
1169 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams3
, (void**)¶ms3
);
1171 *rendering_mode
= IDWriteRenderingParams3_GetRenderingMode1(params3
);
1172 *gridfit_mode
= IDWriteRenderingParams3_GetGridFitMode(params3
);
1173 IDWriteRenderingParams3_Release(params3
);
1176 *rendering_mode
= IDWriteRenderingParams_GetRenderingMode(params
);
1179 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1181 ptr
= get_fontface_gasp(This
, &size
);
1182 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1184 if (*rendering_mode
== DWRITE_RENDERING_MODE1_DEFAULT
) {
1185 if (emSize
>= emthreshold
)
1186 *rendering_mode
= DWRITE_RENDERING_MODE1_OUTLINE
;
1188 *rendering_mode
= fontface_renderingmode_from_measuringmode(measuring_mode
, emSize
, gasp
);
1191 if (*gridfit_mode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1192 if (emSize
>= emthreshold
)
1193 *gridfit_mode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1194 else if (measuring_mode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1195 *gridfit_mode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1197 *gridfit_mode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1203 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace3
*iface
, UINT32 ch
)
1205 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1206 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1210 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace3
*iface
, UINT16 glyph
)
1212 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1213 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1217 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace3
*iface
, WCHAR
const *text
,
1218 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1220 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1221 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1225 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace3
*iface
, UINT16
const *glyphs
,
1226 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1228 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1229 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1233 static const IDWriteFontFace3Vtbl dwritefontfacevtbl
= {
1234 dwritefontface_QueryInterface
,
1235 dwritefontface_AddRef
,
1236 dwritefontface_Release
,
1237 dwritefontface_GetType
,
1238 dwritefontface_GetFiles
,
1239 dwritefontface_GetIndex
,
1240 dwritefontface_GetSimulations
,
1241 dwritefontface_IsSymbolFont
,
1242 dwritefontface_GetMetrics
,
1243 dwritefontface_GetGlyphCount
,
1244 dwritefontface_GetDesignGlyphMetrics
,
1245 dwritefontface_GetGlyphIndices
,
1246 dwritefontface_TryGetFontTable
,
1247 dwritefontface_ReleaseFontTable
,
1248 dwritefontface_GetGlyphRunOutline
,
1249 dwritefontface_GetRecommendedRenderingMode
,
1250 dwritefontface_GetGdiCompatibleMetrics
,
1251 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1252 dwritefontface1_GetMetrics
,
1253 dwritefontface1_GetGdiCompatibleMetrics
,
1254 dwritefontface1_GetCaretMetrics
,
1255 dwritefontface1_GetUnicodeRanges
,
1256 dwritefontface1_IsMonospacedFont
,
1257 dwritefontface1_GetDesignGlyphAdvances
,
1258 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1259 dwritefontface1_GetKerningPairAdjustments
,
1260 dwritefontface1_HasKerningPairs
,
1261 dwritefontface1_GetRecommendedRenderingMode
,
1262 dwritefontface1_GetVerticalGlyphVariants
,
1263 dwritefontface1_HasVerticalGlyphVariants
,
1264 dwritefontface2_IsColorFont
,
1265 dwritefontface2_GetColorPaletteCount
,
1266 dwritefontface2_GetPaletteEntryCount
,
1267 dwritefontface2_GetPaletteEntries
,
1268 dwritefontface2_GetRecommendedRenderingMode
,
1269 dwritefontface3_GetFontFaceReference
,
1270 dwritefontface3_GetPanose
,
1271 dwritefontface3_GetWeight
,
1272 dwritefontface3_GetStretch
,
1273 dwritefontface3_GetStyle
,
1274 dwritefontface3_GetFamilyNames
,
1275 dwritefontface3_GetFaceNames
,
1276 dwritefontface3_GetInformationalStrings
,
1277 dwritefontface3_HasCharacter
,
1278 dwritefontface3_GetRecommendedRenderingMode
,
1279 dwritefontface3_IsCharacterLocal
,
1280 dwritefontface3_IsGlyphLocal
,
1281 dwritefontface3_AreCharactersLocal
,
1282 dwritefontface3_AreGlyphsLocal
1285 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace3
**fontface
)
1287 struct dwrite_font_data
*data
= font
->data
;
1288 struct fontface_desc desc
;
1289 struct list
*cached_list
;
1294 hr
= factory_get_cached_fontface(data
->factory
, &data
->file
, data
->face_index
,
1295 font
->data
->simulations
, (IDWriteFontFace
**)fontface
, &cached_list
);
1299 desc
.factory
= data
->factory
;
1300 desc
.face_type
= data
->face_type
;
1301 desc
.files
= &data
->file
;
1302 desc
.files_number
= 1;
1303 desc
.index
= data
->face_index
;
1304 desc
.simulations
= data
->simulations
;
1305 desc
.font_data
= data
;
1306 hr
= create_fontface(&desc
, fontface
);
1310 factory_cache_fontface(cached_list
, *fontface
);
1315 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1317 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1319 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1321 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1322 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1323 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1324 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1325 IsEqualIID(riid
, &IID_IUnknown
))
1328 IDWriteFont3_AddRef(iface
);
1333 return E_NOINTERFACE
;
1336 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1338 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1339 ULONG ref
= InterlockedIncrement(&This
->ref
);
1340 TRACE("(%p)->(%d)\n", This
, ref
);
1344 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1346 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1347 ULONG ref
= InterlockedDecrement(&This
->ref
);
1349 TRACE("(%p)->(%d)\n", This
, ref
);
1352 IDWriteFontFamily1_Release(This
->family
);
1353 release_font_data(This
->data
);
1360 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1362 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1363 TRACE("(%p)->(%p)\n", This
, family
);
1365 *family
= (IDWriteFontFamily
*)This
->family
;
1366 IDWriteFontFamily_AddRef(*family
);
1370 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1372 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1373 TRACE("(%p)\n", This
);
1374 return This
->data
->weight
;
1377 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1379 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1380 TRACE("(%p)\n", This
);
1381 return This
->data
->stretch
;
1384 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1386 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1387 TRACE("(%p)\n", This
);
1391 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1393 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1394 IDWriteFontFace3
*fontface
;
1397 TRACE("(%p)\n", This
);
1399 hr
= get_fontface_from_font(This
, &fontface
);
1403 return IDWriteFontFace3_IsSymbolFont(fontface
);
1406 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1408 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1409 TRACE("(%p)->(%p)\n", This
, names
);
1410 return clone_localizedstring(This
->data
->names
, names
);
1413 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1414 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1416 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1417 struct dwrite_font_data
*data
= This
->data
;
1420 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1425 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1428 if (!data
->info_strings
[stringid
]) {
1429 IDWriteFontFace3
*fontface
;
1430 const void *table_data
;
1435 hr
= get_fontface_from_font(This
, &fontface
);
1439 table_exists
= FALSE
;
1440 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1441 if (FAILED(hr
) || !table_exists
)
1442 WARN("no NAME table found.\n");
1445 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1446 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1448 IDWriteFontFace3_ReleaseFontTable(fontface
, context
);
1452 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1460 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1462 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1463 TRACE("(%p)\n", This
);
1464 return This
->data
->simulations
;
1467 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1469 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1471 TRACE("(%p)->(%p)\n", This
, metrics
);
1472 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1475 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 value
, BOOL
*exists
)
1477 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1478 IDWriteFontFace3
*fontface
;
1482 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1486 hr
= get_fontface_from_font(This
, &fontface
);
1491 hr
= IDWriteFontFace3_GetGlyphIndices(fontface
, &value
, 1, &index
);
1495 *exists
= index
!= 0;
1499 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**fontface
)
1501 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1502 TRACE("(%p)->(%p)\n", This
, fontface
);
1503 return IDWriteFont3_CreateFontFace(iface
, (IDWriteFontFace3
**)fontface
);
1506 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1508 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1509 TRACE("(%p)->(%p)\n", This
, metrics
);
1510 *metrics
= This
->data
->metrics
;
1513 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1515 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1516 TRACE("(%p)->(%p)\n", This
, panose
);
1517 *panose
= This
->data
->panose
;
1520 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1522 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1523 IDWriteFontFace3
*fontface
;
1526 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1528 hr
= get_fontface_from_font(This
, &fontface
);
1532 return IDWriteFontFace3_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1535 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1537 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1538 IDWriteFontFace3
*fontface
;
1541 TRACE("(%p)\n", This
);
1543 hr
= get_fontface_from_font(This
, &fontface
);
1547 return IDWriteFontFace3_IsMonospacedFont(fontface
);
1550 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1552 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1553 IDWriteFontFace3
*fontface
;
1556 TRACE("(%p)\n", This
);
1558 hr
= get_fontface_from_font(This
, &fontface
);
1562 return IDWriteFontFace3_IsColorFont(fontface
);
1565 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1567 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1570 TRACE("(%p)->(%p)\n", This
, fontface
);
1572 hr
= get_fontface_from_font(This
, fontface
);
1574 IDWriteFontFace3_AddRef(*fontface
);
1579 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1581 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1582 FIXME("(%p)->(%p): stub\n", This
, font
);
1586 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1588 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1590 TRACE("(%p)->(%p)\n", This
, reference
);
1592 return IDWriteFactory3_CreateFontFaceReference_(This
->data
->factory
, This
->data
->file
, This
->data
->face_index
,
1593 This
->data
->simulations
, reference
);
1596 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1598 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1602 TRACE("(%p)->(0x%x)\n", This
, ch
);
1604 hr
= IDWriteFont_HasCharacter((IDWriteFont
*)iface
, ch
, &ret
);
1605 return hr
== S_OK
&& ret
;
1608 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1610 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1611 FIXME("(%p): stub\n", This
);
1612 return DWRITE_LOCALITY_LOCAL
;
1615 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1616 dwritefont_QueryInterface
,
1619 dwritefont_GetFontFamily
,
1620 dwritefont_GetWeight
,
1621 dwritefont_GetStretch
,
1622 dwritefont_GetStyle
,
1623 dwritefont_IsSymbolFont
,
1624 dwritefont_GetFaceNames
,
1625 dwritefont_GetInformationalStrings
,
1626 dwritefont_GetSimulations
,
1627 dwritefont_GetMetrics
,
1628 dwritefont_HasCharacter
,
1629 dwritefont_CreateFontFace
,
1630 dwritefont1_GetMetrics
,
1631 dwritefont1_GetPanose
,
1632 dwritefont1_GetUnicodeRanges
,
1633 dwritefont1_IsMonospacedFont
,
1634 dwritefont2_IsColorFont
,
1635 dwritefont3_CreateFontFace
,
1637 dwritefont3_GetFontFaceReference
,
1638 dwritefont3_HasCharacter
,
1639 dwritefont3_GetLocality
1642 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily1
*family
, IDWriteFont3
**font
)
1644 struct dwrite_font
*This
;
1647 This
= heap_alloc(sizeof(struct dwrite_font
));
1648 if (!This
) return E_OUTOFMEMORY
;
1650 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1652 This
->family
= family
;
1653 IDWriteFontFamily1_AddRef(family
);
1654 This
->style
= data
->style
;
1656 InterlockedIncrement(&This
->data
->ref
);
1658 *font
= &This
->IDWriteFont3_iface
;
1663 /* IDWriteFontList1 */
1664 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList1
*iface
, REFIID riid
, void **obj
)
1666 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1668 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1670 if (IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1671 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1672 IsEqualIID(riid
, &IID_IUnknown
))
1675 IDWriteFontList1_AddRef(iface
);
1680 return E_NOINTERFACE
;
1683 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList1
*iface
)
1685 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1686 ULONG ref
= InterlockedIncrement(&This
->ref
);
1687 TRACE("(%p)->(%d)\n", This
, ref
);
1691 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList1
*iface
)
1693 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1694 ULONG ref
= InterlockedDecrement(&This
->ref
);
1696 TRACE("(%p)->(%d)\n", This
, ref
);
1701 for (i
= 0; i
< This
->font_count
; i
++)
1702 release_font_data(This
->fonts
[i
]);
1703 IDWriteFontFamily1_Release(This
->family
);
1704 heap_free(This
->fonts
);
1711 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList1
*iface
, IDWriteFontCollection
**collection
)
1713 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1714 return IDWriteFontFamily1_GetFontCollection(This
->family
, collection
);
1717 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList1
*iface
)
1719 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1720 TRACE("(%p)\n", This
);
1721 return This
->font_count
;
1724 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont
**font
)
1726 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1728 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1732 if (This
->font_count
== 0)
1735 if (index
>= This
->font_count
)
1736 return E_INVALIDARG
;
1738 return create_font(This
->fonts
[index
], This
->family
, (IDWriteFont3
**)font
);
1741 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList1
*iface
, UINT32 index
)
1743 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1745 FIXME("(%p)->(%u): stub\n", This
, index
);
1747 return DWRITE_LOCALITY_LOCAL
;
1750 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1752 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1754 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1758 if (This
->font_count
== 0)
1761 if (index
>= This
->font_count
)
1764 return create_font(This
->fonts
[index
], This
->family
, font
);
1767 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList1
*iface
, UINT32 index
,
1768 IDWriteFontFaceReference
**reference
)
1770 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1774 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
1778 hr
= IDWriteFontList1_GetFont(iface
, index
, &font
);
1782 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
1783 IDWriteFont3_Release(font
);
1788 static const IDWriteFontList1Vtbl dwritefontlistvtbl
= {
1789 dwritefontlist_QueryInterface
,
1790 dwritefontlist_AddRef
,
1791 dwritefontlist_Release
,
1792 dwritefontlist_GetFontCollection
,
1793 dwritefontlist_GetFontCount
,
1794 dwritefontlist_GetFont
,
1795 dwritefontlist1_GetFontLocality
,
1796 dwritefontlist1_GetFont
,
1797 dwritefontlist1_GetFontFaceReference
1800 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1802 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1804 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1806 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1807 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1808 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1809 IsEqualIID(riid
, &IID_IUnknown
))
1812 IDWriteFontFamily1_AddRef(iface
);
1817 return E_NOINTERFACE
;
1820 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1822 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1823 ULONG ref
= InterlockedIncrement(&This
->ref
);
1824 TRACE("(%p)->(%d)\n", This
, ref
);
1828 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1830 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1831 ULONG ref
= InterlockedDecrement(&This
->ref
);
1833 TRACE("(%p)->(%d)\n", This
, ref
);
1837 IDWriteFontCollection1_Release(This
->collection
);
1838 release_fontfamily_data(This
->data
);
1845 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
1847 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1849 TRACE("(%p)->(%p)\n", This
, collection
);
1851 *collection
= (IDWriteFontCollection
*)This
->collection
;
1852 IDWriteFontCollection_AddRef(*collection
);
1856 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
1858 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1859 TRACE("(%p)\n", This
);
1860 return This
->data
->font_count
;
1863 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
1865 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1867 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1871 if (This
->data
->font_count
== 0)
1874 if (index
>= This
->data
->font_count
)
1875 return E_INVALIDARG
;
1877 return create_font(This
->data
->fonts
[index
], iface
, (IDWriteFont3
**)font
);
1880 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
1882 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1883 return clone_localizedstring(This
->data
->familyname
, names
);
1886 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
1887 const struct dwrite_font_propvec
*req
)
1889 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
1890 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
1891 FLOAT cur_req_prod
, next_req_prod
;
1893 if (next_to_req
< cur_to_req
)
1896 if (next_to_req
> cur_to_req
)
1899 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
1900 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
1902 if (next_req_prod
> cur_req_prod
)
1905 if (next_req_prod
< cur_req_prod
)
1908 if (next
->stretch
> cur
->stretch
)
1910 if (next
->stretch
< cur
->stretch
)
1913 if (next
->style
> cur
->style
)
1915 if (next
->style
< cur
->style
)
1918 if (next
->weight
> cur
->weight
)
1920 if (next
->weight
< cur
->weight
)
1923 /* full match, no reason to prefer new variant */
1927 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1928 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1930 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1931 struct dwrite_font_propvec req
;
1932 struct dwrite_font_data
*match
;
1935 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1937 if (This
->data
->font_count
== 0) {
1939 return DWRITE_E_NOFONT
;
1942 init_font_prop_vec(weight
, stretch
, style
, &req
);
1943 match
= This
->data
->fonts
[0];
1945 for (i
= 1; i
< This
->data
->font_count
; i
++) {
1946 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &match
->propvec
, &req
))
1947 match
= This
->data
->fonts
[i
];
1950 return create_font(match
, iface
, (IDWriteFont3
**)font
);
1953 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
1955 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
1957 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1960 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
1962 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1965 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
1967 UINT32 b
= fonts
->font_count
- 1, j
, t
;
1972 for (j
= 0; j
< b
; j
++) {
1973 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
1974 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
1975 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
1976 fonts
->fonts
[j
+1] = s
;
1987 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1988 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
1990 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1991 matching_filter_func func
= NULL
;
1992 struct dwrite_font_propvec req
;
1993 struct dwrite_fontlist
*fonts
;
1996 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
2000 fonts
= heap_alloc(sizeof(*fonts
));
2002 return E_OUTOFMEMORY
;
2004 /* Allocate as many as family has, not all of them will be necessary used. */
2005 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
2006 if (!fonts
->fonts
) {
2008 return E_OUTOFMEMORY
;
2011 fonts
->IDWriteFontList1_iface
.lpVtbl
= &dwritefontlistvtbl
;
2013 fonts
->family
= iface
;
2014 IDWriteFontFamily1_AddRef(fonts
->family
);
2015 fonts
->font_count
= 0;
2017 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
2018 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
2019 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
2020 func
= is_font_acceptable_for_normal
;
2022 else /* requested oblique or italic */ {
2023 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
2024 func
= is_font_acceptable_for_oblique_italic
;
2027 for (i
= 0; i
< This
->data
->font_count
; i
++) {
2028 if (!func
|| func(This
->data
->fonts
[i
])) {
2029 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
2030 InterlockedIncrement(&This
->data
->fonts
[i
]->ref
);
2031 fonts
->font_count
++;
2035 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
2036 init_font_prop_vec(weight
, stretch
, style
, &req
);
2037 matchingfonts_sort(fonts
, &req
);
2039 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList1_iface
;
2043 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
2045 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2047 FIXME("(%p)->(%u): stub\n", This
, index
);
2049 return DWRITE_LOCALITY_LOCAL
;
2052 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
2054 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2056 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
2060 if (This
->data
->font_count
== 0)
2063 if (index
>= This
->data
->font_count
)
2066 return create_font(This
->data
->fonts
[index
], iface
, font
);
2069 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
2070 IDWriteFontFaceReference
**reference
)
2072 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
2076 TRACE("(%p)->(%u %p)\n", This
, index
, reference
);
2080 hr
= IDWriteFontFamily1_GetFont(iface
, index
, &font
);
2084 hr
= IDWriteFont3_GetFontFaceReference(font
, reference
);
2085 IDWriteFont3_Release(font
);
2090 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
2091 dwritefontfamily_QueryInterface
,
2092 dwritefontfamily_AddRef
,
2093 dwritefontfamily_Release
,
2094 dwritefontfamily_GetFontCollection
,
2095 dwritefontfamily_GetFontCount
,
2096 dwritefontfamily_GetFont
,
2097 dwritefontfamily_GetFamilyNames
,
2098 dwritefontfamily_GetFirstMatchingFont
,
2099 dwritefontfamily_GetMatchingFonts
,
2100 dwritefontfamily1_GetFontLocality
,
2101 dwritefontfamily1_GetFont
,
2102 dwritefontfamily1_GetFontFaceReference
2105 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection1
*collection
, IDWriteFontFamily1
**family
)
2107 struct dwrite_fontfamily
*This
;
2111 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
2112 if (!This
) return E_OUTOFMEMORY
;
2114 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
2116 This
->collection
= collection
;
2117 IDWriteFontCollection1_AddRef(collection
);
2119 InterlockedIncrement(&This
->data
->ref
);
2121 *family
= &This
->IDWriteFontFamily1_iface
;
2126 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2129 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
2132 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2134 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2135 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2137 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2138 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2139 IsEqualIID(riid
, &IID_IUnknown
))
2142 IDWriteFontCollection1_AddRef(iface
);
2148 if (IsEqualIID(riid
, &IID_issystemcollection
))
2151 return E_NOINTERFACE
;
2154 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2156 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2157 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2159 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2160 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2161 IsEqualIID(riid
, &IID_IUnknown
))
2164 IDWriteFontCollection1_AddRef(iface
);
2170 return E_NOINTERFACE
;
2173 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2175 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2176 ULONG ref
= InterlockedIncrement(&This
->ref
);
2177 TRACE("(%p)->(%d)\n", This
, ref
);
2181 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2184 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2185 ULONG ref
= InterlockedDecrement(&This
->ref
);
2186 TRACE("(%p)->(%d)\n", This
, ref
);
2189 for (i
= 0; i
< This
->family_count
; i
++)
2190 release_fontfamily_data(This
->family_data
[i
]);
2191 heap_free(This
->family_data
);
2198 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2200 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2201 TRACE("(%p)\n", This
);
2202 return This
->family_count
;
2205 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2207 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2209 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2211 if (index
>= This
->family_count
) {
2216 return create_fontfamily(This
->family_data
[index
], iface
, (IDWriteFontFamily1
**)family
);
2219 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2223 for (i
= 0; i
< collection
->family_count
; i
++) {
2224 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2225 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2228 for (j
= 0; j
< count
; j
++) {
2230 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2231 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2239 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2241 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2242 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2243 *index
= collection_find_family(This
, name
);
2244 *exists
= *index
!= ~0u;
2248 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2250 UINT32 left_key_size
, right_key_size
;
2251 const void *left_key
, *right_key
;
2257 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2261 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2265 if (left_key_size
!= right_key_size
)
2268 return !memcmp(left_key
, right_key
, left_key_size
);
2271 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2273 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2274 struct dwrite_fontfamily_data
*found_family
= NULL
;
2275 struct dwrite_font_data
*found_font
= NULL
;
2276 IDWriteFontFamily1
*family
;
2277 UINT32 i
, j
, face_index
;
2278 IDWriteFontFile
*file
;
2281 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2286 return E_INVALIDARG
;
2289 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2292 face_index
= IDWriteFontFace_GetIndex(face
);
2294 for (i
= 0; i
< This
->family_count
; i
++) {
2295 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2296 for (j
= 0; j
< family_data
->font_count
; j
++) {
2297 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2299 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2300 found_font
= font_data
;
2301 found_family
= family_data
;
2308 return DWRITE_E_NOFONT
;
2310 hr
= create_fontfamily(found_family
, iface
, &family
);
2314 hr
= create_font(found_font
, family
, (IDWriteFont3
**)font
);
2315 IDWriteFontFamily1_Release(family
);
2319 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2321 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2323 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2328 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2330 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2332 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2334 if (index
>= This
->family_count
) {
2339 return create_fontfamily(This
->family_data
[index
], iface
, family
);
2342 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2343 dwritefontcollection_QueryInterface
,
2344 dwritefontcollection_AddRef
,
2345 dwritefontcollection_Release
,
2346 dwritefontcollection_GetFontFamilyCount
,
2347 dwritefontcollection_GetFontFamily
,
2348 dwritefontcollection_FindFamilyName
,
2349 dwritefontcollection_GetFontFromFontFace
,
2350 dwritefontcollection1_GetFontSet
,
2351 dwritefontcollection1_GetFontFamily
2354 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2355 dwritesystemfontcollection_QueryInterface
,
2356 dwritefontcollection_AddRef
,
2357 dwritefontcollection_Release
,
2358 dwritefontcollection_GetFontFamilyCount
,
2359 dwritefontcollection_GetFontFamily
,
2360 dwritefontcollection_FindFamilyName
,
2361 dwritefontcollection_GetFontFromFontFace
,
2362 dwritefontcollection1_GetFontSet
,
2363 dwritefontcollection1_GetFontFamily
2366 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2368 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2369 struct dwrite_font_data
**new_list
;
2372 new_alloc
= family_data
->font_alloc
* 2;
2373 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2375 return E_OUTOFMEMORY
;
2376 family_data
->fonts
= new_list
;
2377 family_data
->font_alloc
= new_alloc
;
2380 family_data
->fonts
[family_data
->font_count
] = font_data
;
2381 family_data
->font_count
++;
2382 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2383 family_data
->has_normal_face
= 1;
2384 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2385 family_data
->has_oblique_face
= 1;
2387 family_data
->has_italic_face
= 1;
2391 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2393 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2394 struct dwrite_fontfamily_data
**new_list
;
2397 new_alloc
= collection
->family_alloc
* 2;
2398 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2400 return E_OUTOFMEMORY
;
2402 collection
->family_alloc
= new_alloc
;
2403 collection
->family_data
= new_list
;
2406 collection
->family_data
[collection
->family_count
] = family
;
2407 collection
->family_count
++;
2412 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2414 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2415 collection
->ref
= 1;
2416 collection
->family_count
= 0;
2417 collection
->family_alloc
= is_system
? 30 : 5;
2418 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2419 if (!collection
->family_data
)
2420 return E_OUTOFMEMORY
;
2425 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2427 IDWriteFontFileLoader
*loader
;
2434 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2438 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2442 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2443 IDWriteFontFileLoader_Release(loader
);
2450 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2452 BOOL exists
= FALSE
;
2457 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2458 if (FAILED(hr
) || !exists
)
2461 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2464 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2468 while (isspaceW(*in
))
2472 if (!(len
= strlenW(in
)))
2475 while (isspaceW(in
[len
-1]))
2478 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2487 INT len
; /* token length */
2488 INT fulllen
; /* full length including following separators */
2491 static inline BOOL
is_name_separator_char(WCHAR ch
)
2493 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2496 struct name_pattern
{
2497 const WCHAR
*part1
; /* NULL indicates end of list */
2498 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2501 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2503 const struct name_pattern
*pattern
;
2504 struct name_token
*token
;
2507 while ((pattern
= &patterns
[i
++])->part1
) {
2508 int len_part1
= strlenW(pattern
->part1
);
2509 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2511 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2512 if (len_part2
== 0) {
2513 /* simple case with single part pattern */
2514 if (token
->len
!= len_part1
)
2517 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2518 if (match
) *match
= *token
;
2519 list_remove(&token
->entry
);
2525 struct name_token
*next_token
;
2526 struct list
*next_entry
;
2528 /* pattern parts are stored in reading order, tokens list is reversed */
2529 if (token
->len
< len_part2
)
2532 /* it's possible to have combined string as a token, like ExtraCondensed */
2533 if (token
->len
== len_part1
+ len_part2
) {
2534 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2537 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2540 /* combined string match */
2541 if (match
) *match
= *token
;
2542 list_remove(&token
->entry
);
2547 /* now it's only possible to have two tokens matched to respective pattern parts */
2548 if (token
->len
!= len_part2
)
2551 next_entry
= list_next(tokens
, &token
->entry
);
2553 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2554 if (next_token
->len
!= len_part1
)
2557 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2560 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2563 /* both parts matched, remove tokens */
2565 match
->ptr
= next_token
->ptr
;
2566 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2568 list_remove(&token
->entry
);
2569 list_remove(&next_token
->entry
);
2570 heap_free(next_token
);
2585 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2587 static const WCHAR itaW
[] = {'i','t','a',0};
2588 static const WCHAR italW
[] = {'i','t','a','l',0};
2589 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2590 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2592 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2593 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2594 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2595 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2597 static const struct name_pattern italic_patterns
[] = {
2606 static const struct name_pattern oblique_patterns
[] = {
2615 /* italic patterns first */
2616 if (match_pattern_list(tokens
, italic_patterns
, match
))
2617 return DWRITE_FONT_STYLE_ITALIC
;
2619 /* oblique patterns */
2620 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2621 return DWRITE_FONT_STYLE_OBLIQUE
;
2626 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2627 struct name_token
*match
)
2629 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2630 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2631 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2632 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2633 static const WCHAR wideW
[] = {'w','i','d','e',0};
2634 static const WCHAR condW
[] = {'c','o','n','d',0};
2636 static const struct name_pattern ultracondensed_patterns
[] = {
2637 { extraW
, compressedW
},
2638 { extW
, compressedW
},
2639 { ultraW
, compressedW
},
2640 { ultraW
, condensedW
},
2645 static const struct name_pattern extracondensed_patterns
[] = {
2647 { extraW
, condensedW
},
2648 { extW
, condensedW
},
2654 static const struct name_pattern semicondensed_patterns
[] = {
2657 { semiW
, condensedW
},
2662 static const struct name_pattern semiexpanded_patterns
[] = {
2664 { semiW
, expandedW
},
2665 { semiW
, extendedW
},
2669 static const struct name_pattern extraexpanded_patterns
[] = {
2670 { extraW
, expandedW
},
2671 { extW
, expandedW
},
2672 { extraW
, extendedW
},
2673 { extW
, extendedW
},
2677 static const struct name_pattern ultraexpanded_patterns
[] = {
2678 { ultraW
, expandedW
},
2679 { ultraW
, extendedW
},
2683 static const struct name_pattern condensed_patterns
[] = {
2689 static const struct name_pattern expanded_patterns
[] = {
2695 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2696 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2698 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2699 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2701 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2702 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2704 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2705 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2707 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2708 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2710 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2711 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2713 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2714 return DWRITE_FONT_STRETCH_CONDENSED
;
2716 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2717 return DWRITE_FONT_STRETCH_EXPANDED
;
2722 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2723 struct name_token
*match
)
2725 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2726 static const WCHAR nordW
[] = {'n','o','r','d',0};
2728 static const struct name_pattern thin_patterns
[] = {
2735 static const struct name_pattern extralight_patterns
[] = {
2742 static const struct name_pattern semilight_patterns
[] = {
2747 static const struct name_pattern demibold_patterns
[] = {
2753 static const struct name_pattern extrabold_patterns
[] = {
2760 static const struct name_pattern extrablack_patterns
[] = {
2767 static const struct name_pattern bold_patterns
[] = {
2772 static const struct name_pattern thin2_patterns
[] = {
2777 static const struct name_pattern light_patterns
[] = {
2782 static const struct name_pattern medium_patterns
[] = {
2787 static const struct name_pattern black_patterns
[] = {
2794 static const struct name_pattern demibold2_patterns
[] = {
2799 static const struct name_pattern extrabold2_patterns
[] = {
2804 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2805 matching pattern. */
2807 if (match_pattern_list(tokens
, thin_patterns
, match
))
2808 return DWRITE_FONT_WEIGHT_THIN
;
2810 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2811 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2813 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2814 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2816 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2817 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2819 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2820 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2822 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2823 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2825 if (match_pattern_list(tokens
, bold_patterns
, match
))
2826 return DWRITE_FONT_WEIGHT_BOLD
;
2828 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2829 return DWRITE_FONT_WEIGHT_THIN
;
2831 if (match_pattern_list(tokens
, light_patterns
, match
))
2832 return DWRITE_FONT_WEIGHT_LIGHT
;
2834 if (match_pattern_list(tokens
, medium_patterns
, match
))
2835 return DWRITE_FONT_WEIGHT_MEDIUM
;
2837 if (match_pattern_list(tokens
, black_patterns
, match
))
2838 return DWRITE_FONT_WEIGHT_BLACK
;
2840 if (match_pattern_list(tokens
, black_patterns
, match
))
2841 return DWRITE_FONT_WEIGHT_BLACK
;
2843 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2844 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2846 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2847 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2849 /* FIXME: use abbreviated names to extract weight */
2854 struct knownweight_entry
{
2856 DWRITE_FONT_WEIGHT weight
;
2859 static int compare_knownweights(const void *a
, const void* b
)
2861 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2862 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2865 if (target
> entry
->weight
)
2867 else if (target
< entry
->weight
)
2873 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2875 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2876 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2877 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2878 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2879 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2880 const struct knownweight_entry
*ptr
;
2882 static const struct knownweight_entry knownweights
[] = {
2883 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
2884 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
2885 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
2886 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
2887 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
2888 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
2889 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
2890 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
2891 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
2892 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
2895 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
2896 compare_knownweights
);
2902 strcpyW(nameW
, ptr
->nameW
);
2906 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
2908 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
2909 strW
[name
->len
] = 0;
2912 /* Modifies facenameW string, and returns pointer to regular term that was removed */
2913 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
2915 static const WCHAR bookW
[] = {'B','o','o','k',0};
2916 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
2917 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
2918 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
2919 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
2921 static const WCHAR
*regular_patterns
[] = {
2930 const WCHAR
*regular_ptr
= NULL
, *ptr
;
2934 len
= strlenW(facenameW
);
2936 /* remove rightmost regular variant from face name */
2937 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
2938 int pattern_len
= strlenW(ptr
);
2941 if (pattern_len
> len
)
2944 src
= facenameW
+ len
- pattern_len
;
2945 while (src
>= facenameW
) {
2946 if (!strncmpiW(src
, ptr
, pattern_len
)) {
2947 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
2948 len
= strlenW(facenameW
);
2960 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
2968 struct name_token
*token
= heap_alloc(sizeof(*token
));
2973 while (*ptr
&& !is_name_separator_char(*ptr
)) {
2979 /* skip separators */
2980 while (is_name_separator_char(*ptr
)) {
2985 list_add_head(tokens
, &token
->entry
);
2989 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
2991 struct name_token
*token
, *token2
;
2992 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
2995 list_remove(&token
->entry
);
2997 /* don't include last separator */
2998 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
2999 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
3007 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
3009 struct name_token stretch_name
, weight_name
, style_name
;
3010 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
3011 WCHAR weightW
[32], stretchW
[32], styleW
[32];
3012 const WCHAR
*regular_ptr
= NULL
;
3013 DWRITE_FONT_STRETCH stretch
;
3014 DWRITE_FONT_WEIGHT weight
;
3018 /* remove leading and trailing spaces from family and face name */
3019 trim_spaces(familyW
, familynameW
);
3020 len
= trim_spaces(faceW
, facenameW
);
3022 /* remove rightmost regular variant from face name */
3023 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
3025 /* append face name to family name, FIXME check if face name is a substring of family name */
3027 strcatW(familynameW
, spaceW
);
3028 strcatW(familynameW
, facenameW
);
3031 /* tokenize with " .-_" */
3032 fontname_tokenize(&tokens
, familynameW
);
3034 /* extract and resolve style */
3035 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
3037 /* extract stretch */
3038 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
3040 /* extract weight */
3041 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
3043 /* resolve weight */
3044 if (weight
!= font
->weight
) {
3045 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
3046 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
3047 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
3048 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
3049 !(abs(weight
- font
->weight
) <= 150 &&
3050 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
3051 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
3052 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
3054 font
->weight
= weight
;
3058 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
3059 it's leaning in opposite direction from normal comparing to specified stretch or if specified
3060 stretch itself is normal (extracted stretch is never normal). */
3061 if (stretch
!= font
->stretch
) {
3062 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
3063 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
3064 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
3066 font
->stretch
= stretch
;
3070 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
3072 /* get final combined string from what's left in token list, list is released */
3073 fontname_tokens_to_str(&tokens
, finalW
);
3075 if (!strcmpW(familyW
, finalW
))
3078 /* construct face name */
3079 strcpyW(familyW
, finalW
);
3081 /* resolved weight name */
3082 if (weight_name
.ptr
)
3083 font_name_token_to_str(&weight_name
, weightW
);
3084 /* ignore normal weight */
3085 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
3087 /* for known weight values use appropriate names */
3088 else if (is_known_weight_value(font
->weight
, weightW
)) {
3090 /* use Wnnn format as a fallback in case weight is not one of known values */
3092 static const WCHAR fmtW
[] = {'W','%','d',0};
3093 sprintfW(weightW
, fmtW
, font
->weight
);
3096 /* resolved stretch name */
3097 if (stretch_name
.ptr
)
3098 font_name_token_to_str(&stretch_name
, stretchW
);
3099 /* ignore normal stretch */
3100 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
3102 /* use predefined stretch names */
3104 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3105 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3106 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3107 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3108 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3109 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3111 static const WCHAR
*stretchnamesW
[] = {
3112 NULL
, /* DWRITE_FONT_STRETCH_UNDEFINED */
3117 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3123 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3126 /* resolved style name */
3128 font_name_token_to_str(&style_name
, styleW
);
3129 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3131 /* use predefined names */
3133 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3134 strcpyW(styleW
, italicW
);
3136 strcpyW(styleW
, obliqueW
);
3139 /* use Regular match if it was found initially */
3140 if (!*weightW
&& !*stretchW
&& !*styleW
)
3141 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3145 strcpyW(faceW
, stretchW
);
3148 strcatW(faceW
, spaceW
);
3149 strcatW(faceW
, weightW
);
3153 strcatW(faceW
, spaceW
);
3154 strcatW(faceW
, styleW
);
3158 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3162 static HRESULT
init_font_data(const struct fontface_desc
*desc
, IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
3164 struct file_stream_desc stream_desc
;
3165 struct dwrite_font_props props
;
3166 struct dwrite_font_data
*data
;
3167 IDWriteFontFileStream
*stream
;
3168 WCHAR familyW
[255], faceW
[255];
3172 data
= heap_alloc_zero(sizeof(*data
));
3174 return E_OUTOFMEMORY
;
3176 hr
= get_filestream_from_file(desc
->files
[0], &stream
);
3183 data
->factory
= desc
->factory
;
3184 data
->file
= desc
->files
[0];
3185 data
->face_index
= desc
->index
;
3186 data
->face_type
= desc
->face_type
;
3187 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3188 data
->bold_sim_tested
= 0;
3189 data
->oblique_sim_tested
= 0;
3190 IDWriteFontFile_AddRef(data
->file
);
3191 IDWriteFactory3_AddRef(data
->factory
);
3193 stream_desc
.stream
= stream
;
3194 stream_desc
.face_type
= desc
->face_type
;
3195 stream_desc
.face_index
= desc
->index
;
3196 opentype_get_font_properties(&stream_desc
, &props
);
3197 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3198 opentype_get_font_facename(&stream_desc
, &data
->names
);
3200 /* get family name from font file */
3201 hr
= opentype_get_font_familyname(&stream_desc
, family_name
);
3202 IDWriteFontFileStream_Release(stream
);
3204 WARN("unable to get family name from font\n");
3205 release_font_data(data
);
3209 data
->style
= props
.style
;
3210 data
->stretch
= props
.stretch
;
3211 data
->weight
= props
.weight
;
3212 data
->panose
= props
.panose
;
3214 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3215 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3216 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3217 set_en_localizedstring(*family_name
, familyW
);
3218 set_en_localizedstring(data
->names
, faceW
);
3221 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3227 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
, const WCHAR
*facenameW
,
3228 struct dwrite_font_data
**ret
)
3230 struct dwrite_font_data
*data
;
3233 data
= heap_alloc_zero(sizeof(*data
));
3235 return E_OUTOFMEMORY
;
3239 data
->simulations
|= sim
;
3240 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3241 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3242 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3243 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3244 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3246 IDWriteFactory3_AddRef(data
->factory
);
3247 IDWriteFontFile_AddRef(data
->file
);
3249 create_localizedstrings(&data
->names
);
3250 add_localizedstring(data
->names
, enusW
, facenameW
);
3252 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3258 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3260 struct dwrite_fontfamily_data
*data
;
3262 data
= heap_alloc(sizeof(*data
));
3264 return E_OUTOFMEMORY
;
3267 data
->font_count
= 0;
3268 data
->font_alloc
= 2;
3269 data
->has_normal_face
= 0;
3270 data
->has_oblique_face
= 0;
3271 data
->has_italic_face
= 0;
3273 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3276 return E_OUTOFMEMORY
;
3279 data
->familyname
= familyname
;
3280 IDWriteLocalizedStrings_AddRef(familyname
);
3286 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3288 UINT32 i
, j
, heaviest
;
3290 for (i
= 0; i
< family
->font_count
; i
++) {
3291 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3294 if (family
->fonts
[i
]->bold_sim_tested
)
3297 family
->fonts
[i
]->bold_sim_tested
= 1;
3298 for (j
= i
; j
< family
->font_count
; j
++) {
3299 if (family
->fonts
[j
]->bold_sim_tested
)
3302 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3303 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3304 if (family
->fonts
[j
]->weight
> weight
) {
3305 weight
= family
->fonts
[j
]->weight
;
3308 family
->fonts
[j
]->bold_sim_tested
= 1;
3312 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3313 static const struct name_pattern weightsim_patterns
[] = {
3328 WCHAR facenameW
[255], initialW
[255];
3329 struct dwrite_font_data
*boldface
;
3332 /* add Bold simulation based on heaviest face data */
3334 /* Simulated face name should only contain Bold as weight term,
3335 so remove existing regular and weight terms. */
3336 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3337 facename_remove_regular_term(initialW
, -1);
3339 /* remove current weight pattern */
3340 fontname_tokenize(&tokens
, initialW
);
3341 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3342 fontname_tokens_to_str(&tokens
, facenameW
);
3344 /* Bold suffix for new name */
3346 strcatW(facenameW
, spaceW
);
3347 strcatW(facenameW
, boldW
);
3349 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3350 boldface
->bold_sim_tested
= 1;
3351 fontfamily_add_font(family
, boldface
);
3357 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3361 for (i
= 0; i
< family
->font_count
; i
++) {
3362 UINT32 regular
= ~0u, oblique
= ~0u;
3363 struct dwrite_font_data
*obliqueface
;
3364 WCHAR facenameW
[255];
3366 if (family
->fonts
[i
]->oblique_sim_tested
)
3369 family
->fonts
[i
]->oblique_sim_tested
= 1;
3370 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3372 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3375 /* find regular style with same weight/stretch values */
3376 for (j
= i
; j
< family
->font_count
; j
++) {
3377 if (family
->fonts
[j
]->oblique_sim_tested
)
3380 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3381 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3383 family
->fonts
[j
]->oblique_sim_tested
= 1;
3384 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3387 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3391 if (regular
!= ~0u && oblique
!= ~0u)
3395 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3399 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3403 /* add oblique simulation based on this regular face */
3405 /* remove regular term if any, append 'Oblique' */
3406 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3407 facename_remove_regular_term(facenameW
, -1);
3410 strcatW(facenameW
, spaceW
);
3411 strcatW(facenameW
, obliqueW
);
3413 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3414 obliqueface
->oblique_sim_tested
= 1;
3415 fontfamily_add_font(family
, obliqueface
);
3420 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3421 const WCHAR
*replacement_name
)
3423 UINT32 i
= collection_find_family(collection
, replacement_name
);
3424 struct dwrite_fontfamily_data
*target
;
3425 IDWriteLocalizedStrings
*strings
;
3428 /* replacement does not exist */
3432 hr
= create_localizedstrings(&strings
);
3436 /* add a new family with target name, reuse font data from replacement */
3437 add_localizedstring(strings
, enusW
, target_name
);
3438 hr
= init_fontfamily_data(strings
, &target
);
3440 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3443 for (i
= 0; i
< replacement
->font_count
; i
++)
3444 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3446 fontcollection_add_family(collection
, target
);
3447 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3448 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3450 IDWriteLocalizedStrings_Release(strings
);
3454 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3455 system font collections. */
3456 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3458 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3463 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3466 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3471 max_namelen
++; /* returned value doesn't include room for '\0' */
3472 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3473 data
= heap_alloc(max_datalen
);
3475 datalen
= max_datalen
;
3476 namelen
= max_namelen
;
3477 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3478 if (collection_find_family(collection
, name
) == ~0u) {
3479 if (type
== REG_MULTI_SZ
) {
3480 WCHAR
*replacement
= data
;
3481 while (*replacement
) {
3482 if (fontcollection_add_replacement(collection
, name
, replacement
))
3484 replacement
+= strlenW(replacement
) + 1;
3487 else if (type
== REG_SZ
)
3488 fontcollection_add_replacement(collection
, name
, data
);
3491 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3493 datalen
= max_datalen
;
3494 namelen
= max_namelen
;
3502 HRESULT
create_font_collection(IDWriteFactory3
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
,
3503 IDWriteFontCollection1
**ret
)
3505 struct fontfile_enum
{
3507 IDWriteFontFile
*file
;
3509 struct fontfile_enum
*fileenum
, *fileenum2
;
3510 struct dwrite_fontcollection
*collection
;
3511 struct list scannedfiles
;
3512 BOOL current
= FALSE
;
3518 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3519 if (!collection
) return E_OUTOFMEMORY
;
3521 hr
= init_font_collection(collection
, is_system
);
3523 heap_free(collection
);
3527 *ret
= &collection
->IDWriteFontCollection1_iface
;
3529 TRACE("building font collection:\n");
3531 list_init(&scannedfiles
);
3532 while (hr
== S_OK
) {
3533 DWRITE_FONT_FACE_TYPE face_type
;
3534 DWRITE_FONT_FILE_TYPE file_type
;
3535 BOOL supported
, same
= FALSE
;
3536 IDWriteFontFile
*file
;
3540 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3541 if (FAILED(hr
) || !current
)
3544 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3548 /* check if we've scanned this file already */
3549 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3550 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3555 IDWriteFontFile_Release(file
);
3559 /* failed font files are skipped */
3560 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3561 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3562 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3563 IDWriteFontFile_Release(file
);
3568 /* add to scanned list */
3569 fileenum
= heap_alloc(sizeof(*fileenum
));
3570 fileenum
->file
= file
;
3571 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3573 for (i
= 0; i
< face_count
; i
++) {
3574 IDWriteLocalizedStrings
*family_name
= NULL
;
3575 struct dwrite_font_data
*font_data
;
3576 struct fontface_desc desc
;
3580 desc
.factory
= factory
;
3581 desc
.face_type
= face_type
;
3583 desc
.files_number
= 1;
3585 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3586 desc
.font_data
= NULL
;
3588 /* alloc and init new font data structure */
3589 hr
= init_font_data(&desc
, &family_name
, &font_data
);
3591 /* move to next one */
3596 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3598 /* ignore dot named faces */
3599 if (familyW
[0] == '.') {
3600 WARN("Ignoring face %s\n", debugstr_w(familyW
));
3601 IDWriteLocalizedStrings_Release(family_name
);
3602 release_font_data(font_data
);
3606 index
= collection_find_family(collection
, familyW
);
3608 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3610 struct dwrite_fontfamily_data
*family_data
;
3612 /* create and init new family */
3613 hr
= init_fontfamily_data(family_name
, &family_data
);
3615 /* add font to family, family - to collection */
3616 hr
= fontfamily_add_font(family_data
, font_data
);
3618 hr
= fontcollection_add_family(collection
, family_data
);
3621 release_fontfamily_data(family_data
);
3625 IDWriteLocalizedStrings_Release(family_name
);
3632 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3633 IDWriteFontFile_Release(fileenum
->file
);
3634 list_remove(&fileenum
->entry
);
3635 heap_free(fileenum
);
3638 for (i
= 0; i
< collection
->family_count
; i
++) {
3639 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3640 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3644 fontcollection_add_replacements(collection
);
3649 struct system_fontfile_enumerator
3651 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3654 IDWriteFactory3
*factory
;
3659 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3661 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3664 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3668 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3669 IDWriteFontFileEnumerator_AddRef(iface
);
3674 return E_NOINTERFACE
;
3677 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3679 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3680 return InterlockedIncrement(&enumerator
->ref
);
3683 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3685 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3686 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3689 IDWriteFactory3_Release(enumerator
->factory
);
3690 RegCloseKey(enumerator
->hkey
);
3691 heap_free(enumerator
);
3697 static HRESULT
create_local_file_reference(IDWriteFactory3
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3701 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3702 if (!strchrW(filename
, '\\')) {
3703 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3704 WCHAR fullpathW
[MAX_PATH
];
3706 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3707 strcatW(fullpathW
, fontsW
);
3708 strcatW(fullpathW
, filename
);
3710 hr
= IDWriteFactory3_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3713 hr
= IDWriteFactory3_CreateFontFileReference(factory
, filename
, NULL
, file
);
3718 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3720 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3721 DWORD ret
, type
, val_count
, count
;
3722 WCHAR
*value
, *filename
;
3727 if (enumerator
->index
< 0)
3730 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3731 if (ret
!= ERROR_SUCCESS
)
3735 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3736 filename
= heap_alloc(count
);
3737 if (!value
|| !filename
) {
3739 heap_free(filename
);
3740 return E_OUTOFMEMORY
;
3743 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3746 heap_free(filename
);
3750 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3753 heap_free(filename
);
3757 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3759 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3760 DWORD ret
, max_val_count
;
3764 enumerator
->index
++;
3766 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
3767 if (ret
!= ERROR_SUCCESS
)
3771 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
3772 return E_OUTOFMEMORY
;
3774 /* iterate until we find next string value */
3776 DWORD type
= 0, count
, val_count
;
3777 val_count
= max_val_count
;
3778 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
3780 if (type
== REG_SZ
) {
3784 enumerator
->index
++;
3787 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3792 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3794 systemfontfileenumerator_QueryInterface
,
3795 systemfontfileenumerator_AddRef
,
3796 systemfontfileenumerator_Release
,
3797 systemfontfileenumerator_MoveNext
,
3798 systemfontfileenumerator_GetCurrentFontFile
3801 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory3
*factory
, IDWriteFontFileEnumerator
**ret
)
3803 struct system_fontfile_enumerator
*enumerator
;
3804 static const WCHAR fontslistW
[] = {
3805 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3806 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3807 'F','o','n','t','s',0
3812 enumerator
= heap_alloc(sizeof(*enumerator
));
3814 return E_OUTOFMEMORY
;
3816 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3817 enumerator
->ref
= 1;
3818 enumerator
->factory
= factory
;
3819 enumerator
->index
= -1;
3820 IDWriteFactory3_AddRef(factory
);
3822 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3823 ERR("failed to open fonts list key\n");
3824 IDWriteFactory3_Release(factory
);
3825 heap_free(enumerator
);
3829 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3834 HRESULT
get_system_fontcollection(IDWriteFactory3
*factory
, IDWriteFontCollection1
**collection
)
3836 IDWriteFontFileEnumerator
*enumerator
;
3841 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3845 TRACE("building system font collection for factory %p\n", factory
);
3846 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3847 IDWriteFontFileEnumerator_Release(enumerator
);
3851 static HRESULT
eudc_collection_add_family(IDWriteFactory3
*factory
, struct dwrite_fontcollection
*collection
,
3852 const WCHAR
*keynameW
, const WCHAR
*pathW
)
3854 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};
3855 static const WCHAR emptyW
[] = {0};
3856 IDWriteLocalizedStrings
*names
;
3857 DWRITE_FONT_FACE_TYPE face_type
;
3858 DWRITE_FONT_FILE_TYPE file_type
;
3860 UINT32 face_count
, i
;
3861 IDWriteFontFile
*file
;
3863 struct dwrite_fontfamily_data
*family_data
;
3865 /* create font file from this path */
3866 hr
= create_local_file_reference(factory
, pathW
, &file
);
3870 /* failed font files are skipped */
3871 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3872 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3873 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3874 IDWriteFontFile_Release(file
);
3878 /* create and init new family */
3880 /* Family names are added for non-specific locale, represented with empty string.
3881 Default family appears with empty family name. */
3882 create_localizedstrings(&names
);
3883 if (!strcmpiW(keynameW
, defaultfontW
))
3884 add_localizedstring(names
, emptyW
, emptyW
);
3886 add_localizedstring(names
, emptyW
, keynameW
);
3888 hr
= init_fontfamily_data(names
, &family_data
);
3889 IDWriteLocalizedStrings_Release(names
);
3891 IDWriteFontFile_Release(file
);
3895 /* fill with faces */
3896 for (i
= 0; i
< face_count
; i
++) {
3897 struct dwrite_font_data
*font_data
;
3898 struct fontface_desc desc
;
3900 /* alloc and init new font data structure */
3901 desc
.factory
= factory
;
3902 desc
.face_type
= face_type
;
3905 desc
.files_number
= 1;
3906 desc
.simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3907 desc
.font_data
= NULL
;
3909 hr
= init_font_data(&desc
, &names
, &font_data
);
3913 IDWriteLocalizedStrings_Release(names
);
3915 /* add font to family */
3916 hr
= fontfamily_add_font(family_data
, font_data
);
3918 release_font_data(font_data
);
3921 /* add family to collection */
3922 hr
= fontcollection_add_family(collection
, family_data
);
3924 release_fontfamily_data(family_data
);
3925 IDWriteFontFile_Release(file
);
3930 HRESULT
get_eudc_fontcollection(IDWriteFactory3
*factory
, IDWriteFontCollection
**ret
)
3932 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
3933 struct dwrite_fontcollection
*collection
;
3934 static const WCHAR emptyW
[] = {0};
3935 WCHAR eudckeypathW
[16];
3943 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
3947 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3948 if (!collection
) return E_OUTOFMEMORY
;
3950 hr
= init_font_collection(collection
, FALSE
);
3952 heap_free(collection
);
3956 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3958 /* return empty collection if EUDC fonts are not configured */
3959 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
3960 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
3963 retval
= ERROR_SUCCESS
;
3965 while (retval
!= ERROR_NO_MORE_ITEMS
) {
3966 WCHAR keynameW
[64], pathW
[MAX_PATH
];
3967 DWORD type
, path_len
, name_len
;
3969 path_len
= sizeof(pathW
)/sizeof(*pathW
);
3970 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
3971 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
3972 if (retval
|| type
!= REG_SZ
)
3975 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
3977 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
3979 RegCloseKey(eudckey
);
3981 /* try to add global default if not defined for specific codepage */
3983 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
3985 if (FAILED(hr
) || !exists
) {
3986 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
3987 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
3989 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
3992 /* EUDC collection offers simulated faces too */
3993 for (i
= 0; i
< collection
->family_count
; i
++) {
3994 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3995 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
4001 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
4003 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4005 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4007 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
4010 IDWriteFontFile_AddRef(iface
);
4015 return E_NOINTERFACE
;
4018 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
4020 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4021 ULONG ref
= InterlockedIncrement(&This
->ref
);
4022 TRACE("(%p)->(%d)\n", This
, ref
);
4026 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
4028 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4029 ULONG ref
= InterlockedDecrement(&This
->ref
);
4031 TRACE("(%p)->(%d)\n", This
, ref
);
4035 IDWriteFontFileLoader_Release(This
->loader
);
4036 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
4037 heap_free(This
->reference_key
);
4044 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
4046 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4047 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
4048 *fontFileReferenceKey
= This
->reference_key
;
4049 *fontFileReferenceKeySize
= This
->key_size
;
4054 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
4056 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4057 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
4058 *fontFileLoader
= This
->loader
;
4059 IDWriteFontFileLoader_AddRef(This
->loader
);
4064 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
4065 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
4067 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
4068 IDWriteFontFileStream
*stream
;
4071 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
4073 *isSupportedFontType
= FALSE
;
4074 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
4076 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
4079 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
4083 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
4085 /* TODO: Further Analysis */
4086 IDWriteFontFileStream_Release(stream
);
4090 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
4091 dwritefontfile_QueryInterface
,
4092 dwritefontfile_AddRef
,
4093 dwritefontfile_Release
,
4094 dwritefontfile_GetReferenceKey
,
4095 dwritefontfile_GetLoader
,
4096 dwritefontfile_Analyze
,
4099 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
4101 struct dwrite_fontfile
*This
;
4103 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
4104 if (!This
) return E_OUTOFMEMORY
;
4106 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
4108 IDWriteFontFileLoader_AddRef(loader
);
4109 This
->loader
= loader
;
4110 This
->stream
= NULL
;
4111 This
->reference_key
= heap_alloc(key_size
);
4112 memcpy(This
->reference_key
, reference_key
, key_size
);
4113 This
->key_size
= key_size
;
4115 *font_file
= &This
->IDWriteFontFile_iface
;
4120 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
4122 IDWriteFontFileLoader
*loader
;
4128 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4132 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
4134 IDWriteFontFileLoader_Release(loader
);
4138 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
4139 IDWriteFontFileLoader_Release(loader
);
4144 HRESULT
create_fontface(const struct fontface_desc
*desc
, IDWriteFontFace3
**ret
)
4146 struct file_stream_desc stream_desc
;
4147 struct dwrite_fontface
*fontface
;
4154 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
4156 return E_OUTOFMEMORY
;
4158 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * desc
->files_number
);
4159 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * desc
->files_number
);
4161 if (!fontface
->files
|| !fontface
->streams
) {
4162 heap_free(fontface
->files
);
4163 heap_free(fontface
->streams
);
4164 heap_free(fontface
);
4165 return E_OUTOFMEMORY
;
4168 fontface
->IDWriteFontFace3_iface
.lpVtbl
= &dwritefontfacevtbl
;
4170 fontface
->type
= desc
->face_type
;
4171 fontface
->file_count
= desc
->files_number
;
4172 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
4173 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
4174 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
4175 memset(&fontface
->cpal
, 0, sizeof(fontface
->cpal
));
4176 memset(&fontface
->colr
, 0, sizeof(fontface
->colr
));
4177 fontface
->cmap
.exists
= TRUE
;
4178 fontface
->vdmx
.exists
= TRUE
;
4179 fontface
->gasp
.exists
= TRUE
;
4180 fontface
->cpal
.exists
= TRUE
;
4181 fontface
->colr
.exists
= TRUE
;
4182 fontface
->index
= desc
->index
;
4183 fontface
->simulations
= desc
->simulations
;
4184 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
4186 for (i
= 0; i
< fontface
->file_count
; i
++) {
4187 hr
= get_stream_from_file(desc
->files
[i
], &fontface
->streams
[i
]);
4189 IDWriteFontFace3_Release(&fontface
->IDWriteFontFace3_iface
);
4193 fontface
->files
[i
] = desc
->files
[i
];
4194 IDWriteFontFile_AddRef(fontface
->files
[i
]);
4197 stream_desc
.stream
= fontface
->streams
[0];
4198 stream_desc
.face_type
= desc
->face_type
;
4199 stream_desc
.face_index
= desc
->index
;
4200 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4201 if (desc
->simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4202 /* TODO: test what happens if caret is already slanted */
4203 if (fontface
->caret
.slopeRise
== 1) {
4204 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4205 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4209 fontface
->flags
= 0;
4210 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace3_iface
, &is_symbol
);
4212 fontface
->flags
|= FONTFACE_IS_SYMBOL
;
4213 if (freetype_has_kerning_pairs(&fontface
->IDWriteFontFace3_iface
))
4214 fontface
->flags
|= FONTFACE_HAS_KERN_PAIRS
;
4215 if (freetype_is_monospaced(&fontface
->IDWriteFontFace3_iface
))
4216 fontface
->flags
|= FONTFACE_IS_MONOSPACED
;
4217 if (opentype_has_vertical_variants(&fontface
->IDWriteFontFace3_iface
))
4218 fontface
->flags
|= FONTFACE_HAS_VERTICAL_VARIANTS
;
4220 /* Font properties are reused from font object when 'normal' face creation path is used:
4221 collection -> family -> matching font -> fontface.
4223 If face is created directly from factory we have to go through properties resolution.
4225 if (desc
->font_data
) {
4226 fontface
->weight
= desc
->font_data
->weight
;
4227 fontface
->style
= desc
->font_data
->style
;
4228 fontface
->stretch
= desc
->font_data
->stretch
;
4229 fontface
->panose
= desc
->font_data
->panose
;
4232 IDWriteLocalizedStrings
*names
;
4233 struct dwrite_font_data
*data
;
4235 hr
= init_font_data(desc
, &names
, &data
);
4237 IDWriteFontFace3_Release(&fontface
->IDWriteFontFace3_iface
);
4241 fontface
->weight
= data
->weight
;
4242 fontface
->style
= data
->style
;
4243 fontface
->stretch
= data
->stretch
;
4244 fontface
->panose
= data
->panose
;
4246 IDWriteLocalizedStrings_Release(names
);
4247 release_font_data(data
);
4250 *ret
= &fontface
->IDWriteFontFace3_iface
;
4254 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4261 struct local_cached_stream
4264 IDWriteFontFileStream
*stream
;
4265 struct local_refkey
*key
;
4269 struct dwrite_localfontfilestream
4271 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4274 struct local_cached_stream
*entry
;
4275 const void *file_ptr
;
4279 struct dwrite_localfontfileloader
{
4280 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4283 struct list streams
;
4286 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4288 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4291 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4293 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4296 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4298 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4299 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4300 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
4303 IDWriteFontFileStream_AddRef(iface
);
4308 return E_NOINTERFACE
;
4311 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4313 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4314 ULONG ref
= InterlockedIncrement(&This
->ref
);
4315 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4319 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4321 list_remove(&stream
->entry
);
4322 heap_free(stream
->key
);
4326 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4328 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4329 ULONG ref
= InterlockedDecrement(&This
->ref
);
4331 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4334 UnmapViewOfFile(This
->file_ptr
);
4335 release_cached_stream(This
->entry
);
4342 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4344 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4346 TRACE_(dwrite_file
)("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
4347 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4349 *fragment_context
= NULL
;
4351 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4352 *fragment_start
= NULL
;
4356 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4360 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4362 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4363 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4366 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4368 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4369 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4374 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4376 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4379 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4381 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4382 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4383 *last_writetime
= li
.QuadPart
;
4388 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4390 localfontfilestream_QueryInterface
,
4391 localfontfilestream_AddRef
,
4392 localfontfilestream_Release
,
4393 localfontfilestream_ReadFileFragment
,
4394 localfontfilestream_ReleaseFileFragment
,
4395 localfontfilestream_GetFileSize
,
4396 localfontfilestream_GetLastWriteTime
4399 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4401 struct dwrite_localfontfilestream
*This
;
4405 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4407 return E_OUTOFMEMORY
;
4409 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4412 This
->file_ptr
= file_ptr
;
4414 This
->entry
= entry
;
4416 *ret
= &This
->IDWriteFontFileStream_iface
;
4420 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4422 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4424 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4426 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
4429 IDWriteLocalFontFileLoader_AddRef(iface
);
4434 return E_NOINTERFACE
;
4437 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4439 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4440 ULONG ref
= InterlockedIncrement(&This
->ref
);
4441 TRACE("(%p)->(%d)\n", This
, ref
);
4445 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4447 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4448 ULONG ref
= InterlockedDecrement(&This
->ref
);
4450 TRACE("(%p)->(%d)\n", This
, ref
);
4453 struct local_cached_stream
*stream
, *stream2
;
4455 /* This will detach all entries from cache. Entries are released together with streams,
4456 so stream controls cache entry lifetime. */
4457 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
4458 list_init(&stream
->entry
);
4466 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
4468 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4469 const struct local_refkey
*refkey
= key
;
4470 struct local_cached_stream
*stream
;
4471 IDWriteFontFileStream
*filestream
;
4472 HANDLE file
, mapping
;
4477 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
4478 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4480 /* search cache first */
4481 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4482 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4483 *ret
= stream
->stream
;
4484 IDWriteFontFileStream_AddRef(*ret
);
4491 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4492 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4493 if (file
== INVALID_HANDLE_VALUE
)
4496 GetFileSizeEx(file
, &size
);
4497 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4502 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4503 CloseHandle(mapping
);
4505 ERR("mapping failed, file size %s, error %d\n", wine_dbgstr_longlong(size
.QuadPart
), GetLastError());
4509 stream
= heap_alloc(sizeof(*stream
));
4511 UnmapViewOfFile(file_ptr
);
4512 return E_OUTOFMEMORY
;
4515 stream
->key
= heap_alloc(key_size
);
4517 UnmapViewOfFile(file_ptr
);
4519 return E_OUTOFMEMORY
;
4522 stream
->key_size
= key_size
;
4523 memcpy(stream
->key
, key
, key_size
);
4525 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4527 UnmapViewOfFile(file_ptr
);
4528 heap_free(stream
->key
);
4533 stream
->stream
= filestream
;
4534 list_add_head(&This
->streams
, &stream
->entry
);
4536 *ret
= stream
->stream
;
4541 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4543 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4544 const struct local_refkey
*refkey
= key
;
4546 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4548 *length
= strlenW(refkey
->name
);
4552 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4554 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4555 const struct local_refkey
*refkey
= key
;
4557 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4559 if (length
< strlenW(refkey
->name
))
4560 return E_INVALIDARG
;
4562 strcpyW(path
, refkey
->name
);
4566 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
4568 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4569 const struct local_refkey
*refkey
= key
;
4571 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
4573 *writetime
= refkey
->writetime
;
4577 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4578 localfontfileloader_QueryInterface
,
4579 localfontfileloader_AddRef
,
4580 localfontfileloader_Release
,
4581 localfontfileloader_CreateStreamFromKey
,
4582 localfontfileloader_GetFilePathLengthFromKey
,
4583 localfontfileloader_GetFilePathFromKey
,
4584 localfontfileloader_GetLastWriteTimeFromKey
4587 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
**ret
)
4589 struct dwrite_localfontfileloader
*This
;
4593 This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
4595 return E_OUTOFMEMORY
;
4597 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4599 list_init(&This
->streams
);
4601 *ret
= &This
->IDWriteLocalFontFileLoader_iface
;
4605 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4607 struct local_refkey
*refkey
;
4610 return E_INVALIDARG
;
4612 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4615 refkey
= heap_alloc(*size
);
4617 return E_OUTOFMEMORY
;
4620 refkey
->writetime
= *writetime
;
4622 WIN32_FILE_ATTRIBUTE_DATA info
;
4624 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4625 refkey
->writetime
= info
.ftLastWriteTime
;
4627 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4629 strcpyW(refkey
->name
, path
);
4636 /* IDWriteGlyphRunAnalysis */
4637 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4639 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4641 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4643 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4644 IsEqualIID(riid
, &IID_IUnknown
))
4647 IDWriteGlyphRunAnalysis_AddRef(iface
);
4652 return E_NOINTERFACE
;
4655 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4657 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4658 ULONG ref
= InterlockedIncrement(&This
->ref
);
4659 TRACE("(%p)->(%u)\n", This
, ref
);
4663 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4665 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4666 ULONG ref
= InterlockedDecrement(&This
->ref
);
4668 TRACE("(%p)->(%u)\n", This
, ref
);
4671 if (This
->run
.fontFace
)
4672 IDWriteFontFace_Release(This
->run
.fontFace
);
4673 heap_free(This
->glyphs
);
4674 heap_free(This
->advances
);
4675 heap_free(This
->advanceoffsets
);
4676 heap_free(This
->ascenderoffsets
);
4677 heap_free(This
->bitmap
);
4684 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4686 struct dwrite_glyphbitmap glyph_bitmap
;
4687 IDWriteFontFace3
*fontface3
;
4688 D2D_POINT_2F origin
;
4693 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4694 *bounds
= analysis
->bounds
;
4698 if (analysis
->run
.isSideways
)
4699 FIXME("sideways runs are not supported.\n");
4701 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
4703 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4705 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
4706 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
4707 for any non-zero glyph ascender */
4708 origin
.x
= origin
.y
= 0.0f
;
4709 is_rtl
= analysis
->run
.bidiLevel
& 1;
4711 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4712 glyph_bitmap
.fontface
= fontface3
;
4713 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4714 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4715 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4716 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4717 glyph_bitmap
.m
= &analysis
->m
;
4719 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4720 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4721 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4722 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4723 RECT
*bbox
= &glyph_bitmap
.bbox
;
4725 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4726 freetype_get_glyph_bbox(&glyph_bitmap
);
4729 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4731 OffsetRect(bbox
, origin
.x
, origin
.y
);
4734 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4736 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4737 origin
.x
+= advance
->x
;
4738 origin
.y
+= advance
->y
;
4741 IDWriteFontFace3_Release(fontface3
);
4743 /* translate to given run origin */
4744 OffsetRect(&analysis
->bounds
, analysis
->origin
.x
, analysis
->origin
.y
);
4745 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4746 OffsetRect(&analysis
->bounds
, analysis
->m
.dx
, analysis
->m
.dy
);
4748 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4749 *bounds
= analysis
->bounds
;
4752 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4754 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4756 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4758 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4759 memset(bounds
, 0, sizeof(*bounds
));
4760 return E_INVALIDARG
;
4763 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
4764 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
4765 memset(bounds
, 0, sizeof(*bounds
));
4769 glyphrunanalysis_get_texturebounds(This
, bounds
);
4773 static inline int get_dib_stride( int width
, int bpp
)
4775 return ((width
* bpp
+ 31) >> 3) & ~3;
4778 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4780 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4781 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4782 (runbounds
->left
- bounds
->left
) * 3;
4784 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4785 runbounds
->left
- bounds
->left
;
4788 static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
, DWRITE_TEXTURE_TYPE type
)
4790 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4791 struct dwrite_glyphbitmap glyph_bitmap
;
4792 IDWriteFontFace3
*fontface2
;
4793 D2D_POINT_2F origin
;
4799 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface2
);
4801 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4805 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4806 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4808 analysis
->bitmap
= heap_alloc_zero(size
);
4810 origin
.x
= origin
.y
= 0.0f
;
4811 is_rtl
= analysis
->run
.bidiLevel
& 1;
4813 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4814 glyph_bitmap
.fontface
= fontface2
;
4815 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4816 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4817 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4818 glyph_bitmap
.type
= type
;
4819 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4820 glyph_bitmap
.m
= &analysis
->m
;
4821 bbox
= &glyph_bitmap
.bbox
;
4823 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4824 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4825 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4826 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4827 int x
, y
, width
, height
;
4831 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4832 freetype_get_glyph_bbox(&glyph_bitmap
);
4834 if (IsRectEmpty(bbox
)) {
4835 origin
.x
+= advance
->x
;
4836 origin
.y
+= advance
->y
;
4840 width
= bbox
->right
- bbox
->left
;
4841 height
= bbox
->bottom
- bbox
->top
;
4843 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4844 glyph_bitmap
.pitch
= (width
+ 3) / 4 * 4;
4846 glyph_bitmap
.pitch
= ((width
+ 31) >> 5) << 2;
4848 glyph_bitmap
.buf
= src
= heap_alloc_zero(height
* glyph_bitmap
.pitch
);
4849 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4852 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4854 OffsetRect(bbox
, origin
.x
, origin
.y
);
4857 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4859 OffsetRect(bbox
, analysis
->origin
.x
, analysis
->origin
.y
);
4860 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4861 OffsetRect(bbox
, analysis
->m
.dx
, analysis
->m
.dy
);
4863 /* blit to analysis bitmap */
4864 dst
= get_pixel_ptr(analysis
->bitmap
, type
, bbox
, &analysis
->bounds
);
4867 /* convert 1bpp to 8bpp/24bpp */
4868 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4869 for (y
= 0; y
< height
; y
++) {
4870 for (x
= 0; x
< width
; x
++)
4871 if (src
[x
/ 8] & masks
[x
% 8])
4872 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4873 src
+= glyph_bitmap
.pitch
;
4874 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4878 for (y
= 0; y
< height
; y
++) {
4879 for (x
= 0; x
< width
; x
++)
4880 if (src
[x
/ 8] & masks
[x
% 8])
4881 dst
[x
] = DWRITE_ALPHA_MAX
;
4882 src
+= get_dib_stride(width
, 1);
4883 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
4888 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
4889 for (y
= 0; y
< height
; y
++) {
4890 for (x
= 0; x
< width
; x
++)
4891 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
4892 src
+= glyph_bitmap
.pitch
;
4893 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4897 heap_free(glyph_bitmap
.buf
);
4899 origin
.x
+= advance
->x
;
4900 origin
.y
+= advance
->y
;
4903 IDWriteFontFace3_Release(fontface2
);
4905 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
4907 /* we don't need this anymore */
4908 heap_free(analysis
->glyphs
);
4909 heap_free(analysis
->advances
);
4910 heap_free(analysis
->advanceoffsets
);
4911 heap_free(analysis
->ascenderoffsets
);
4912 IDWriteFontFace_Release(analysis
->run
.fontFace
);
4914 analysis
->glyphs
= NULL
;
4915 analysis
->advances
= NULL
;
4916 analysis
->advanceoffsets
= NULL
;
4917 analysis
->ascenderoffsets
= NULL
;
4918 analysis
->run
.glyphIndices
= NULL
;
4919 analysis
->run
.fontFace
= NULL
;
4922 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
4923 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
4925 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4929 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
4931 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
4932 return E_INVALIDARG
;
4934 /* make sure buffer is large enough for requested texture type */
4935 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
4936 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4939 if (size
< required
)
4940 return E_NOT_SUFFICIENT_BUFFER
;
4942 /* validate requested texture type with rendering mode */
4943 switch (This
->rendering_mode
)
4945 case DWRITE_RENDERING_MODE_ALIASED
:
4946 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
4947 return DWRITE_E_UNSUPPORTEDOPERATION
;
4949 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4950 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4951 case DWRITE_RENDERING_MODE_NATURAL
:
4952 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4953 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
4954 return DWRITE_E_UNSUPPORTEDOPERATION
;
4960 memset(bitmap
, 0, size
);
4961 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
4962 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
4963 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
4964 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
4965 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
4966 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
4970 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
))
4971 glyphrunanalysis_render(This
, type
);
4973 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
4974 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
4976 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
4977 memcpy(dst
, src
, draw_width
);
4986 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
4987 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
4989 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4991 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
4994 return E_INVALIDARG
;
4996 switch (This
->rendering_mode
)
4998 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4999 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
5002 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
5003 *gamma
= (FLOAT
)value
/ 1000.0f
;
5005 *cleartypelevel
= 1.0f
;
5008 case DWRITE_RENDERING_MODE_ALIASED
:
5009 case DWRITE_RENDERING_MODE_NATURAL
:
5010 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
5011 *gamma
= IDWriteRenderingParams_GetGamma(params
);
5012 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
5013 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
5022 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
5023 glyphrunanalysis_QueryInterface
,
5024 glyphrunanalysis_AddRef
,
5025 glyphrunanalysis_Release
,
5026 glyphrunanalysis_GetAlphaTextureBounds
,
5027 glyphrunanalysis_CreateAlphaTexture
,
5028 glyphrunanalysis_GetAlphaBlendParams
5031 static inline void init_2d_vec(D2D_POINT_2F
*vec
, FLOAT length
, BOOL is_vertical
)
5043 static inline void transform_2d_vec(D2D_POINT_2F
*vec
, const DWRITE_MATRIX
*m
)
5046 ret
.x
= vec
->x
* m
->m11
+ vec
->y
* m
->m21
;
5047 ret
.y
= vec
->x
* m
->m12
+ vec
->y
* m
->m22
;
5051 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
5053 struct dwrite_glyphrunanalysis
*analysis
;
5059 /* check for valid rendering mode */
5060 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| desc
->rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
5061 return E_INVALIDARG
;
5063 analysis
= heap_alloc(sizeof(*analysis
));
5065 return E_OUTOFMEMORY
;
5067 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
5069 analysis
->rendering_mode
= desc
->rendering_mode
;
5070 analysis
->flags
= 0;
5071 analysis
->bitmap
= NULL
;
5072 analysis
->ppdip
= desc
->ppdip
;
5073 analysis
->origin
.x
= desc
->origin_x
* desc
->ppdip
;
5074 analysis
->origin
.y
= desc
->origin_y
* desc
->ppdip
;
5075 SetRectEmpty(&analysis
->bounds
);
5076 analysis
->run
= *desc
->run
;
5077 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
5078 analysis
->glyphs
= heap_alloc(desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5079 analysis
->advances
= heap_alloc(desc
->run
->glyphCount
*sizeof(*analysis
->advances
));
5080 if (desc
->run
->glyphOffsets
) {
5081 analysis
->advanceoffsets
= heap_alloc(desc
->run
->glyphCount
*sizeof(*analysis
->advanceoffsets
));
5082 analysis
->ascenderoffsets
= heap_alloc(desc
->run
->glyphCount
*sizeof(*analysis
->ascenderoffsets
));
5085 analysis
->advanceoffsets
= NULL
;
5086 analysis
->ascenderoffsets
= NULL
;
5089 if (!analysis
->glyphs
|| !analysis
->advances
|| ((!analysis
->advanceoffsets
|| !analysis
->ascenderoffsets
) && desc
->run
->glyphOffsets
)) {
5090 heap_free(analysis
->glyphs
);
5091 heap_free(analysis
->advances
);
5092 heap_free(analysis
->advanceoffsets
);
5093 heap_free(analysis
->ascenderoffsets
);
5095 analysis
->glyphs
= NULL
;
5096 analysis
->advances
= NULL
;
5097 analysis
->advanceoffsets
= NULL
;
5098 analysis
->ascenderoffsets
= NULL
;
5100 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
5101 return E_OUTOFMEMORY
;
5104 /* check if transform is usable */
5105 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
5106 analysis
->m
= *desc
->transform
;
5107 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
5110 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
5112 analysis
->run
.glyphIndices
= analysis
->glyphs
;
5113 analysis
->run
.glyphAdvances
= NULL
;
5114 analysis
->run
.glyphOffsets
= NULL
;
5116 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
5118 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5119 transform_2d_vec(&analysis
->origin
, &analysis
->m
);
5121 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
5123 if (desc
->run
->glyphAdvances
) {
5124 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5125 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* desc
->run
->glyphAdvances
[i
] * desc
->ppdip
, desc
->run
->isSideways
);
5126 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5127 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
5131 DWRITE_FONT_METRICS metrics
;
5132 IDWriteFontFace1
*fontface1
;
5134 IDWriteFontFace_GetMetrics(desc
->run
->fontFace
, &metrics
);
5135 IDWriteFontFace_QueryInterface(desc
->run
->fontFace
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
5137 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5141 switch (desc
->measuring_mode
)
5143 case DWRITE_MEASURING_MODE_NATURAL
:
5144 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, desc
->run
->glyphIndices
+ i
, &a
, desc
->run
->isSideways
);
5147 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* get_scaled_advance_width(a
, desc
->run
->fontEmSize
, &metrics
) * desc
->ppdip
,
5148 desc
->run
->isSideways
);
5150 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5151 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5152 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, desc
->run
->fontEmSize
, desc
->ppdip
, desc
->transform
,
5153 desc
->measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, desc
->run
->isSideways
, 1, desc
->run
->glyphIndices
+ i
, &a
);
5155 init_2d_vec(analysis
->advances
+ i
, 0.0f
, FALSE
);
5157 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* floorf(a
* desc
->run
->fontEmSize
* desc
->ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
),
5158 desc
->run
->isSideways
);
5164 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
5165 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
5168 IDWriteFontFace1_Release(fontface1
);
5171 if (desc
->run
->glyphOffsets
) {
5172 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5173 init_2d_vec(analysis
->advanceoffsets
+ i
, rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
* desc
->ppdip
, desc
->run
->isSideways
);
5174 /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
5175 init_2d_vec(analysis
->ascenderoffsets
+ i
, -desc
->run
->glyphOffsets
[i
].ascenderOffset
* desc
->ppdip
, !desc
->run
->isSideways
);
5176 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
) {
5177 transform_2d_vec(analysis
->advanceoffsets
+ i
, &analysis
->m
);
5178 transform_2d_vec(analysis
->ascenderoffsets
+ i
, &analysis
->m
);
5183 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5187 /* IDWriteColorGlyphRunEnumerator */
5188 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
5190 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5192 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5194 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5195 IsEqualIID(riid
, &IID_IUnknown
))
5198 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
5203 return E_NOINTERFACE
;
5206 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
5208 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5209 ULONG ref
= InterlockedIncrement(&This
->ref
);
5210 TRACE("(%p)->(%u)\n", This
, ref
);
5214 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
5216 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5217 ULONG ref
= InterlockedDecrement(&This
->ref
);
5219 TRACE("(%p)->(%u)\n", This
, ref
);
5222 heap_free(This
->advances
);
5223 heap_free(This
->color_advances
);
5224 heap_free(This
->offsets
);
5225 heap_free(This
->color_offsets
);
5226 heap_free(This
->glyphindices
);
5227 heap_free(This
->glyphs
);
5228 if (This
->colr
.context
)
5229 IDWriteFontFace3_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
5230 IDWriteFontFace3_Release(This
->fontface
);
5237 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5239 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5240 FLOAT origin
= 0.0f
;
5246 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5250 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5252 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5253 FLOAT advance_adj
= 0.0f
;
5254 BOOL got_palette_index
;
5257 /* start with regular glyphs */
5258 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5259 UINT32 first_glyph
= 0;
5261 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5262 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5263 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5264 first_glyph
= min(first_glyph
, g
);
5267 glyphenum
->glyphindices
[g
] = 1;
5268 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5269 if (glyphenum
->color_offsets
)
5270 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5273 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5274 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5275 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5276 colorrun
->paletteIndex
= 0xffff;
5277 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5278 glyphenum
->has_regular_glyphs
= FALSE
;
5282 colorrun
->glyphRun
.glyphCount
= 0;
5283 got_palette_index
= FALSE
;
5287 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5289 glyphenum
->glyphindices
[g
] = 1;
5291 /* all glyph layers were returned */
5292 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5293 advance_adj
+= glyphenum
->advances
[g
];
5297 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5298 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5299 if (!got_palette_index
) {
5300 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5301 /* use foreground color or request one from the font */
5302 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5303 if (colorrun
->paletteIndex
!= 0xffff) {
5304 HRESULT hr
= IDWriteFontFace3_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5305 1, &colorrun
->runColor
);
5307 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5308 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5310 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5311 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5312 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5313 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5314 got_palette_index
= TRUE
;
5317 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5318 /* offsets are relative to glyph origin, nothing to fix up */
5319 if (glyphenum
->color_offsets
)
5320 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5321 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5323 glyphenum
->color_advances
[index
-1] += advance_adj
;
5324 colorrun
->glyphRun
.glyphCount
++;
5328 advance_adj
+= glyphenum
->advances
[g
];
5331 /* reset last advance */
5332 if (colorrun
->glyphRun
.glyphCount
)
5333 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5335 return colorrun
->glyphRun
.glyphCount
> 0;
5338 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5340 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5342 TRACE("(%p)->(%p)\n", This
, has_run
);
5346 This
->colorrun
.glyphRun
.glyphCount
= 0;
5347 while (This
->current_layer
< This
->max_layer_num
) {
5348 if (colorglyphenum_build_color_run(This
))
5351 This
->current_layer
++;
5354 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5359 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5361 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5363 TRACE("(%p)->(%p)\n", This
, run
);
5365 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5367 return E_NOT_VALID_STATE
;
5370 *run
= &This
->colorrun
;
5374 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5375 colorglyphenum_QueryInterface
,
5376 colorglyphenum_AddRef
,
5377 colorglyphenum_Release
,
5378 colorglyphenum_MoveNext
,
5379 colorglyphenum_GetCurrentRun
5382 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5383 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5385 struct dwrite_colorglyphenum
*colorglyphenum
;
5386 BOOL colorfont
, has_colored_glyph
;
5387 IDWriteFontFace3
*fontface3
;
5393 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
5395 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
5399 colorfont
= IDWriteFontFace3_IsColorFont(fontface3
) && IDWriteFontFace3_GetColorPaletteCount(fontface3
) > palette
;
5401 hr
= DWRITE_E_NOCOLOR
;
5405 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5406 if (!colorglyphenum
) {
5411 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5412 colorglyphenum
->ref
= 1;
5413 colorglyphenum
->origin_x
= originX
;
5414 colorglyphenum
->origin_y
= originY
;
5415 colorglyphenum
->fontface
= fontface3
;
5416 colorglyphenum
->glyphs
= NULL
;
5417 colorglyphenum
->run
= *run
;
5418 colorglyphenum
->run
.glyphIndices
= NULL
;
5419 colorglyphenum
->run
.glyphAdvances
= NULL
;
5420 colorglyphenum
->run
.glyphOffsets
= NULL
;
5421 colorglyphenum
->palette
= palette
;
5422 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5423 colorglyphenum
->colr
.exists
= TRUE
;
5424 get_fontface_table(fontface3
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5425 colorglyphenum
->current_layer
= 0;
5426 colorglyphenum
->max_layer_num
= 0;
5428 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5430 has_colored_glyph
= FALSE
;
5431 colorglyphenum
->has_regular_glyphs
= FALSE
;
5432 for (i
= 0; i
< run
->glyphCount
; i
++) {
5433 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5434 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5435 has_colored_glyph
= TRUE
;
5437 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5438 colorglyphenum
->has_regular_glyphs
= TRUE
;
5441 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5442 is supposed to proceed normally, like if font had no color info at all. */
5443 if (!has_colored_glyph
) {
5444 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5445 return DWRITE_E_NOCOLOR
;
5448 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5449 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5450 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5451 if (run
->glyphOffsets
) {
5452 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5453 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5454 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5457 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5458 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5459 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5460 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5462 if (run
->glyphAdvances
)
5463 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5465 DWRITE_FONT_METRICS metrics
;
5467 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5468 for (i
= 0; i
< run
->glyphCount
; i
++) {
5472 switch (measuring_mode
)
5474 case DWRITE_MEASURING_MODE_NATURAL
:
5475 hr
= IDWriteFontFace3_GetDesignGlyphAdvances(fontface3
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5478 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5480 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5481 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5482 hr
= IDWriteFontFace3_GetGdiCompatibleGlyphAdvances(fontface3
, run
->fontEmSize
, 1.0f
, transform
,
5483 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5485 colorglyphenum
->advances
[i
] = 0.0f
;
5487 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5495 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5499 IDWriteFontFace3_Release(fontface3
);
5503 /* IDWriteFontFaceReference */
5504 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
5506 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5508 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5510 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) || IsEqualIID(riid
, &IID_IUnknown
)) {
5512 IDWriteFontFaceReference_AddRef(iface
);
5518 return E_NOINTERFACE
;
5521 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference
*iface
)
5523 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5524 ULONG ref
= InterlockedIncrement(&This
->ref
);
5525 TRACE("(%p)->(%u)\n", This
, ref
);
5529 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference
*iface
)
5531 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5532 ULONG ref
= InterlockedDecrement(&This
->ref
);
5534 TRACE("(%p)->(%u)\n", This
, ref
);
5537 IDWriteFontFile_Release(This
->file
);
5538 IDWriteFactory3_Release(This
->factory
);
5545 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference
*iface
, IDWriteFontFace3
**fontface
)
5547 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5549 TRACE("(%p)->(%p)\n", This
, fontface
);
5551 return IDWriteFontFaceReference_CreateFontFaceWithSimulations(iface
, This
->simulations
, fontface
);
5554 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
5555 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
5557 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5558 DWRITE_FONT_FILE_TYPE file_type
;
5559 DWRITE_FONT_FACE_TYPE face_type
;
5560 IDWriteFontFace
*fontface
;
5565 TRACE("(%p)->(%d %p)\n", This
, simulations
, ret
);
5567 hr
= IDWriteFontFile_Analyze(This
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
5571 hr
= IDWriteFactory3_CreateFontFace(This
->factory
, face_type
, 1, &This
->file
, This
->index
, simulations
, &fontface
);
5572 if (SUCCEEDED(hr
)) {
5573 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)ret
);
5574 IDWriteFontFace_Release(fontface
);
5580 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
5582 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5583 IDWriteFontFile
*file
;
5586 TRACE("(%p)->(%p)\n", This
, ref
);
5588 if (FAILED(IDWriteFontFaceReference_GetFontFile(ref
, &file
)))
5591 ret
= is_same_fontfile(This
->file
, file
) &&
5592 This
->index
== IDWriteFontFaceReference_GetFontFaceIndex(ref
) &&
5593 This
->simulations
== IDWriteFontFaceReference_GetSimulations(ref
);
5594 IDWriteFontFile_Release(file
);
5599 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
5601 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5603 TRACE("(%p)\n", This
);
5608 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference
*iface
)
5610 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5612 TRACE("(%p)\n", This
);
5614 return This
->simulations
;
5617 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
5619 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5620 IDWriteFontFileLoader
*loader
;
5625 TRACE("(%p)->(%p)\n", This
, file
);
5627 hr
= IDWriteFontFile_GetReferenceKey(This
->file
, &key
, &key_size
);
5631 hr
= IDWriteFontFile_GetLoader(This
->file
, &loader
);
5635 hr
= IDWriteFactory3_CreateCustomFontFileReference(This
->factory
, key
, key_size
, loader
, file
);
5636 IDWriteFontFileLoader_Release(loader
);
5641 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
5643 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5645 FIXME("(%p): stub\n", This
);
5650 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference
*iface
)
5652 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5654 FIXME("(%p): stub\n", This
);
5659 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
5661 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5663 FIXME("(%p)->(%p): stub\n", This
, writetime
);
5668 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference
*iface
)
5670 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5672 FIXME("(%p): stub\n", This
);
5674 return DWRITE_LOCALITY_LOCAL
;
5677 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
5679 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5681 FIXME("(%p): stub\n", This
);
5686 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
, WCHAR
const *chars
,
5689 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5691 FIXME("(%p)->(%s:%u): stub\n", This
, debugstr_wn(chars
, count
), count
);
5696 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
, UINT16
const *glyphs
,
5699 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5701 FIXME("(%p)->(%p %u): stub\n", This
, glyphs
, count
);
5706 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
5707 UINT64 offset
, UINT64 size
)
5709 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5711 FIXME("(%p)->(%s %s): stub\n", This
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
5716 static const IDWriteFontFaceReferenceVtbl fontfacereferencevtbl
= {
5717 fontfacereference_QueryInterface
,
5718 fontfacereference_AddRef
,
5719 fontfacereference_Release
,
5720 fontfacereference_CreateFontFace
,
5721 fontfacereference_CreateFontFaceWithSimulations
,
5722 fontfacereference_Equals
,
5723 fontfacereference_GetFontFaceIndex
,
5724 fontfacereference_GetSimulations
,
5725 fontfacereference_GetFontFile
,
5726 fontfacereference_GetLocalFileSize
,
5727 fontfacereference_GetFileSize
,
5728 fontfacereference_GetFileTime
,
5729 fontfacereference_GetLocality
,
5730 fontfacereference_EnqueueFontDownloadRequest
,
5731 fontfacereference_EnqueueCharacterDownloadRequest
,
5732 fontfacereference_EnqueueGlyphDownloadRequest
,
5733 fontfacereference_EnqueueFileFragmentDownloadRequest
5736 HRESULT
create_fontfacereference(IDWriteFactory3
*factory
, IDWriteFontFile
*file
, UINT32 index
,
5737 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFaceReference
**ret
)
5739 struct dwrite_fontfacereference
*ref
;
5743 if (!is_simulation_valid(simulations
))
5744 return E_INVALIDARG
;
5746 ref
= heap_alloc(sizeof(*ref
));
5748 return E_OUTOFMEMORY
;
5750 ref
->IDWriteFontFaceReference_iface
.lpVtbl
= &fontfacereferencevtbl
;
5753 ref
->factory
= factory
;
5754 IDWriteFactory3_AddRef(ref
->factory
);
5756 IDWriteFontFile_AddRef(ref
->file
);
5758 ref
->simulations
= simulations
;
5759 *ret
= &ref
->IDWriteFontFaceReference_iface
;