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 "wine/list.h"
27 #include "dwrite_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
30 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
32 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
33 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
34 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
35 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
36 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
37 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
38 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
39 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
41 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
43 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
44 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
45 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
47 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
48 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
49 static const WCHAR semiW
[] = {'s','e','m','i',0};
50 static const WCHAR extW
[] = {'e','x','t',0};
51 static const WCHAR thinW
[] = {'t','h','i','n',0};
52 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
53 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
54 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
55 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
56 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
57 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
58 static const WCHAR boldW
[] = {'B','o','l','d',0};
59 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
60 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
61 static const WCHAR demiW
[] = {'d','e','m','i',0};
62 static const WCHAR spaceW
[] = {' ',0};
63 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
65 struct dwrite_font_propvec
{
71 struct dwrite_font_data
{
74 DWRITE_FONT_STYLE style
;
75 DWRITE_FONT_STRETCH stretch
;
76 DWRITE_FONT_WEIGHT weight
;
78 struct dwrite_font_propvec propvec
;
80 DWRITE_FONT_METRICS1 metrics
;
81 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
82 IDWriteLocalizedStrings
*names
;
84 /* data needed to create fontface instance */
85 IDWriteFactory3
*factory
;
86 DWRITE_FONT_FACE_TYPE face_type
;
87 IDWriteFontFile
*file
;
94 /* used to mark font as tested when scanning for simulation candidate */
95 BOOL bold_sim_tested
: 1;
96 BOOL oblique_sim_tested
: 1;
99 struct dwrite_fontlist
{
100 IDWriteFontList1 IDWriteFontList1_iface
;
103 IDWriteFontFamily1
*family
;
104 struct dwrite_font_data
**fonts
;
108 struct dwrite_fontfamily_data
{
111 IDWriteLocalizedStrings
*familyname
;
113 struct dwrite_font_data
**fonts
;
116 BOOL has_normal_face
: 1;
117 BOOL has_oblique_face
: 1;
118 BOOL has_italic_face
: 1;
121 struct dwrite_fontcollection
{
122 IDWriteFontCollection1 IDWriteFontCollection1_iface
;
125 struct dwrite_fontfamily_data
**family_data
;
130 struct dwrite_fontfamily
{
131 IDWriteFontFamily1 IDWriteFontFamily1_iface
;
134 struct dwrite_fontfamily_data
*data
;
136 IDWriteFontCollection1
*collection
;
140 IDWriteFont3 IDWriteFont3_iface
;
143 IDWriteFontFamily1
*family
;
145 DWRITE_FONT_STYLE style
;
146 struct dwrite_font_data
*data
;
149 struct dwrite_fonttable
{
156 enum runanalysis_flags
{
157 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
158 RUNANALYSIS_BITMAP_READY
= 1 << 1,
159 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
162 struct dwrite_glyphrunanalysis
{
163 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
166 DWRITE_RENDERING_MODE rendering_mode
;
167 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
172 D2D_POINT_2F
*advances
;
173 D2D_POINT_2F
*advanceoffsets
;
174 D2D_POINT_2F
*ascenderoffsets
;
181 struct dwrite_colorglyphenum
{
182 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
185 FLOAT origin_x
; /* original run origin */
188 IDWriteFontFace3
*fontface
; /* for convenience */
189 DWRITE_COLOR_GLYPH_RUN colorrun
; /* returned with GetCurrentRun() */
190 DWRITE_GLYPH_RUN run
; /* base run */
191 UINT32 palette
; /* palette index to get layer color from */
192 FLOAT
*advances
; /* original or measured advances for base glyphs */
193 FLOAT
*color_advances
; /* returned color run points to this */
194 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
195 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
196 UINT16
*glyphindices
; /* returned color run points to this */
197 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
198 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
199 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
200 UINT16 max_layer_num
; /* max number of layers for this run */
201 struct dwrite_fonttable colr
; /* used to access layers */
204 #define GLYPH_BLOCK_SHIFT 8
205 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
206 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
207 #define GLYPH_MAX 65536
209 struct dwrite_fontface
{
210 IDWriteFontFace3 IDWriteFontFace3_iface
;
213 IDWriteFontFileStream
**streams
;
214 IDWriteFontFile
**files
;
219 DWRITE_FONT_FACE_TYPE type
;
220 DWRITE_FONT_METRICS1 metrics
;
221 DWRITE_CARET_METRICS caret
;
224 BOOL has_kerning_pairs
: 1;
225 BOOL is_monospaced
: 1;
227 struct dwrite_fonttable cmap
;
228 struct dwrite_fonttable vdmx
;
229 struct dwrite_fonttable gasp
;
230 struct dwrite_fonttable cpal
;
231 struct dwrite_fonttable colr
;
232 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
235 struct dwrite_fontfile
{
236 IDWriteFontFile IDWriteFontFile_iface
;
239 IDWriteFontFileLoader
*loader
;
242 IDWriteFontFileStream
*stream
;
245 struct dwrite_fontfacereference
{
246 IDWriteFontFaceReference IDWriteFontFaceReference_iface
;
249 IDWriteFontFile
*file
;
252 IDWriteFactory3
*factory
;
255 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace3(IDWriteFontFace3
*iface
)
257 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace3_iface
);
260 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
262 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
265 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
267 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
270 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
272 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
275 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection1(IDWriteFontCollection1
*iface
)
277 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection1_iface
);
280 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
282 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
285 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
287 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
290 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList1(IDWriteFontList1
*iface
)
292 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList1_iface
);
295 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
297 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference_iface
);
300 static inline const char *debugstr_tag(UINT32 tag
)
302 return debugstr_an((char*)&tag
, 4);
305 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
307 static const DWRITE_GLYPH_METRICS nil
;
308 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
310 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
311 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
315 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
317 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
320 /* start new block */
321 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
323 return E_OUTOFMEMORY
;
326 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
330 static void* get_fontface_table(IDWriteFontFace3
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
334 if (table
->data
|| !table
->exists
)
337 table
->exists
= FALSE
;
338 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
340 if (FAILED(hr
) || !table
->exists
) {
341 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
348 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
349 struct dwrite_font_propvec
*vec
)
351 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
352 vec
->style
= style
* 7.0f
;
353 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
356 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
358 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
361 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
363 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
366 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
368 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
371 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
373 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
376 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
378 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_GASP_TAG
, &fontface
->gasp
);
379 *size
= fontface
->gasp
.size
;
383 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
385 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
388 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
390 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_COLR_TAG
, &fontface
->colr
);
393 static void release_font_data(struct dwrite_font_data
*data
)
397 if (InterlockedDecrement(&data
->ref
) > 0)
400 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
401 if (data
->info_strings
[i
])
402 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
405 IDWriteLocalizedStrings_Release(data
->names
);
407 IDWriteFontFile_Release(data
->file
);
408 IDWriteFactory3_Release(data
->factory
);
409 heap_free(data
->facename
);
413 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
417 if (InterlockedDecrement(&data
->ref
) > 0)
420 for (i
= 0; i
< data
->font_count
; i
++)
421 release_font_data(data
->fonts
[i
]);
422 heap_free(data
->fonts
);
423 IDWriteLocalizedStrings_Release(data
->familyname
);
427 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace3
*iface
, REFIID riid
, void **obj
)
429 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
431 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
433 if (IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
434 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
435 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
436 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
437 IsEqualIID(riid
, &IID_IUnknown
))
440 IDWriteFontFace3_AddRef(iface
);
445 return E_NOINTERFACE
;
448 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace3
*iface
)
450 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
451 ULONG ref
= InterlockedIncrement(&This
->ref
);
452 TRACE("(%p)->(%d)\n", This
, ref
);
456 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace3
*iface
)
458 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
459 ULONG ref
= InterlockedDecrement(&This
->ref
);
461 TRACE("(%p)->(%d)\n", This
, ref
);
466 if (This
->cmap
.context
)
467 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cmap
.context
);
468 if (This
->vdmx
.context
)
469 IDWriteFontFace3_ReleaseFontTable(iface
, This
->vdmx
.context
);
470 if (This
->gasp
.context
)
471 IDWriteFontFace3_ReleaseFontTable(iface
, This
->gasp
.context
);
472 if (This
->cpal
.context
)
473 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cpal
.context
);
474 if (This
->colr
.context
)
475 IDWriteFontFace3_ReleaseFontTable(iface
, This
->colr
.context
);
476 for (i
= 0; i
< This
->file_count
; i
++) {
477 if (This
->streams
[i
])
478 IDWriteFontFileStream_Release(This
->streams
[i
]);
480 IDWriteFontFile_Release(This
->files
[i
]);
482 heap_free(This
->streams
);
483 heap_free(This
->files
);
485 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
486 heap_free(This
->glyphs
[i
]);
488 freetype_notify_cacheremove(iface
);
495 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace3
*iface
)
497 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
498 TRACE("(%p)\n", This
);
502 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace3
*iface
, UINT32
*number_of_files
,
503 IDWriteFontFile
**fontfiles
)
505 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
508 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
509 if (fontfiles
== NULL
)
511 *number_of_files
= This
->file_count
;
514 if (*number_of_files
< This
->file_count
)
517 for (i
= 0; i
< This
->file_count
; i
++)
519 IDWriteFontFile_AddRef(This
->files
[i
]);
520 fontfiles
[i
] = This
->files
[i
];
526 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace3
*iface
)
528 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
529 TRACE("(%p)\n", This
);
533 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace3
*iface
)
535 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
536 TRACE("(%p)\n", This
);
537 return This
->simulations
;
540 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace3
*iface
)
542 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
543 TRACE("(%p)\n", This
);
544 return This
->is_symbol
;
547 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS
*metrics
)
549 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
550 TRACE("(%p)->(%p)\n", This
, metrics
);
551 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
554 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace3
*iface
)
556 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
557 TRACE("(%p)\n", This
);
558 return freetype_get_glyphcount(iface
);
561 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace3
*iface
,
562 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
564 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
568 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
574 FIXME("sideways metrics are not supported.\n");
576 for (i
= 0; i
< glyph_count
; i
++) {
577 DWRITE_GLYPH_METRICS metrics
;
579 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
581 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
582 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
592 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace3
*iface
, UINT32
const *codepoints
,
593 UINT32 count
, UINT16
*glyph_indices
)
595 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
597 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
603 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
607 freetype_get_glyphs(iface
, This
->charmap
, codepoints
, count
, glyph_indices
);
611 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace3
*iface
, UINT32 table_tag
,
612 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
614 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
616 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
618 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
621 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace3
*iface
, void *table_context
)
623 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
625 TRACE("(%p)->(%p)\n", This
, table_context
);
627 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
630 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace3
*iface
, FLOAT emSize
,
631 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
632 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
634 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
636 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
637 count
, is_sideways
, is_rtl
, sink
);
639 if (!glyphs
|| !sink
)
643 FIXME("sideways mode is not supported.\n");
645 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
648 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
649 FLOAT ppem
, WORD gasp
)
651 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
655 case DWRITE_MEASURING_MODE_NATURAL
:
657 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
658 mode
= DWRITE_RENDERING_MODE_NATURAL
;
660 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
663 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
664 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
666 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
667 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
676 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
677 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
679 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
684 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
687 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
691 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
692 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
695 ppem
= emSize
* ppdip
;
697 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
698 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
702 ptr
= get_fontface_gasp(This
, &size
);
703 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
704 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
708 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
709 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
711 DWRITE_FONT_METRICS1 metrics1
;
712 HRESULT hr
= IDWriteFontFace3_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
713 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
717 static inline int round_metric(FLOAT metric
)
719 return (int)floorf(metric
+ 0.5f
);
722 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT ppdip
,
723 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
724 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
726 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
727 DWRITE_MEASURING_MODE mode
;
732 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
733 glyph_count
, metrics
, is_sideways
);
735 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
736 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
738 size
= emSize
* ppdip
;
739 scale
= size
/ This
->metrics
.designUnitsPerEm
;
740 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
742 for (i
= 0; i
< glyph_count
; i
++) {
743 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
744 DWRITE_GLYPH_METRICS design
;
746 hr
= IDWriteFontFace3_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
750 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
);
751 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
753 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
754 SCALE_METRIC(leftSideBearing
);
755 SCALE_METRIC(rightSideBearing
);
756 SCALE_METRIC(topSideBearing
);
757 SCALE_METRIC(advanceHeight
);
758 SCALE_METRIC(bottomSideBearing
);
759 SCALE_METRIC(verticalOriginY
);
766 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
768 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
769 TRACE("(%p)->(%p)\n", This
, metrics
);
770 *metrics
= This
->metrics
;
773 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
774 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
776 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
777 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
778 UINT16 ascent
, descent
;
781 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
783 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
784 memset(metrics
, 0, sizeof(*metrics
));
788 em_size
*= pixels_per_dip
;
789 if (m
&& m
->m22
!= 0.0f
)
790 em_size
*= fabs(m
->m22
);
792 scale
= em_size
/ design
->designUnitsPerEm
;
793 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
794 ascent
= round_metric(design
->ascent
* scale
);
795 descent
= round_metric(design
->descent
* scale
);
798 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
799 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
800 metrics
->ascent
= round_metric(ascent
/ scale
);
801 metrics
->descent
= round_metric(descent
/ scale
);
803 SCALE_METRIC(lineGap
);
804 SCALE_METRIC(capHeight
);
805 SCALE_METRIC(xHeight
);
806 SCALE_METRIC(underlinePosition
);
807 SCALE_METRIC(underlineThickness
);
808 SCALE_METRIC(strikethroughPosition
);
809 SCALE_METRIC(strikethroughThickness
);
810 SCALE_METRIC(glyphBoxLeft
);
811 SCALE_METRIC(glyphBoxTop
);
812 SCALE_METRIC(glyphBoxRight
);
813 SCALE_METRIC(glyphBoxBottom
);
814 SCALE_METRIC(subscriptPositionX
);
815 SCALE_METRIC(subscriptPositionY
);
816 SCALE_METRIC(subscriptSizeX
);
817 SCALE_METRIC(subscriptSizeY
);
818 SCALE_METRIC(superscriptPositionX
);
819 SCALE_METRIC(superscriptPositionY
);
820 SCALE_METRIC(superscriptSizeX
);
821 SCALE_METRIC(superscriptSizeY
);
823 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
829 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace3
*iface
, DWRITE_CARET_METRICS
*metrics
)
831 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
832 TRACE("(%p)->(%p)\n", This
, metrics
);
833 *metrics
= This
->caret
;
836 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace3
*iface
, UINT32 max_count
,
837 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
839 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
841 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
844 if (max_count
&& !ranges
)
847 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
850 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace3
*iface
)
852 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
853 TRACE("(%p)\n", This
);
854 return This
->is_monospaced
;
857 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3
*iface
,
858 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
860 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
863 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
866 FIXME("sideways mode not supported\n");
868 for (i
= 0; i
< glyph_count
; i
++)
869 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], DWRITE_MEASURING_MODE_NATURAL
);
874 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace3
*iface
,
875 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
876 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
878 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
879 DWRITE_MEASURING_MODE mode
;
882 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
883 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
885 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
886 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
891 if (em_size
== 0.0f
) {
892 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
896 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
897 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
899 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
900 for (i
= 0; i
< glyph_count
; i
++) {
901 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
);
902 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
908 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace3
*iface
, UINT32 count
,
909 const UINT16
*indices
, INT32
*adjustments
)
911 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
914 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
916 if (!(indices
|| adjustments
) || !count
)
919 if (!indices
|| count
== 1) {
920 memset(adjustments
, 0, count
*sizeof(INT32
));
924 if (!This
->has_kerning_pairs
) {
925 memset(adjustments
, 0, count
*sizeof(INT32
));
929 for (i
= 0; i
< count
-1; i
++)
930 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
931 adjustments
[count
-1] = 0;
936 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace3
*iface
)
938 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
939 TRACE("(%p)\n", This
);
940 return This
->has_kerning_pairs
;
943 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
,
944 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
945 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
947 DWRITE_GRID_FIT_MODE gridfitmode
;
948 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
949 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
952 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace3
*iface
, UINT32 glyph_count
,
953 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
955 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
956 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
960 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3
*iface
)
962 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
963 FIXME("(%p): stub\n", This
);
967 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace3
*iface
)
969 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
970 TRACE("(%p)\n", This
);
971 return get_fontface_cpal(This
) && get_fontface_colr(This
);
974 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace3
*iface
)
976 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
977 TRACE("(%p)\n", This
);
978 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
981 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace3
*iface
)
983 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
984 TRACE("(%p)\n", This
);
985 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
988 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace3
*iface
, UINT32 palette_index
,
989 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
991 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
992 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
993 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
996 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
997 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
998 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
999 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1001 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1006 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1007 measuringmode
, params
, renderingmode
, gridfitmode
);
1010 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1013 FIXME("sideways mode not supported\n");
1015 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1017 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1018 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1020 IDWriteRenderingParams2
*params2
;
1023 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1025 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1026 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1027 IDWriteRenderingParams2_Release(params2
);
1030 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1033 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1035 ptr
= get_fontface_gasp(This
, &size
);
1036 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1038 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1039 if (emSize
>= emthreshold
)
1040 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1042 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1045 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1046 if (emSize
>= emthreshold
)
1047 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1048 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1049 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1051 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1057 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace3
*iface
, IDWriteFontFaceReference
**ref
)
1059 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1060 FIXME("(%p)->(%p): stub\n", This
, ref
);
1064 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace3
*iface
, DWRITE_PANOSE
*panose
)
1066 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1067 FIXME("(%p)->(%p): stub\n", This
, panose
);
1070 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace3
*iface
)
1072 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1073 FIXME("(%p): stub\n", This
);
1074 return DWRITE_FONT_WEIGHT_NORMAL
;
1077 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace3
*iface
)
1079 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1080 FIXME("(%p): stub\n", This
);
1081 return DWRITE_FONT_STRETCH_NORMAL
;
1084 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace3
*iface
)
1086 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1087 FIXME("(%p): stub\n", This
);
1088 return DWRITE_FONT_STYLE_NORMAL
;
1091 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1093 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1094 FIXME("(%p)->(%p): stub\n", This
, names
);
1098 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1100 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1101 FIXME("(%p)->(%p): stub\n", This
, names
);
1105 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace3
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1106 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1108 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1109 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1113 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace3
*iface
, UINT32 ch
)
1115 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1119 TRACE("(%p)->(0x%08x)\n", This
, ch
);
1122 hr
= IDWriteFontFace3_GetGlyphIndices(iface
, &ch
, 1, &index
);
1129 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emsize
, FLOAT dpi_x
, FLOAT dpi_y
,
1130 DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1131 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1133 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1134 FIXME("(%p)->(%f %f %f %p %d %u %u %p %p %p): stub\n", This
, emsize
, dpi_x
, dpi_y
, transform
, is_sideways
, threshold
,
1135 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1139 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace3
*iface
, UINT32 ch
)
1141 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1142 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1146 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace3
*iface
, UINT16 glyph
)
1148 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1149 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1153 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace3
*iface
, WCHAR
const *text
,
1154 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1156 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1157 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1161 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace3
*iface
, UINT16
const *glyphs
,
1162 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1164 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1165 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1169 static const IDWriteFontFace3Vtbl dwritefontfacevtbl
= {
1170 dwritefontface_QueryInterface
,
1171 dwritefontface_AddRef
,
1172 dwritefontface_Release
,
1173 dwritefontface_GetType
,
1174 dwritefontface_GetFiles
,
1175 dwritefontface_GetIndex
,
1176 dwritefontface_GetSimulations
,
1177 dwritefontface_IsSymbolFont
,
1178 dwritefontface_GetMetrics
,
1179 dwritefontface_GetGlyphCount
,
1180 dwritefontface_GetDesignGlyphMetrics
,
1181 dwritefontface_GetGlyphIndices
,
1182 dwritefontface_TryGetFontTable
,
1183 dwritefontface_ReleaseFontTable
,
1184 dwritefontface_GetGlyphRunOutline
,
1185 dwritefontface_GetRecommendedRenderingMode
,
1186 dwritefontface_GetGdiCompatibleMetrics
,
1187 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1188 dwritefontface1_GetMetrics
,
1189 dwritefontface1_GetGdiCompatibleMetrics
,
1190 dwritefontface1_GetCaretMetrics
,
1191 dwritefontface1_GetUnicodeRanges
,
1192 dwritefontface1_IsMonospacedFont
,
1193 dwritefontface1_GetDesignGlyphAdvances
,
1194 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1195 dwritefontface1_GetKerningPairAdjustments
,
1196 dwritefontface1_HasKerningPairs
,
1197 dwritefontface1_GetRecommendedRenderingMode
,
1198 dwritefontface1_GetVerticalGlyphVariants
,
1199 dwritefontface1_HasVerticalGlyphVariants
,
1200 dwritefontface2_IsColorFont
,
1201 dwritefontface2_GetColorPaletteCount
,
1202 dwritefontface2_GetPaletteEntryCount
,
1203 dwritefontface2_GetPaletteEntries
,
1204 dwritefontface2_GetRecommendedRenderingMode
,
1205 dwritefontface3_GetFontFaceReference
,
1206 dwritefontface3_GetPanose
,
1207 dwritefontface3_GetWeight
,
1208 dwritefontface3_GetStretch
,
1209 dwritefontface3_GetStyle
,
1210 dwritefontface3_GetFamilyNames
,
1211 dwritefontface3_GetFaceNames
,
1212 dwritefontface3_GetInformationalStrings
,
1213 dwritefontface3_HasCharacter
,
1214 dwritefontface3_GetRecommendedRenderingMode
,
1215 dwritefontface3_IsCharacterLocal
,
1216 dwritefontface3_IsGlyphLocal
,
1217 dwritefontface3_AreCharactersLocal
,
1218 dwritefontface3_AreGlyphsLocal
1221 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace3
**fontface
)
1223 struct dwrite_font_data
*data
= font
->data
;
1224 IDWriteFontFace
*face
;
1229 hr
= IDWriteFactory3_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
1230 data
->face_index
, font
->data
->simulations
, &face
);
1234 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void**)fontface
);
1235 IDWriteFontFace_Release(face
);
1240 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1242 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1244 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1246 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1247 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1248 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1249 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1250 IsEqualIID(riid
, &IID_IUnknown
))
1253 IDWriteFont3_AddRef(iface
);
1258 return E_NOINTERFACE
;
1261 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1263 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1264 ULONG ref
= InterlockedIncrement(&This
->ref
);
1265 TRACE("(%p)->(%d)\n", This
, ref
);
1269 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1271 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1272 ULONG ref
= InterlockedDecrement(&This
->ref
);
1274 TRACE("(%p)->(%d)\n", This
, ref
);
1277 IDWriteFontFamily1_Release(This
->family
);
1278 release_font_data(This
->data
);
1285 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1287 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1288 TRACE("(%p)->(%p)\n", This
, family
);
1290 *family
= (IDWriteFontFamily
*)This
->family
;
1291 IDWriteFontFamily_AddRef(*family
);
1295 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1297 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1298 TRACE("(%p)\n", This
);
1299 return This
->data
->weight
;
1302 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1304 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1305 TRACE("(%p)\n", This
);
1306 return This
->data
->stretch
;
1309 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1311 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1312 TRACE("(%p)\n", This
);
1316 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1318 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1319 IDWriteFontFace3
*fontface
;
1322 TRACE("(%p)\n", This
);
1324 hr
= get_fontface_from_font(This
, &fontface
);
1328 return IDWriteFontFace3_IsSymbolFont(fontface
);
1331 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1333 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1334 TRACE("(%p)->(%p)\n", This
, names
);
1335 return clone_localizedstring(This
->data
->names
, names
);
1338 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1339 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1341 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1342 struct dwrite_font_data
*data
= This
->data
;
1345 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1350 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1353 if (!data
->info_strings
[stringid
]) {
1354 IDWriteFontFace3
*fontface
;
1355 const void *table_data
;
1360 hr
= get_fontface_from_font(This
, &fontface
);
1364 table_exists
= FALSE
;
1365 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1366 if (FAILED(hr
) || !table_exists
)
1367 WARN("no NAME table found.\n");
1370 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1371 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1373 IDWriteFontFace3_ReleaseFontTable(fontface
, context
);
1377 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1385 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1387 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1388 TRACE("(%p)\n", This
);
1389 return This
->data
->simulations
;
1392 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1394 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1396 TRACE("(%p)->(%p)\n", This
, metrics
);
1397 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1400 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 value
, BOOL
*exists
)
1402 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1403 IDWriteFontFace3
*fontface
;
1407 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1411 hr
= get_fontface_from_font(This
, &fontface
);
1416 hr
= IDWriteFontFace3_GetGlyphIndices(fontface
, &value
, 1, &index
);
1420 *exists
= index
!= 0;
1424 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**face
)
1426 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1429 TRACE("(%p)->(%p)\n", This
, face
);
1431 hr
= get_fontface_from_font(This
, (IDWriteFontFace3
**)face
);
1433 IDWriteFontFace_AddRef(*face
);
1438 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1440 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1441 TRACE("(%p)->(%p)\n", This
, metrics
);
1442 *metrics
= This
->data
->metrics
;
1445 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1447 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1448 TRACE("(%p)->(%p)\n", This
, panose
);
1449 *panose
= This
->data
->panose
;
1452 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1454 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1455 IDWriteFontFace3
*fontface
;
1458 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1460 hr
= get_fontface_from_font(This
, &fontface
);
1464 return IDWriteFontFace3_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1467 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1469 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1470 IDWriteFontFace3
*fontface
;
1473 TRACE("(%p)\n", This
);
1475 hr
= get_fontface_from_font(This
, &fontface
);
1479 return IDWriteFontFace3_IsMonospacedFont(fontface
);
1482 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1484 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1485 IDWriteFontFace3
*fontface
;
1488 TRACE("(%p)\n", This
);
1490 hr
= get_fontface_from_font(This
, &fontface
);
1494 return IDWriteFontFace3_IsColorFont(fontface
);
1497 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1499 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1500 FIXME("(%p)->(%p): stub\n", This
, fontface
);
1504 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1506 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1507 FIXME("(%p)->(%p): stub\n", This
, font
);
1511 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1513 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1515 TRACE("(%p)->(%p)\n", This
, reference
);
1517 return IDWriteFactory3_CreateFontFaceReference_(This
->data
->factory
, This
->data
->file
, This
->data
->face_index
,
1518 This
->data
->simulations
, reference
);
1521 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1523 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1526 TRACE("(%p)->(0x%x)\n", This
, ch
);
1528 IDWriteFont_HasCharacter((IDWriteFont
*)iface
, ch
, &ret
);
1532 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1534 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1535 FIXME("(%p): stub\n", This
);
1536 return DWRITE_LOCALITY_LOCAL
;
1539 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1540 dwritefont_QueryInterface
,
1543 dwritefont_GetFontFamily
,
1544 dwritefont_GetWeight
,
1545 dwritefont_GetStretch
,
1546 dwritefont_GetStyle
,
1547 dwritefont_IsSymbolFont
,
1548 dwritefont_GetFaceNames
,
1549 dwritefont_GetInformationalStrings
,
1550 dwritefont_GetSimulations
,
1551 dwritefont_GetMetrics
,
1552 dwritefont_HasCharacter
,
1553 dwritefont_CreateFontFace
,
1554 dwritefont1_GetMetrics
,
1555 dwritefont1_GetPanose
,
1556 dwritefont1_GetUnicodeRanges
,
1557 dwritefont1_IsMonospacedFont
,
1558 dwritefont2_IsColorFont
,
1559 dwritefont3_CreateFontFace
,
1561 dwritefont3_GetFontFaceReference
,
1562 dwritefont3_HasCharacter
,
1563 dwritefont3_GetLocality
1566 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily1
*family
, IDWriteFont3
**font
)
1568 struct dwrite_font
*This
;
1571 This
= heap_alloc(sizeof(struct dwrite_font
));
1572 if (!This
) return E_OUTOFMEMORY
;
1574 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1576 This
->family
= family
;
1577 IDWriteFontFamily1_AddRef(family
);
1578 This
->style
= data
->style
;
1580 InterlockedIncrement(&This
->data
->ref
);
1582 *font
= &This
->IDWriteFont3_iface
;
1587 /* IDWriteFontList1 */
1588 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList1
*iface
, REFIID riid
, void **obj
)
1590 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1592 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1594 if (IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1595 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1596 IsEqualIID(riid
, &IID_IUnknown
))
1599 IDWriteFontList1_AddRef(iface
);
1604 return E_NOINTERFACE
;
1607 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList1
*iface
)
1609 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1610 ULONG ref
= InterlockedIncrement(&This
->ref
);
1611 TRACE("(%p)->(%d)\n", This
, ref
);
1615 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList1
*iface
)
1617 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1618 ULONG ref
= InterlockedDecrement(&This
->ref
);
1620 TRACE("(%p)->(%d)\n", This
, ref
);
1625 for (i
= 0; i
< This
->font_count
; i
++)
1626 release_font_data(This
->fonts
[i
]);
1627 IDWriteFontFamily1_Release(This
->family
);
1634 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList1
*iface
, IDWriteFontCollection
**collection
)
1636 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1637 return IDWriteFontFamily1_GetFontCollection(This
->family
, collection
);
1640 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList1
*iface
)
1642 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1643 TRACE("(%p)\n", This
);
1644 return This
->font_count
;
1647 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont
**font
)
1649 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1651 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1655 if (This
->font_count
== 0)
1658 if (index
>= This
->font_count
)
1659 return E_INVALIDARG
;
1661 return create_font(This
->fonts
[index
], This
->family
, (IDWriteFont3
**)font
);
1664 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList1
*iface
, UINT32 index
)
1666 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1668 FIXME("(%p)->(%u): stub\n", This
, index
);
1670 return DWRITE_LOCALITY_LOCAL
;
1673 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1675 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1677 FIXME("(%p)->(%u %p): stub\n", This
, index
, font
);
1682 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList1
*iface
, UINT32 index
,
1683 IDWriteFontFaceReference
**reference
)
1685 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1687 FIXME("(%p)->(%u %p): stub\n", This
, index
, reference
);
1692 static const IDWriteFontList1Vtbl dwritefontlistvtbl
= {
1693 dwritefontlist_QueryInterface
,
1694 dwritefontlist_AddRef
,
1695 dwritefontlist_Release
,
1696 dwritefontlist_GetFontCollection
,
1697 dwritefontlist_GetFontCount
,
1698 dwritefontlist_GetFont
,
1699 dwritefontlist1_GetFontLocality
,
1700 dwritefontlist1_GetFont
,
1701 dwritefontlist1_GetFontFaceReference
1704 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1706 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1708 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1710 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1711 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1712 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1713 IsEqualIID(riid
, &IID_IUnknown
))
1716 IDWriteFontFamily1_AddRef(iface
);
1721 return E_NOINTERFACE
;
1724 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1726 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1727 ULONG ref
= InterlockedIncrement(&This
->ref
);
1728 TRACE("(%p)->(%d)\n", This
, ref
);
1732 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1734 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1735 ULONG ref
= InterlockedDecrement(&This
->ref
);
1737 TRACE("(%p)->(%d)\n", This
, ref
);
1741 IDWriteFontCollection1_Release(This
->collection
);
1742 release_fontfamily_data(This
->data
);
1749 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
1751 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1753 TRACE("(%p)->(%p)\n", This
, collection
);
1755 *collection
= (IDWriteFontCollection
*)This
->collection
;
1756 IDWriteFontCollection_AddRef(*collection
);
1760 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
1762 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1763 TRACE("(%p)\n", This
);
1764 return This
->data
->font_count
;
1767 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
1769 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1771 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1775 if (This
->data
->font_count
== 0)
1778 if (index
>= This
->data
->font_count
)
1779 return E_INVALIDARG
;
1781 return create_font(This
->data
->fonts
[index
], iface
, (IDWriteFont3
**)font
);
1784 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
1786 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1787 return clone_localizedstring(This
->data
->familyname
, names
);
1790 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
1791 const struct dwrite_font_propvec
*req
)
1793 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
1794 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
1795 FLOAT cur_req_prod
, next_req_prod
;
1797 if (next_to_req
< cur_to_req
)
1800 if (next_to_req
> cur_to_req
)
1803 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
1804 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
1806 if (next_req_prod
> cur_req_prod
)
1809 if (next_req_prod
< cur_req_prod
)
1812 if (next
->stretch
> cur
->stretch
)
1814 if (next
->stretch
< cur
->stretch
)
1817 if (next
->style
> cur
->style
)
1819 if (next
->style
< cur
->style
)
1822 if (next
->weight
> cur
->weight
)
1824 if (next
->weight
< cur
->weight
)
1827 /* full match, no reason to prefer new variant */
1831 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1832 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1834 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1835 struct dwrite_font_propvec req
;
1836 struct dwrite_font_data
*match
;
1839 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1841 if (This
->data
->font_count
== 0) {
1843 return DWRITE_E_NOFONT
;
1846 init_font_prop_vec(weight
, stretch
, style
, &req
);
1847 match
= This
->data
->fonts
[0];
1849 for (i
= 1; i
< This
->data
->font_count
; i
++) {
1850 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &match
->propvec
, &req
))
1851 match
= This
->data
->fonts
[i
];
1854 return create_font(match
, iface
, (IDWriteFont3
**)font
);
1857 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
1859 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
1861 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1864 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
1866 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1869 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
1871 UINT32 b
= fonts
->font_count
- 1, j
, t
;
1876 for (j
= 0; j
< b
; j
++) {
1877 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
1878 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
1879 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
1880 fonts
->fonts
[j
+1] = s
;
1891 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1892 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
1894 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1895 matching_filter_func func
= NULL
;
1896 struct dwrite_font_propvec req
;
1897 struct dwrite_fontlist
*fonts
;
1900 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
1904 fonts
= heap_alloc(sizeof(*fonts
));
1906 return E_OUTOFMEMORY
;
1908 /* Allocate as many as family has, not all of them will be necessary used. */
1909 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
1910 if (!fonts
->fonts
) {
1912 return E_OUTOFMEMORY
;
1915 fonts
->IDWriteFontList1_iface
.lpVtbl
= &dwritefontlistvtbl
;
1917 fonts
->family
= iface
;
1918 IDWriteFontFamily1_AddRef(fonts
->family
);
1919 fonts
->font_count
= 0;
1921 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
1922 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
1923 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
1924 func
= is_font_acceptable_for_normal
;
1926 else /* requested oblique or italic */ {
1927 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
1928 func
= is_font_acceptable_for_oblique_italic
;
1931 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1932 if (!func
|| func(This
->data
->fonts
[i
])) {
1933 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
1934 InterlockedIncrement(&This
->data
->fonts
[i
]->ref
);
1935 fonts
->font_count
++;
1939 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
1940 init_font_prop_vec(weight
, stretch
, style
, &req
);
1941 matchingfonts_sort(fonts
, &req
);
1943 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList1_iface
;
1947 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
1949 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1951 FIXME("(%p)->(%u): stub\n", This
, index
);
1953 return DWRITE_LOCALITY_LOCAL
;
1956 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1958 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1960 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1964 if (This
->data
->font_count
== 0)
1967 if (index
>= This
->data
->font_count
)
1970 return create_font(This
->data
->fonts
[index
], iface
, font
);
1973 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
1974 IDWriteFontFaceReference
**ref
)
1976 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1978 FIXME("(%p)->(%u %p): stub\n", This
, index
, ref
);
1983 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
1984 dwritefontfamily_QueryInterface
,
1985 dwritefontfamily_AddRef
,
1986 dwritefontfamily_Release
,
1987 dwritefontfamily_GetFontCollection
,
1988 dwritefontfamily_GetFontCount
,
1989 dwritefontfamily_GetFont
,
1990 dwritefontfamily_GetFamilyNames
,
1991 dwritefontfamily_GetFirstMatchingFont
,
1992 dwritefontfamily_GetMatchingFonts
,
1993 dwritefontfamily1_GetFontLocality
,
1994 dwritefontfamily1_GetFont
,
1995 dwritefontfamily1_GetFontFaceReference
1998 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection1
*collection
, IDWriteFontFamily1
**family
)
2000 struct dwrite_fontfamily
*This
;
2004 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
2005 if (!This
) return E_OUTOFMEMORY
;
2007 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
2009 This
->collection
= collection
;
2010 IDWriteFontCollection1_AddRef(collection
);
2012 InterlockedIncrement(&This
->data
->ref
);
2014 *family
= &This
->IDWriteFontFamily1_iface
;
2019 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2022 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
2025 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2027 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2028 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2030 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2031 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2032 IsEqualIID(riid
, &IID_IUnknown
))
2035 IDWriteFontCollection1_AddRef(iface
);
2041 if (IsEqualIID(riid
, &IID_issystemcollection
))
2044 return E_NOINTERFACE
;
2047 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2049 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2050 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2052 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2053 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2054 IsEqualIID(riid
, &IID_IUnknown
))
2057 IDWriteFontCollection1_AddRef(iface
);
2063 return E_NOINTERFACE
;
2066 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2068 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2069 ULONG ref
= InterlockedIncrement(&This
->ref
);
2070 TRACE("(%p)->(%d)\n", This
, ref
);
2074 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2077 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2078 ULONG ref
= InterlockedDecrement(&This
->ref
);
2079 TRACE("(%p)->(%d)\n", This
, ref
);
2082 for (i
= 0; i
< This
->family_count
; i
++)
2083 release_fontfamily_data(This
->family_data
[i
]);
2084 heap_free(This
->family_data
);
2091 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2093 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2094 TRACE("(%p)\n", This
);
2095 return This
->family_count
;
2098 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2100 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2102 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2104 if (index
>= This
->family_count
) {
2109 return create_fontfamily(This
->family_data
[index
], iface
, (IDWriteFontFamily1
**)family
);
2112 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2116 for (i
= 0; i
< collection
->family_count
; i
++) {
2117 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2118 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2121 for (j
= 0; j
< count
; j
++) {
2123 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2124 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2132 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2134 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2135 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2136 *index
= collection_find_family(This
, name
);
2137 *exists
= *index
!= ~0u;
2141 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2143 UINT32 left_key_size
, right_key_size
;
2144 const void *left_key
, *right_key
;
2150 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2154 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2158 if (left_key_size
!= right_key_size
)
2161 return !memcmp(left_key
, right_key
, left_key_size
);
2164 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2166 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2167 struct dwrite_fontfamily_data
*found_family
= NULL
;
2168 struct dwrite_font_data
*found_font
= NULL
;
2169 IDWriteFontFamily1
*family
;
2170 UINT32 i
, j
, face_index
;
2171 IDWriteFontFile
*file
;
2174 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2179 return E_INVALIDARG
;
2182 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2185 face_index
= IDWriteFontFace_GetIndex(face
);
2187 for (i
= 0; i
< This
->family_count
; i
++) {
2188 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2189 for (j
= 0; j
< family_data
->font_count
; j
++) {
2190 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2192 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2193 found_font
= font_data
;
2194 found_family
= family_data
;
2201 return DWRITE_E_NOFONT
;
2203 hr
= create_fontfamily(found_family
, iface
, &family
);
2207 hr
= create_font(found_font
, family
, (IDWriteFont3
**)font
);
2208 IDWriteFontFamily1_Release(family
);
2212 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2214 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2216 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2221 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2223 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2225 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2227 if (index
>= This
->family_count
) {
2232 return create_fontfamily(This
->family_data
[index
], iface
, family
);
2235 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2236 dwritefontcollection_QueryInterface
,
2237 dwritefontcollection_AddRef
,
2238 dwritefontcollection_Release
,
2239 dwritefontcollection_GetFontFamilyCount
,
2240 dwritefontcollection_GetFontFamily
,
2241 dwritefontcollection_FindFamilyName
,
2242 dwritefontcollection_GetFontFromFontFace
,
2243 dwritefontcollection1_GetFontSet
,
2244 dwritefontcollection1_GetFontFamily
2247 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2248 dwritesystemfontcollection_QueryInterface
,
2249 dwritefontcollection_AddRef
,
2250 dwritefontcollection_Release
,
2251 dwritefontcollection_GetFontFamilyCount
,
2252 dwritefontcollection_GetFontFamily
,
2253 dwritefontcollection_FindFamilyName
,
2254 dwritefontcollection_GetFontFromFontFace
,
2255 dwritefontcollection1_GetFontSet
,
2256 dwritefontcollection1_GetFontFamily
2259 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2261 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2262 struct dwrite_font_data
**new_list
;
2265 new_alloc
= family_data
->font_alloc
* 2;
2266 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2268 return E_OUTOFMEMORY
;
2269 family_data
->fonts
= new_list
;
2270 family_data
->font_alloc
= new_alloc
;
2273 family_data
->fonts
[family_data
->font_count
] = font_data
;
2274 family_data
->font_count
++;
2275 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2276 family_data
->has_normal_face
= 1;
2277 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2278 family_data
->has_oblique_face
= 1;
2280 family_data
->has_italic_face
= 1;
2284 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2286 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2287 struct dwrite_fontfamily_data
**new_list
;
2290 new_alloc
= collection
->family_alloc
* 2;
2291 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2293 return E_OUTOFMEMORY
;
2295 collection
->family_alloc
= new_alloc
;
2296 collection
->family_data
= new_list
;
2299 collection
->family_data
[collection
->family_count
] = family
;
2300 collection
->family_count
++;
2305 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2307 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2308 collection
->ref
= 1;
2309 collection
->family_count
= 0;
2310 collection
->family_alloc
= is_system
? 30 : 5;
2311 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2312 if (!collection
->family_data
)
2313 return E_OUTOFMEMORY
;
2318 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2320 IDWriteFontFileLoader
*loader
;
2327 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2331 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2335 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2336 IDWriteFontFileLoader_Release(loader
);
2343 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2345 BOOL exists
= FALSE
;
2350 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2351 if (FAILED(hr
) || !exists
)
2354 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2357 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2361 while (isspaceW(*in
))
2365 if (!(len
= strlenW(in
)))
2368 while (isspaceW(in
[len
-1]))
2371 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2380 INT len
; /* token length */
2381 INT fulllen
; /* full length including following separators */
2384 static inline BOOL
is_name_separator_char(WCHAR ch
)
2386 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2389 struct name_pattern
{
2390 const WCHAR
*part1
; /* NULL indicates end of list */
2391 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2394 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2396 const struct name_pattern
*pattern
;
2397 struct name_token
*token
;
2400 while ((pattern
= &patterns
[i
++])->part1
) {
2401 int len_part1
= strlenW(pattern
->part1
);
2402 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2404 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2405 if (len_part2
== 0) {
2406 /* simple case with single part pattern */
2407 if (token
->len
!= len_part1
)
2410 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2411 if (match
) *match
= *token
;
2412 list_remove(&token
->entry
);
2418 struct name_token
*next_token
;
2419 struct list
*next_entry
;
2421 /* pattern parts are stored in reading order, tokens list is reversed */
2422 if (token
->len
< len_part2
)
2425 /* it's possible to have combined string as a token, like ExtraCondensed */
2426 if (token
->len
== len_part1
+ len_part2
) {
2427 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2430 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2433 /* combined string match */
2434 if (match
) *match
= *token
;
2435 list_remove(&token
->entry
);
2440 /* now it's only possible to have two tokens matched to respective pattern parts */
2441 if (token
->len
!= len_part2
)
2444 next_entry
= list_next(tokens
, &token
->entry
);
2446 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2447 if (next_token
->len
!= len_part1
)
2450 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2453 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2456 /* both parts matched, remove tokens */
2458 match
->ptr
= next_token
->ptr
;
2459 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2461 list_remove(&token
->entry
);
2462 list_remove(&next_token
->entry
);
2463 heap_free(next_token
);
2478 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2480 static const WCHAR itaW
[] = {'i','t','a',0};
2481 static const WCHAR italW
[] = {'i','t','a','l',0};
2482 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2483 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2485 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2486 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2487 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2488 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2490 static const struct name_pattern italic_patterns
[] = {
2499 static const struct name_pattern oblique_patterns
[] = {
2508 /* italic patterns first */
2509 if (match_pattern_list(tokens
, italic_patterns
, match
))
2510 return DWRITE_FONT_STYLE_ITALIC
;
2512 /* oblique patterns */
2513 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2514 return DWRITE_FONT_STYLE_OBLIQUE
;
2519 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2520 struct name_token
*match
)
2522 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2523 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2524 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2525 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2526 static const WCHAR wideW
[] = {'w','i','d','e',0};
2527 static const WCHAR condW
[] = {'c','o','n','d',0};
2529 static const struct name_pattern ultracondensed_patterns
[] = {
2530 { extraW
, compressedW
},
2531 { extW
, compressedW
},
2532 { ultraW
, compressedW
},
2533 { ultraW
, condensedW
},
2538 static const struct name_pattern extracondensed_patterns
[] = {
2540 { extraW
, condensedW
},
2541 { extW
, condensedW
},
2547 static const struct name_pattern semicondensed_patterns
[] = {
2550 { semiW
, condensedW
},
2555 static const struct name_pattern semiexpanded_patterns
[] = {
2557 { semiW
, expandedW
},
2558 { semiW
, extendedW
},
2562 static const struct name_pattern extraexpanded_patterns
[] = {
2563 { extraW
, expandedW
},
2564 { extW
, expandedW
},
2565 { extraW
, extendedW
},
2566 { extW
, extendedW
},
2570 static const struct name_pattern ultraexpanded_patterns
[] = {
2571 { ultraW
, expandedW
},
2572 { ultraW
, extendedW
},
2576 static const struct name_pattern condensed_patterns
[] = {
2582 static const struct name_pattern expanded_patterns
[] = {
2588 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2589 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2591 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2592 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2594 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2595 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2597 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2598 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2600 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2601 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2603 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2604 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2606 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2607 return DWRITE_FONT_STRETCH_CONDENSED
;
2609 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2610 return DWRITE_FONT_STRETCH_EXPANDED
;
2615 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2616 struct name_token
*match
)
2618 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2619 static const WCHAR nordW
[] = {'n','o','r','d',0};
2621 static const struct name_pattern thin_patterns
[] = {
2628 static const struct name_pattern extralight_patterns
[] = {
2635 static const struct name_pattern semilight_patterns
[] = {
2640 static const struct name_pattern demibold_patterns
[] = {
2646 static const struct name_pattern extrabold_patterns
[] = {
2653 static const struct name_pattern extrablack_patterns
[] = {
2660 static const struct name_pattern bold_patterns
[] = {
2665 static const struct name_pattern thin2_patterns
[] = {
2670 static const struct name_pattern light_patterns
[] = {
2675 static const struct name_pattern medium_patterns
[] = {
2680 static const struct name_pattern black_patterns
[] = {
2687 static const struct name_pattern demibold2_patterns
[] = {
2692 static const struct name_pattern extrabold2_patterns
[] = {
2697 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2698 matching pattern. */
2700 if (match_pattern_list(tokens
, thin_patterns
, match
))
2701 return DWRITE_FONT_WEIGHT_THIN
;
2703 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2704 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2706 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2707 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2709 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2710 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2712 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2713 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2715 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2716 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2718 if (match_pattern_list(tokens
, bold_patterns
, match
))
2719 return DWRITE_FONT_WEIGHT_BOLD
;
2721 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2722 return DWRITE_FONT_WEIGHT_THIN
;
2724 if (match_pattern_list(tokens
, light_patterns
, match
))
2725 return DWRITE_FONT_WEIGHT_LIGHT
;
2727 if (match_pattern_list(tokens
, medium_patterns
, match
))
2728 return DWRITE_FONT_WEIGHT_MEDIUM
;
2730 if (match_pattern_list(tokens
, black_patterns
, match
))
2731 return DWRITE_FONT_WEIGHT_BLACK
;
2733 if (match_pattern_list(tokens
, black_patterns
, match
))
2734 return DWRITE_FONT_WEIGHT_BLACK
;
2736 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2737 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2739 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2740 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2742 /* FIXME: use abbreviated names to extract weight */
2747 struct knownweight_entry
{
2749 DWRITE_FONT_WEIGHT weight
;
2752 static int compare_knownweights(const void *a
, const void* b
)
2754 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2755 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2758 if (target
> entry
->weight
)
2760 else if (target
< entry
->weight
)
2766 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2768 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2769 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2770 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2771 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2772 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2773 const struct knownweight_entry
*ptr
;
2775 static const struct knownweight_entry knownweights
[] = {
2776 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
2777 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
2778 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
2779 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
2780 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
2781 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
2782 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
2783 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
2784 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
2785 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
2788 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
2789 compare_knownweights
);
2795 strcpyW(nameW
, ptr
->nameW
);
2799 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
2801 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
2802 strW
[name
->len
] = 0;
2805 /* Modifies facenameW string, and returns pointer to regular term that was removed */
2806 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
2808 static const WCHAR bookW
[] = {'B','o','o','k',0};
2809 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
2810 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
2811 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
2812 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
2814 static const WCHAR
*regular_patterns
[] = {
2823 const WCHAR
*regular_ptr
= NULL
, *ptr
;
2827 len
= strlenW(facenameW
);
2829 /* remove rightmost regular variant from face name */
2830 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
2831 int pattern_len
= strlenW(ptr
);
2834 if (pattern_len
> len
)
2837 src
= facenameW
+ len
- pattern_len
;
2838 while (src
>= facenameW
) {
2839 if (!strncmpiW(src
, ptr
, pattern_len
)) {
2840 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
2841 len
= strlenW(facenameW
);
2853 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
2861 struct name_token
*token
= heap_alloc(sizeof(*token
));
2866 while (*ptr
&& !is_name_separator_char(*ptr
)) {
2872 /* skip separators */
2873 while (is_name_separator_char(*ptr
)) {
2878 list_add_head(tokens
, &token
->entry
);
2882 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
2884 struct name_token
*token
, *token2
;
2885 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
2888 list_remove(&token
->entry
);
2890 /* don't include last separator */
2891 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
2892 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
2900 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
2902 struct name_token stretch_name
, weight_name
, style_name
;
2903 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
2904 WCHAR weightW
[32], stretchW
[32], styleW
[32];
2905 const WCHAR
*regular_ptr
= NULL
;
2906 DWRITE_FONT_STRETCH stretch
;
2907 DWRITE_FONT_WEIGHT weight
;
2911 /* remove leading and trailing spaces from family and face name */
2912 trim_spaces(familyW
, familynameW
);
2913 len
= trim_spaces(faceW
, facenameW
);
2915 /* remove rightmost regular variant from face name */
2916 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
2918 /* append face name to family name, FIXME check if face name is a substring of family name */
2920 strcatW(familynameW
, spaceW
);
2921 strcatW(familynameW
, facenameW
);
2924 /* tokenize with " .-_" */
2925 fontname_tokenize(&tokens
, familynameW
);
2927 /* extract and resolve style */
2928 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
2930 /* extract stretch */
2931 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
2933 /* extract weight */
2934 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
2936 /* resolve weight */
2937 if (weight
!= font
->weight
) {
2938 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
2939 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
2940 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
2941 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
2942 !(abs(weight
- font
->weight
) <= 150 &&
2943 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
2944 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
2945 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
2947 font
->weight
= weight
;
2951 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
2952 it's leaning in opposite direction from normal comparing to specified stretch or if specified
2953 stretch itself is normal (extracted stretch is never normal). */
2954 if (stretch
!= font
->stretch
) {
2955 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
2956 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
2957 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
2959 font
->stretch
= stretch
;
2963 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
2965 /* get final combined string from what's left in token list, list is released */
2966 fontname_tokens_to_str(&tokens
, finalW
);
2968 if (!strcmpW(familyW
, finalW
))
2971 /* construct face name */
2972 strcpyW(familyW
, finalW
);
2974 /* resolved weight name */
2975 if (weight_name
.ptr
)
2976 font_name_token_to_str(&weight_name
, weightW
);
2977 /* ignore normal weight */
2978 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
2980 /* for known weight values use appropriate names */
2981 else if (is_known_weight_value(font
->weight
, weightW
)) {
2983 /* use Wnnn format as a fallback in case weight is not one of known values */
2985 static const WCHAR fmtW
[] = {'W','%','d',0};
2986 sprintfW(weightW
, fmtW
, font
->weight
);
2989 /* resolved stretch name */
2990 if (stretch_name
.ptr
)
2991 font_name_token_to_str(&stretch_name
, stretchW
);
2992 /* ignore normal stretch */
2993 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
2995 /* use predefined stretch names */
2997 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2998 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2999 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3000 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3001 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3002 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3004 static const WCHAR
*stretchnamesW
[] = {
3009 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3015 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3018 /* resolved style name */
3020 font_name_token_to_str(&style_name
, styleW
);
3021 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3023 /* use predefined names */
3025 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3026 strcpyW(styleW
, italicW
);
3028 strcpyW(styleW
, obliqueW
);
3031 /* use Regular match if it was found initially */
3032 if (!*weightW
&& !*stretchW
&& !*styleW
)
3033 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3037 strcpyW(faceW
, stretchW
);
3040 strcatW(faceW
, spaceW
);
3041 strcatW(faceW
, weightW
);
3045 strcatW(faceW
, spaceW
);
3046 strcatW(faceW
, styleW
);
3050 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3054 static HRESULT
init_font_data(IDWriteFactory3
*factory
, IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
, UINT32 face_index
,
3055 IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
3057 struct dwrite_font_props props
;
3058 struct dwrite_font_data
*data
;
3059 IDWriteFontFileStream
*stream
;
3060 WCHAR familyW
[255], faceW
[255];
3064 data
= heap_alloc_zero(sizeof(*data
));
3066 return E_OUTOFMEMORY
;
3068 hr
= get_filestream_from_file(file
, &stream
);
3075 data
->factory
= factory
;
3077 data
->face_index
= face_index
;
3078 data
->face_type
= face_type
;
3079 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3080 data
->bold_sim_tested
= 0;
3081 data
->oblique_sim_tested
= 0;
3082 IDWriteFontFile_AddRef(file
);
3083 IDWriteFactory3_AddRef(factory
);
3085 opentype_get_font_properties(stream
, face_type
, face_index
, &props
);
3086 opentype_get_font_metrics(stream
, face_type
, face_index
, &data
->metrics
, NULL
);
3087 opentype_get_font_facename(stream
, face_type
, face_index
, &data
->names
);
3089 /* get family name from font file */
3090 hr
= opentype_get_font_familyname(stream
, face_type
, face_index
, family_name
);
3091 IDWriteFontFileStream_Release(stream
);
3093 WARN("unable to get family name from font\n");
3094 release_font_data(data
);
3098 data
->style
= props
.style
;
3099 data
->stretch
= props
.stretch
;
3100 data
->weight
= props
.weight
;
3101 data
->panose
= props
.panose
;
3103 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3104 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3105 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3106 set_en_localizedstring(*family_name
, familyW
);
3107 set_en_localizedstring(data
->names
, faceW
);
3110 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3116 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
, const WCHAR
*facenameW
,
3117 struct dwrite_font_data
**ret
)
3119 struct dwrite_font_data
*data
;
3122 data
= heap_alloc_zero(sizeof(*data
));
3124 return E_OUTOFMEMORY
;
3128 data
->simulations
|= sim
;
3129 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3130 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3131 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3132 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3133 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3135 IDWriteFactory3_AddRef(data
->factory
);
3136 IDWriteFontFile_AddRef(data
->file
);
3138 create_localizedstrings(&data
->names
);
3139 add_localizedstring(data
->names
, enusW
, facenameW
);
3141 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3147 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3149 struct dwrite_fontfamily_data
*data
;
3151 data
= heap_alloc(sizeof(*data
));
3153 return E_OUTOFMEMORY
;
3156 data
->font_count
= 0;
3157 data
->font_alloc
= 2;
3158 data
->has_normal_face
= 0;
3159 data
->has_oblique_face
= 0;
3160 data
->has_italic_face
= 0;
3162 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3165 return E_OUTOFMEMORY
;
3168 data
->familyname
= familyname
;
3169 IDWriteLocalizedStrings_AddRef(familyname
);
3175 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3177 UINT32 i
, j
, heaviest
;
3179 for (i
= 0; i
< family
->font_count
; i
++) {
3180 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3183 if (family
->fonts
[i
]->bold_sim_tested
)
3186 family
->fonts
[i
]->bold_sim_tested
= 1;
3187 for (j
= i
; j
< family
->font_count
; j
++) {
3188 if (family
->fonts
[j
]->bold_sim_tested
)
3191 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3192 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3193 if (family
->fonts
[j
]->weight
> weight
) {
3194 weight
= family
->fonts
[j
]->weight
;
3197 family
->fonts
[j
]->bold_sim_tested
= 1;
3201 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3202 static const struct name_pattern weightsim_patterns
[] = {
3217 WCHAR facenameW
[255], initialW
[255];
3218 struct dwrite_font_data
*boldface
;
3221 /* add Bold simulation based on heaviest face data */
3223 /* Simulated face name should only contain Bold as weight term,
3224 so remove existing regular and weight terms. */
3225 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3226 facename_remove_regular_term(initialW
, -1);
3228 /* remove current weight pattern */
3229 fontname_tokenize(&tokens
, initialW
);
3230 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3231 fontname_tokens_to_str(&tokens
, facenameW
);
3233 /* Bold suffix for new name */
3235 strcatW(facenameW
, spaceW
);
3236 strcatW(facenameW
, boldW
);
3238 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3239 boldface
->bold_sim_tested
= 1;
3240 fontfamily_add_font(family
, boldface
);
3246 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3250 for (i
= 0; i
< family
->font_count
; i
++) {
3251 UINT32 regular
= ~0u, oblique
= ~0u;
3252 struct dwrite_font_data
*obliqueface
;
3253 WCHAR facenameW
[255];
3255 if (family
->fonts
[i
]->oblique_sim_tested
)
3258 family
->fonts
[i
]->oblique_sim_tested
= 1;
3259 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3261 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3264 /* find regular style with same weight/stretch values */
3265 for (j
= i
; j
< family
->font_count
; j
++) {
3266 if (family
->fonts
[j
]->oblique_sim_tested
)
3269 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3270 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3272 family
->fonts
[j
]->oblique_sim_tested
= 1;
3273 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3276 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3280 if (regular
!= ~0u && oblique
!= ~0u)
3284 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3288 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3292 /* add oblique simulation based on this regular face */
3294 /* remove regular term if any, append 'Oblique' */
3295 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3296 facename_remove_regular_term(facenameW
, -1);
3299 strcatW(facenameW
, spaceW
);
3300 strcatW(facenameW
, obliqueW
);
3302 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3303 obliqueface
->oblique_sim_tested
= 1;
3304 fontfamily_add_font(family
, obliqueface
);
3309 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3310 const WCHAR
*replacement_name
)
3312 UINT32 i
= collection_find_family(collection
, replacement_name
);
3313 struct dwrite_fontfamily_data
*target
;
3314 IDWriteLocalizedStrings
*strings
;
3317 /* replacement does not exist */
3321 hr
= create_localizedstrings(&strings
);
3325 /* add a new family with target name, reuse font data from replacement */
3326 add_localizedstring(strings
, enusW
, target_name
);
3327 hr
= init_fontfamily_data(strings
, &target
);
3329 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3332 for (i
= 0; i
< replacement
->font_count
; i
++)
3333 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3335 fontcollection_add_family(collection
, target
);
3336 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3337 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3339 IDWriteLocalizedStrings_Release(strings
);
3343 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3344 system font collections. */
3345 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3347 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3352 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3355 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3360 max_namelen
++; /* returned value doesn't include room for '\0' */
3361 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3362 data
= heap_alloc(max_datalen
);
3364 datalen
= max_datalen
;
3365 namelen
= max_namelen
;
3366 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3367 if (collection_find_family(collection
, name
) == ~0u) {
3368 if (type
== REG_MULTI_SZ
) {
3369 WCHAR
*replacement
= data
;
3370 while (*replacement
) {
3371 if (fontcollection_add_replacement(collection
, name
, replacement
))
3373 replacement
+= strlenW(replacement
) + 1;
3376 else if (type
== REG_SZ
)
3377 fontcollection_add_replacement(collection
, name
, data
);
3380 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3382 datalen
= max_datalen
;
3383 namelen
= max_namelen
;
3391 HRESULT
create_font_collection(IDWriteFactory3
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
3393 struct fontfile_enum
{
3395 IDWriteFontFile
*file
;
3397 struct fontfile_enum
*fileenum
, *fileenum2
;
3398 struct dwrite_fontcollection
*collection
;
3399 struct list scannedfiles
;
3400 BOOL current
= FALSE
;
3406 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3407 if (!collection
) return E_OUTOFMEMORY
;
3409 hr
= init_font_collection(collection
, is_system
);
3411 heap_free(collection
);
3415 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3417 TRACE("building font collection:\n");
3419 list_init(&scannedfiles
);
3420 while (hr
== S_OK
) {
3421 DWRITE_FONT_FACE_TYPE face_type
;
3422 DWRITE_FONT_FILE_TYPE file_type
;
3423 BOOL supported
, same
= FALSE
;
3424 IDWriteFontFile
*file
;
3428 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3429 if (FAILED(hr
) || !current
)
3432 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3436 /* check if we've scanned this file already */
3437 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3438 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3443 IDWriteFontFile_Release(file
);
3447 /* failed font files are skipped */
3448 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3449 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3450 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3451 IDWriteFontFile_Release(file
);
3456 /* add to scanned list */
3457 fileenum
= heap_alloc(sizeof(*fileenum
));
3458 fileenum
->file
= file
;
3459 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3461 for (i
= 0; i
< face_count
; i
++) {
3462 IDWriteLocalizedStrings
*family_name
= NULL
;
3463 struct dwrite_font_data
*font_data
;
3467 /* alloc and init new font data structure */
3468 hr
= init_font_data(factory
, file
, face_type
, i
, &family_name
, &font_data
);
3470 /* move to next one */
3475 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3477 index
= collection_find_family(collection
, familyW
);
3479 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3481 struct dwrite_fontfamily_data
*family_data
;
3483 /* create and init new family */
3484 hr
= init_fontfamily_data(family_name
, &family_data
);
3486 /* add font to family, family - to collection */
3487 hr
= fontfamily_add_font(family_data
, font_data
);
3489 hr
= fontcollection_add_family(collection
, family_data
);
3492 release_fontfamily_data(family_data
);
3496 IDWriteLocalizedStrings_Release(family_name
);
3503 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3504 IDWriteFontFile_Release(fileenum
->file
);
3505 list_remove(&fileenum
->entry
);
3506 heap_free(fileenum
);
3509 for (i
= 0; i
< collection
->family_count
; i
++) {
3510 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3511 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3515 fontcollection_add_replacements(collection
);
3520 struct system_fontfile_enumerator
3522 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3525 IDWriteFactory3
*factory
;
3530 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3532 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3535 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3539 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3540 IDWriteFontFileEnumerator_AddRef(iface
);
3545 return E_NOINTERFACE
;
3548 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3550 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3551 return InterlockedIncrement(&enumerator
->ref
);
3554 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3556 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3557 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3560 IDWriteFactory3_Release(enumerator
->factory
);
3561 RegCloseKey(enumerator
->hkey
);
3562 heap_free(enumerator
);
3568 static HRESULT
create_local_file_reference(IDWriteFactory3
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3572 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3573 if (!strchrW(filename
, '\\')) {
3574 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3575 WCHAR fullpathW
[MAX_PATH
];
3577 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3578 strcatW(fullpathW
, fontsW
);
3579 strcatW(fullpathW
, filename
);
3581 hr
= IDWriteFactory3_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3584 hr
= IDWriteFactory3_CreateFontFileReference(factory
, filename
, NULL
, file
);
3589 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3591 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3592 DWORD ret
, type
, val_count
, count
;
3593 WCHAR
*value
, *filename
;
3598 if (enumerator
->index
< 0)
3601 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3602 if (ret
!= ERROR_SUCCESS
)
3606 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3607 filename
= heap_alloc(count
);
3608 if (!value
|| !filename
) {
3610 heap_free(filename
);
3611 return E_OUTOFMEMORY
;
3614 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3617 heap_free(filename
);
3621 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3624 heap_free(filename
);
3628 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3630 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3631 DWORD ret
, max_val_count
;
3635 enumerator
->index
++;
3637 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
3638 if (ret
!= ERROR_SUCCESS
)
3642 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
3643 return E_OUTOFMEMORY
;
3645 /* iterate until we find next string value */
3647 DWORD type
= 0, count
, val_count
;
3648 val_count
= max_val_count
;
3649 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
3651 if (type
== REG_SZ
) {
3655 enumerator
->index
++;
3658 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3663 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3665 systemfontfileenumerator_QueryInterface
,
3666 systemfontfileenumerator_AddRef
,
3667 systemfontfileenumerator_Release
,
3668 systemfontfileenumerator_MoveNext
,
3669 systemfontfileenumerator_GetCurrentFontFile
3672 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory3
*factory
, IDWriteFontFileEnumerator
**ret
)
3674 struct system_fontfile_enumerator
*enumerator
;
3675 static const WCHAR fontslistW
[] = {
3676 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3677 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3678 'F','o','n','t','s',0
3683 enumerator
= heap_alloc(sizeof(*enumerator
));
3685 return E_OUTOFMEMORY
;
3687 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3688 enumerator
->ref
= 1;
3689 enumerator
->factory
= factory
;
3690 enumerator
->index
= -1;
3691 IDWriteFactory3_AddRef(factory
);
3693 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3694 ERR("failed to open fonts list key\n");
3695 IDWriteFactory3_Release(factory
);
3696 heap_free(enumerator
);
3700 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3705 HRESULT
get_system_fontcollection(IDWriteFactory3
*factory
, IDWriteFontCollection
**collection
)
3707 IDWriteFontFileEnumerator
*enumerator
;
3712 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3716 TRACE("building system font collection for factory %p\n", factory
);
3717 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3718 IDWriteFontFileEnumerator_Release(enumerator
);
3722 static HRESULT
eudc_collection_add_family(IDWriteFactory3
*factory
, struct dwrite_fontcollection
*collection
,
3723 const WCHAR
*keynameW
, const WCHAR
*pathW
)
3725 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};
3726 static const WCHAR emptyW
[] = {0};
3727 IDWriteLocalizedStrings
*names
;
3728 DWRITE_FONT_FACE_TYPE face_type
;
3729 DWRITE_FONT_FILE_TYPE file_type
;
3731 UINT32 face_count
, i
;
3732 IDWriteFontFile
*file
;
3734 struct dwrite_fontfamily_data
*family_data
;
3736 /* create font file from this path */
3737 hr
= create_local_file_reference(factory
, pathW
, &file
);
3741 /* failed font files are skipped */
3742 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3743 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3744 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3745 IDWriteFontFile_Release(file
);
3749 /* create and init new family */
3751 /* Family names are added for non-specific locale, represented with empty string.
3752 Default family appears with empty family name. */
3753 create_localizedstrings(&names
);
3754 if (!strcmpiW(keynameW
, defaultfontW
))
3755 add_localizedstring(names
, emptyW
, emptyW
);
3757 add_localizedstring(names
, emptyW
, keynameW
);
3759 hr
= init_fontfamily_data(names
, &family_data
);
3760 IDWriteLocalizedStrings_Release(names
);
3762 IDWriteFontFile_Release(file
);
3766 /* fill with faces */
3767 for (i
= 0; i
< face_count
; i
++) {
3768 struct dwrite_font_data
*font_data
;
3770 /* alloc and init new font data structure */
3771 hr
= init_font_data(factory
, file
, face_type
, i
, &names
, &font_data
);
3775 IDWriteLocalizedStrings_Release(names
);
3777 /* add font to family */
3778 hr
= fontfamily_add_font(family_data
, font_data
);
3780 release_font_data(font_data
);
3783 /* add family to collection */
3784 hr
= fontcollection_add_family(collection
, family_data
);
3786 release_fontfamily_data(family_data
);
3787 IDWriteFontFile_Release(file
);
3792 HRESULT
get_eudc_fontcollection(IDWriteFactory3
*factory
, IDWriteFontCollection
**ret
)
3794 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
3795 struct dwrite_fontcollection
*collection
;
3796 static const WCHAR emptyW
[] = {0};
3797 WCHAR eudckeypathW
[16];
3805 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
3809 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3810 if (!collection
) return E_OUTOFMEMORY
;
3812 hr
= init_font_collection(collection
, FALSE
);
3814 heap_free(collection
);
3818 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3820 /* return empty collection if EUDC fonts are not configured */
3821 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
3822 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
3825 retval
= ERROR_SUCCESS
;
3827 while (retval
!= ERROR_NO_MORE_ITEMS
) {
3828 WCHAR keynameW
[64], pathW
[MAX_PATH
];
3829 DWORD type
, path_len
, name_len
;
3831 path_len
= sizeof(pathW
)/sizeof(*pathW
);
3832 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
3833 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
3834 if (retval
|| type
!= REG_SZ
)
3837 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
3839 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
3841 RegCloseKey(eudckey
);
3843 /* try to add global default if not defined for specific codepage */
3845 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
3847 if (FAILED(hr
) || !exists
) {
3848 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
3849 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
3851 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
3854 /* EUDC collection offers simulated faces too */
3855 for (i
= 0; i
< collection
->family_count
; i
++) {
3856 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3857 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3863 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
3865 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3867 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3869 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
3872 IDWriteFontFile_AddRef(iface
);
3877 return E_NOINTERFACE
;
3880 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
3882 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3883 ULONG ref
= InterlockedIncrement(&This
->ref
);
3884 TRACE("(%p)->(%d)\n", This
, ref
);
3888 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
3890 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3891 ULONG ref
= InterlockedDecrement(&This
->ref
);
3893 TRACE("(%p)->(%d)\n", This
, ref
);
3897 IDWriteFontFileLoader_Release(This
->loader
);
3898 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
3899 heap_free(This
->reference_key
);
3906 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
3908 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3909 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
3910 *fontFileReferenceKey
= This
->reference_key
;
3911 *fontFileReferenceKeySize
= This
->key_size
;
3916 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
3918 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3919 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
3920 *fontFileLoader
= This
->loader
;
3921 IDWriteFontFileLoader_AddRef(This
->loader
);
3926 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
3927 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
3929 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3930 IDWriteFontFileStream
*stream
;
3933 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
3935 *isSupportedFontType
= FALSE
;
3936 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3938 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3941 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
3945 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
3947 /* TODO: Further Analysis */
3948 IDWriteFontFileStream_Release(stream
);
3952 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
3953 dwritefontfile_QueryInterface
,
3954 dwritefontfile_AddRef
,
3955 dwritefontfile_Release
,
3956 dwritefontfile_GetReferenceKey
,
3957 dwritefontfile_GetLoader
,
3958 dwritefontfile_Analyze
,
3961 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
3963 struct dwrite_fontfile
*This
;
3965 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
3966 if (!This
) return E_OUTOFMEMORY
;
3968 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
3970 IDWriteFontFileLoader_AddRef(loader
);
3971 This
->loader
= loader
;
3972 This
->stream
= NULL
;
3973 This
->reference_key
= heap_alloc(key_size
);
3974 memcpy(This
->reference_key
, reference_key
, key_size
);
3975 This
->key_size
= key_size
;
3977 *font_file
= &This
->IDWriteFontFile_iface
;
3982 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3984 IDWriteFontFileLoader
*loader
;
3990 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3994 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3996 IDWriteFontFileLoader_Release(loader
);
4000 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
4001 IDWriteFontFileLoader_Release(loader
);
4006 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
4007 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
4009 struct dwrite_fontface
*fontface
;
4015 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
4017 return E_OUTOFMEMORY
;
4019 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
4020 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
4022 if (!fontface
->files
|| !fontface
->streams
) {
4023 heap_free(fontface
->files
);
4024 heap_free(fontface
->streams
);
4025 heap_free(fontface
);
4026 return E_OUTOFMEMORY
;
4029 fontface
->IDWriteFontFace3_iface
.lpVtbl
= &dwritefontfacevtbl
;
4031 fontface
->type
= facetype
;
4032 fontface
->file_count
= files_number
;
4033 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
4034 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
4035 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
4036 memset(&fontface
->cpal
, 0, sizeof(fontface
->cpal
));
4037 memset(&fontface
->colr
, 0, sizeof(fontface
->colr
));
4038 fontface
->cmap
.exists
= TRUE
;
4039 fontface
->vdmx
.exists
= TRUE
;
4040 fontface
->gasp
.exists
= TRUE
;
4041 fontface
->cpal
.exists
= TRUE
;
4042 fontface
->colr
.exists
= TRUE
;
4043 fontface
->index
= index
;
4044 fontface
->simulations
= simulations
;
4045 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
4047 for (i
= 0; i
< fontface
->file_count
; i
++) {
4048 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
4050 IDWriteFontFace3_Release(&fontface
->IDWriteFontFace3_iface
);
4054 fontface
->files
[i
] = font_files
[i
];
4055 IDWriteFontFile_AddRef(font_files
[i
]);
4058 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
4059 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4060 /* TODO: test what happens if caret is already slanted */
4061 if (fontface
->caret
.slopeRise
== 1) {
4062 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4063 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4066 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace3_iface
, &fontface
->is_symbol
);
4067 fontface
->has_kerning_pairs
= freetype_has_kerning_pairs(&fontface
->IDWriteFontFace3_iface
);
4068 fontface
->is_monospaced
= freetype_is_monospaced(&fontface
->IDWriteFontFace3_iface
);
4070 *ret
= &fontface
->IDWriteFontFace3_iface
;
4074 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4081 struct local_cached_stream
4084 IDWriteFontFileStream
*stream
;
4085 struct local_refkey
*key
;
4089 struct dwrite_localfontfilestream
4091 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4094 struct local_cached_stream
*entry
;
4095 const void *file_ptr
;
4099 struct dwrite_localfontfileloader
{
4100 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4103 struct list streams
;
4106 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4108 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4111 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4113 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4116 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4118 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4119 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4120 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
4123 IDWriteFontFileStream_AddRef(iface
);
4128 return E_NOINTERFACE
;
4131 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4133 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4134 ULONG ref
= InterlockedIncrement(&This
->ref
);
4135 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4139 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4141 list_remove(&stream
->entry
);
4142 heap_free(stream
->key
);
4146 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4148 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4149 ULONG ref
= InterlockedDecrement(&This
->ref
);
4151 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4154 UnmapViewOfFile(This
->file_ptr
);
4155 release_cached_stream(This
->entry
);
4162 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4164 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4166 TRACE_(dwrite_file
)("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
4167 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4169 *fragment_context
= NULL
;
4171 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4172 *fragment_start
= NULL
;
4176 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4180 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4182 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4183 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4186 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4188 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4189 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4194 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4196 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4199 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4201 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4202 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4203 *last_writetime
= li
.QuadPart
;
4208 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4210 localfontfilestream_QueryInterface
,
4211 localfontfilestream_AddRef
,
4212 localfontfilestream_Release
,
4213 localfontfilestream_ReadFileFragment
,
4214 localfontfilestream_ReleaseFileFragment
,
4215 localfontfilestream_GetFileSize
,
4216 localfontfilestream_GetLastWriteTime
4219 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4221 struct dwrite_localfontfilestream
*This
;
4225 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4227 return E_OUTOFMEMORY
;
4229 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4232 This
->file_ptr
= file_ptr
;
4234 This
->entry
= entry
;
4236 *ret
= &This
->IDWriteFontFileStream_iface
;
4240 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4242 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4244 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4246 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
4249 IDWriteLocalFontFileLoader_AddRef(iface
);
4254 return E_NOINTERFACE
;
4257 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4259 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4260 ULONG ref
= InterlockedIncrement(&This
->ref
);
4261 TRACE("(%p)->(%d)\n", This
, ref
);
4265 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4267 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4268 ULONG ref
= InterlockedDecrement(&This
->ref
);
4270 TRACE("(%p)->(%d)\n", This
, ref
);
4273 struct local_cached_stream
*stream
, *stream2
;
4275 /* This will detach all entries from cache. Entries are released together with streams,
4276 so stream controls cache entry lifetime. */
4277 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
4278 list_init(&stream
->entry
);
4286 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
4288 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4289 const struct local_refkey
*refkey
= key
;
4290 struct local_cached_stream
*stream
;
4291 IDWriteFontFileStream
*filestream
;
4292 HANDLE file
, mapping
;
4297 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
4298 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4300 /* search cache first */
4301 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4302 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4303 *ret
= stream
->stream
;
4304 IDWriteFontFileStream_AddRef(*ret
);
4311 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4312 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4313 if (file
== INVALID_HANDLE_VALUE
)
4316 GetFileSizeEx(file
, &size
);
4317 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4322 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4323 CloseHandle(mapping
);
4325 stream
= heap_alloc(sizeof(*stream
));
4327 UnmapViewOfFile(file_ptr
);
4328 return E_OUTOFMEMORY
;
4331 stream
->key
= heap_alloc(key_size
);
4333 UnmapViewOfFile(file_ptr
);
4335 return E_OUTOFMEMORY
;
4338 stream
->key_size
= key_size
;
4339 memcpy(stream
->key
, key
, key_size
);
4341 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4343 UnmapViewOfFile(file_ptr
);
4344 heap_free(stream
->key
);
4349 stream
->stream
= filestream
;
4350 list_add_head(&This
->streams
, &stream
->entry
);
4352 *ret
= stream
->stream
;
4357 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4359 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4360 const struct local_refkey
*refkey
= key
;
4362 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4364 *length
= strlenW(refkey
->name
);
4368 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4370 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4371 const struct local_refkey
*refkey
= key
;
4373 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4375 if (length
< strlenW(refkey
->name
))
4376 return E_INVALIDARG
;
4378 strcpyW(path
, refkey
->name
);
4382 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
4384 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4385 const struct local_refkey
*refkey
= key
;
4387 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
4389 *writetime
= refkey
->writetime
;
4393 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4394 localfontfileloader_QueryInterface
,
4395 localfontfileloader_AddRef
,
4396 localfontfileloader_Release
,
4397 localfontfileloader_CreateStreamFromKey
,
4398 localfontfileloader_GetFilePathLengthFromKey
,
4399 localfontfileloader_GetFilePathFromKey
,
4400 localfontfileloader_GetLastWriteTimeFromKey
4403 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
**ret
)
4405 struct dwrite_localfontfileloader
*This
;
4409 This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
4411 return E_OUTOFMEMORY
;
4413 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4415 list_init(&This
->streams
);
4417 *ret
= &This
->IDWriteLocalFontFileLoader_iface
;
4421 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4423 struct local_refkey
*refkey
;
4426 return E_INVALIDARG
;
4428 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4431 refkey
= heap_alloc(*size
);
4433 return E_OUTOFMEMORY
;
4436 refkey
->writetime
= *writetime
;
4438 WIN32_FILE_ATTRIBUTE_DATA info
;
4440 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4441 refkey
->writetime
= info
.ftLastWriteTime
;
4443 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4445 strcpyW(refkey
->name
, path
);
4452 /* IDWriteGlyphRunAnalysis */
4453 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4455 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4457 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4459 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4460 IsEqualIID(riid
, &IID_IUnknown
))
4463 IDWriteGlyphRunAnalysis_AddRef(iface
);
4468 return E_NOINTERFACE
;
4471 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4473 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4474 ULONG ref
= InterlockedIncrement(&This
->ref
);
4475 TRACE("(%p)->(%u)\n", This
, ref
);
4479 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4481 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4482 ULONG ref
= InterlockedDecrement(&This
->ref
);
4484 TRACE("(%p)->(%u)\n", This
, ref
);
4487 if (This
->run
.fontFace
)
4488 IDWriteFontFace_Release(This
->run
.fontFace
);
4489 heap_free(This
->glyphs
);
4490 heap_free(This
->advances
);
4491 heap_free(This
->advanceoffsets
);
4492 heap_free(This
->ascenderoffsets
);
4493 heap_free(This
->bitmap
);
4500 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4502 struct dwrite_glyphbitmap glyph_bitmap
;
4503 IDWriteFontFace3
*fontface3
;
4504 D2D_POINT_2F origin
;
4509 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4510 *bounds
= analysis
->bounds
;
4514 if (analysis
->run
.isSideways
)
4515 FIXME("sideways runs are not supported.\n");
4517 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
4519 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4521 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
4522 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
4523 for any non-zero glyph ascender */
4524 origin
.x
= origin
.y
= 0.0f
;
4525 is_rtl
= analysis
->run
.bidiLevel
& 1;
4527 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4528 glyph_bitmap
.fontface
= fontface3
;
4529 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4530 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4531 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4532 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4533 glyph_bitmap
.m
= &analysis
->m
;
4535 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4536 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4537 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4538 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4539 RECT
*bbox
= &glyph_bitmap
.bbox
;
4541 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4542 freetype_get_glyph_bbox(&glyph_bitmap
);
4545 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4547 OffsetRect(bbox
, origin
.x
, origin
.y
);
4550 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4552 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4553 origin
.x
+= advance
->x
;
4554 origin
.y
+= advance
->y
;
4557 IDWriteFontFace3_Release(fontface3
);
4559 /* translate to given run origin */
4560 OffsetRect(&analysis
->bounds
, analysis
->origin
.x
, analysis
->origin
.y
);
4561 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4562 OffsetRect(&analysis
->bounds
, analysis
->m
.dx
, analysis
->m
.dy
);
4564 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4565 *bounds
= analysis
->bounds
;
4568 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4570 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4572 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4574 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4575 memset(bounds
, 0, sizeof(*bounds
));
4576 return E_INVALIDARG
;
4579 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
4580 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
4581 memset(bounds
, 0, sizeof(*bounds
));
4585 glyphrunanalysis_get_texturebounds(This
, bounds
);
4589 static inline int get_dib_stride( int width
, int bpp
)
4591 return ((width
* bpp
+ 31) >> 3) & ~3;
4594 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4596 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4597 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4598 (runbounds
->left
- bounds
->left
) * 3;
4600 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4601 runbounds
->left
- bounds
->left
;
4604 static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
, DWRITE_TEXTURE_TYPE type
)
4606 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4607 struct dwrite_glyphbitmap glyph_bitmap
;
4608 IDWriteFontFace3
*fontface2
;
4609 D2D_POINT_2F origin
;
4615 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface2
);
4617 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4621 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4622 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4624 analysis
->bitmap
= heap_alloc_zero(size
);
4626 origin
.x
= origin
.y
= 0.0f
;
4627 is_rtl
= analysis
->run
.bidiLevel
& 1;
4629 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4630 glyph_bitmap
.fontface
= fontface2
;
4631 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4632 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4633 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4634 glyph_bitmap
.type
= type
;
4635 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4636 glyph_bitmap
.m
= &analysis
->m
;
4637 bbox
= &glyph_bitmap
.bbox
;
4639 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4640 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4641 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4642 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4643 int x
, y
, width
, height
;
4647 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4648 freetype_get_glyph_bbox(&glyph_bitmap
);
4650 if (IsRectEmpty(bbox
)) {
4651 origin
.x
+= advance
->x
;
4652 origin
.y
+= advance
->y
;
4656 width
= bbox
->right
- bbox
->left
;
4657 height
= bbox
->bottom
- bbox
->top
;
4659 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4660 glyph_bitmap
.pitch
= (width
+ 3) / 4 * 4;
4662 glyph_bitmap
.pitch
= ((width
+ 31) >> 5) << 2;
4664 glyph_bitmap
.buf
= src
= heap_alloc_zero(height
* glyph_bitmap
.pitch
);
4665 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4668 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4670 OffsetRect(bbox
, origin
.x
, origin
.y
);
4673 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4675 OffsetRect(bbox
, analysis
->origin
.x
, analysis
->origin
.y
);
4676 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4677 OffsetRect(bbox
, analysis
->m
.dx
, analysis
->m
.dy
);
4679 /* blit to analysis bitmap */
4680 dst
= get_pixel_ptr(analysis
->bitmap
, type
, bbox
, &analysis
->bounds
);
4683 /* convert 1bpp to 8bpp/24bpp */
4684 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4685 for (y
= 0; y
< height
; y
++) {
4686 for (x
= 0; x
< width
; x
++)
4687 if (src
[x
/ 8] & masks
[x
% 8])
4688 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4689 src
+= glyph_bitmap
.pitch
;
4690 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4694 for (y
= 0; y
< height
; y
++) {
4695 for (x
= 0; x
< width
; x
++)
4696 if (src
[x
/ 8] & masks
[x
% 8])
4697 dst
[x
] = DWRITE_ALPHA_MAX
;
4698 src
+= get_dib_stride(width
, 1);
4699 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
4704 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
4705 for (y
= 0; y
< height
; y
++) {
4706 for (x
= 0; x
< width
; x
++)
4707 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
4708 src
+= glyph_bitmap
.pitch
;
4709 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4713 heap_free(glyph_bitmap
.buf
);
4715 origin
.x
+= advance
->x
;
4716 origin
.y
+= advance
->y
;
4719 IDWriteFontFace3_Release(fontface2
);
4721 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
4723 /* we don't need this anymore */
4724 heap_free(analysis
->glyphs
);
4725 heap_free(analysis
->advances
);
4726 heap_free(analysis
->advanceoffsets
);
4727 heap_free(analysis
->ascenderoffsets
);
4728 IDWriteFontFace_Release(analysis
->run
.fontFace
);
4730 analysis
->glyphs
= NULL
;
4731 analysis
->advances
= NULL
;
4732 analysis
->advanceoffsets
= NULL
;
4733 analysis
->ascenderoffsets
= NULL
;
4734 analysis
->run
.glyphIndices
= NULL
;
4735 analysis
->run
.fontFace
= NULL
;
4738 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
4739 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
4741 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4745 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
4747 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
4748 return E_INVALIDARG
;
4750 /* make sure buffer is large enough for requested texture type */
4751 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
4752 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4755 if (size
< required
)
4756 return E_NOT_SUFFICIENT_BUFFER
;
4758 /* validate requested texture type with rendering mode */
4759 switch (This
->rendering_mode
)
4761 case DWRITE_RENDERING_MODE_ALIASED
:
4762 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
4763 return DWRITE_E_UNSUPPORTEDOPERATION
;
4765 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4766 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4767 case DWRITE_RENDERING_MODE_NATURAL
:
4768 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4769 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
4770 return DWRITE_E_UNSUPPORTEDOPERATION
;
4776 memset(bitmap
, 0, size
);
4777 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
4778 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
4779 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
4780 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
4781 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
4782 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
4786 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
))
4787 glyphrunanalysis_render(This
, type
);
4789 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
4790 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
4792 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
4793 memcpy(dst
, src
, draw_width
);
4802 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
4803 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
4805 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4807 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
4810 return E_INVALIDARG
;
4812 switch (This
->rendering_mode
)
4814 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4815 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4818 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
4819 *gamma
= (FLOAT
)value
/ 1000.0f
;
4821 *cleartypelevel
= 1.0f
;
4824 case DWRITE_RENDERING_MODE_ALIASED
:
4825 case DWRITE_RENDERING_MODE_NATURAL
:
4826 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4827 *gamma
= IDWriteRenderingParams_GetGamma(params
);
4828 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
4829 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
4838 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
4839 glyphrunanalysis_QueryInterface
,
4840 glyphrunanalysis_AddRef
,
4841 glyphrunanalysis_Release
,
4842 glyphrunanalysis_GetAlphaTextureBounds
,
4843 glyphrunanalysis_CreateAlphaTexture
,
4844 glyphrunanalysis_GetAlphaBlendParams
4847 static inline void init_2d_vec(D2D_POINT_2F
*vec
, FLOAT length
, BOOL is_vertical
)
4859 static inline void transform_2d_vec(D2D_POINT_2F
*vec
, const DWRITE_MATRIX
*m
)
4862 ret
.x
= vec
->x
* m
->m11
+ vec
->y
* m
->m21
;
4863 ret
.y
= vec
->x
* m
->m12
+ vec
->y
* m
->m22
;
4867 HRESULT
create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_GLYPH_RUN
const *run
,
4868 FLOAT ppdip
, const DWRITE_MATRIX
*transform
, DWRITE_GRID_FIT_MODE gridfit_mode
, DWRITE_TEXT_ANTIALIAS_MODE aa_mode
,
4869 FLOAT originX
, FLOAT originY
, IDWriteGlyphRunAnalysis
**ret
)
4871 struct dwrite_glyphrunanalysis
*analysis
;
4877 /* check for valid rendering mode */
4878 if ((UINT32
)rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
4879 return E_INVALIDARG
;
4881 analysis
= heap_alloc(sizeof(*analysis
));
4883 return E_OUTOFMEMORY
;
4885 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
4887 analysis
->rendering_mode
= rendering_mode
;
4888 analysis
->flags
= 0;
4889 analysis
->bitmap
= NULL
;
4890 analysis
->ppdip
= ppdip
;
4891 analysis
->origin
.x
= originX
* ppdip
;
4892 analysis
->origin
.y
= originY
* ppdip
;
4893 SetRectEmpty(&analysis
->bounds
);
4894 analysis
->run
= *run
;
4895 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
4896 analysis
->glyphs
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphIndices
));
4897 analysis
->advances
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advances
));
4898 if (run
->glyphOffsets
) {
4899 analysis
->advanceoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advanceoffsets
));
4900 analysis
->ascenderoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->ascenderoffsets
));
4903 analysis
->advanceoffsets
= NULL
;
4904 analysis
->ascenderoffsets
= NULL
;
4907 if (!analysis
->glyphs
|| !analysis
->advances
|| ((!analysis
->advanceoffsets
|| !analysis
->ascenderoffsets
) && run
->glyphOffsets
)) {
4908 heap_free(analysis
->glyphs
);
4909 heap_free(analysis
->advances
);
4910 heap_free(analysis
->advanceoffsets
);
4911 heap_free(analysis
->ascenderoffsets
);
4913 analysis
->glyphs
= NULL
;
4914 analysis
->advances
= NULL
;
4915 analysis
->advanceoffsets
= NULL
;
4916 analysis
->ascenderoffsets
= NULL
;
4918 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
4919 return E_OUTOFMEMORY
;
4922 /* check if transform is usable */
4923 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
))) {
4924 analysis
->m
= *transform
;
4925 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
4928 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
4930 analysis
->run
.glyphIndices
= analysis
->glyphs
;
4931 analysis
->run
.glyphAdvances
= NULL
;
4932 analysis
->run
.glyphOffsets
= NULL
;
4934 rtl_factor
= run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
4936 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4937 transform_2d_vec(&analysis
->origin
, &analysis
->m
);
4939 memcpy(analysis
->glyphs
, run
->glyphIndices
, run
->glyphCount
*sizeof(*run
->glyphIndices
));
4941 if (run
->glyphAdvances
) {
4942 for (i
= 0; i
< run
->glyphCount
; i
++) {
4943 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* run
->glyphAdvances
[i
] * ppdip
, run
->isSideways
);
4944 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4945 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4949 DWRITE_FONT_METRICS metrics
;
4950 IDWriteFontFace1
*fontface1
;
4952 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
4953 IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4955 for (i
= 0; i
< run
->glyphCount
; i
++) {
4959 switch (measuring_mode
)
4961 case DWRITE_MEASURING_MODE_NATURAL
:
4962 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
4965 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
) * ppdip
,
4968 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
4969 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
4970 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, run
->fontEmSize
, ppdip
, transform
,
4971 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
4973 init_2d_vec(analysis
->advances
+ i
, 0.0f
, FALSE
);
4975 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* floorf(a
* run
->fontEmSize
* ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
),
4982 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4983 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4986 IDWriteFontFace1_Release(fontface1
);
4989 if (run
->glyphOffsets
) {
4990 for (i
= 0; i
< run
->glyphCount
; i
++) {
4991 init_2d_vec(analysis
->advanceoffsets
+ i
, rtl_factor
* run
->glyphOffsets
[i
].advanceOffset
* ppdip
, run
->isSideways
);
4992 /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
4993 init_2d_vec(analysis
->ascenderoffsets
+ i
, -run
->glyphOffsets
[i
].ascenderOffset
* ppdip
, !run
->isSideways
);
4994 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
) {
4995 transform_2d_vec(analysis
->advanceoffsets
+ i
, &analysis
->m
);
4996 transform_2d_vec(analysis
->ascenderoffsets
+ i
, &analysis
->m
);
5001 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5005 /* IDWriteColorGlyphRunEnumerator */
5006 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
5008 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5010 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5012 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5013 IsEqualIID(riid
, &IID_IUnknown
))
5016 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
5021 return E_NOINTERFACE
;
5024 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
5026 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5027 ULONG ref
= InterlockedIncrement(&This
->ref
);
5028 TRACE("(%p)->(%u)\n", This
, ref
);
5032 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
5034 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5035 ULONG ref
= InterlockedDecrement(&This
->ref
);
5037 TRACE("(%p)->(%u)\n", This
, ref
);
5040 heap_free(This
->advances
);
5041 heap_free(This
->color_advances
);
5042 heap_free(This
->offsets
);
5043 heap_free(This
->color_offsets
);
5044 heap_free(This
->glyphindices
);
5045 heap_free(This
->glyphs
);
5046 if (This
->colr
.context
)
5047 IDWriteFontFace3_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
5048 IDWriteFontFace3_Release(This
->fontface
);
5055 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5057 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5058 FLOAT origin
= 0.0f
;
5064 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5068 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5070 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5071 FLOAT advance_adj
= 0.0f
;
5072 BOOL got_palette_index
;
5075 /* start with regular glyphs */
5076 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5077 UINT32 first_glyph
= 0;
5079 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5080 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5081 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5082 first_glyph
= min(first_glyph
, g
);
5085 glyphenum
->glyphindices
[g
] = 1;
5086 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5087 if (glyphenum
->color_offsets
)
5088 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5091 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5092 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5093 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5094 colorrun
->paletteIndex
= 0xffff;
5095 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5096 glyphenum
->has_regular_glyphs
= FALSE
;
5100 colorrun
->glyphRun
.glyphCount
= 0;
5101 got_palette_index
= FALSE
;
5105 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5107 glyphenum
->glyphindices
[g
] = 1;
5109 /* all glyph layers were returned */
5110 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5111 advance_adj
+= glyphenum
->advances
[g
];
5115 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5116 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5117 if (!got_palette_index
) {
5118 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5119 /* use foreground color or request one from the font */
5120 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5121 if (colorrun
->paletteIndex
!= 0xffff) {
5122 HRESULT hr
= IDWriteFontFace3_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5123 1, &colorrun
->runColor
);
5125 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5126 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5128 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5129 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5130 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5131 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5132 got_palette_index
= TRUE
;
5135 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5136 /* offsets are relative to glyph origin, nothing to fix up */
5137 if (glyphenum
->color_offsets
)
5138 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5139 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5141 glyphenum
->color_advances
[index
-1] += advance_adj
;
5142 colorrun
->glyphRun
.glyphCount
++;
5146 advance_adj
+= glyphenum
->advances
[g
];
5149 /* reset last advance */
5150 if (colorrun
->glyphRun
.glyphCount
)
5151 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5153 return colorrun
->glyphRun
.glyphCount
> 0;
5156 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5158 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5160 TRACE("(%p)->(%p)\n", This
, has_run
);
5164 This
->colorrun
.glyphRun
.glyphCount
= 0;
5165 while (This
->current_layer
< This
->max_layer_num
) {
5166 if (colorglyphenum_build_color_run(This
))
5169 This
->current_layer
++;
5172 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5177 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5179 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5181 TRACE("(%p)->(%p)\n", This
, run
);
5183 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5185 return E_NOT_VALID_STATE
;
5188 *run
= &This
->colorrun
;
5192 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5193 colorglyphenum_QueryInterface
,
5194 colorglyphenum_AddRef
,
5195 colorglyphenum_Release
,
5196 colorglyphenum_MoveNext
,
5197 colorglyphenum_GetCurrentRun
5200 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5201 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5203 struct dwrite_colorglyphenum
*colorglyphenum
;
5204 BOOL colorfont
, has_colored_glyph
;
5205 IDWriteFontFace3
*fontface3
;
5211 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
5213 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
5217 colorfont
= IDWriteFontFace3_IsColorFont(fontface3
) && IDWriteFontFace3_GetColorPaletteCount(fontface3
) > palette
;
5219 hr
= DWRITE_E_NOCOLOR
;
5223 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5224 if (!colorglyphenum
) {
5229 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5230 colorglyphenum
->ref
= 1;
5231 colorglyphenum
->origin_x
= originX
;
5232 colorglyphenum
->origin_y
= originY
;
5233 colorglyphenum
->fontface
= fontface3
;
5234 colorglyphenum
->glyphs
= NULL
;
5235 colorglyphenum
->run
= *run
;
5236 colorglyphenum
->run
.glyphIndices
= NULL
;
5237 colorglyphenum
->run
.glyphAdvances
= NULL
;
5238 colorglyphenum
->run
.glyphOffsets
= NULL
;
5239 colorglyphenum
->palette
= palette
;
5240 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5241 colorglyphenum
->colr
.exists
= TRUE
;
5242 get_fontface_table(fontface3
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5243 colorglyphenum
->current_layer
= 0;
5244 colorglyphenum
->max_layer_num
= 0;
5246 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5248 has_colored_glyph
= FALSE
;
5249 colorglyphenum
->has_regular_glyphs
= FALSE
;
5250 for (i
= 0; i
< run
->glyphCount
; i
++) {
5251 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5252 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5253 has_colored_glyph
= TRUE
;
5255 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5256 colorglyphenum
->has_regular_glyphs
= TRUE
;
5259 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5260 is supposed to proceed normally, like if font had no color info at all. */
5261 if (!has_colored_glyph
) {
5262 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5263 return DWRITE_E_NOCOLOR
;
5266 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5267 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5268 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5269 if (run
->glyphOffsets
) {
5270 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5271 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5272 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5275 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5276 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5277 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5278 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5280 if (run
->glyphAdvances
)
5281 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5283 DWRITE_FONT_METRICS metrics
;
5285 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5286 for (i
= 0; i
< run
->glyphCount
; i
++) {
5290 switch (measuring_mode
)
5292 case DWRITE_MEASURING_MODE_NATURAL
:
5293 hr
= IDWriteFontFace3_GetDesignGlyphAdvances(fontface3
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5296 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5298 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5299 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5300 hr
= IDWriteFontFace3_GetGdiCompatibleGlyphAdvances(fontface3
, run
->fontEmSize
, 1.0f
, transform
,
5301 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5303 colorglyphenum
->advances
[i
] = 0.0f
;
5305 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5313 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5317 IDWriteFontFace3_Release(fontface3
);
5321 /* IDWriteFontFaceReference */
5322 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
5324 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5326 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5328 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) || IsEqualIID(riid
, &IID_IUnknown
)) {
5330 IDWriteFontFaceReference_AddRef(iface
);
5336 return E_NOINTERFACE
;
5339 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference
*iface
)
5341 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5342 ULONG ref
= InterlockedIncrement(&This
->ref
);
5343 TRACE("(%p)->(%u)\n", This
, ref
);
5347 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference
*iface
)
5349 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5350 ULONG ref
= InterlockedDecrement(&This
->ref
);
5352 TRACE("(%p)->(%u)\n", This
, ref
);
5355 IDWriteFontFile_Release(This
->file
);
5356 IDWriteFactory3_Release(This
->factory
);
5363 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference
*iface
, IDWriteFontFace3
**fontface
)
5365 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5367 TRACE("(%p)->(%p)\n", This
, fontface
);
5369 return IDWriteFontFaceReference_CreateFontFaceWithSimulations(iface
, This
->simulations
, fontface
);
5372 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
5373 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
5375 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5376 DWRITE_FONT_FILE_TYPE file_type
;
5377 DWRITE_FONT_FACE_TYPE face_type
;
5378 IDWriteFontFace
*fontface
;
5383 TRACE("(%p)->(%d %p)\n", This
, simulations
, ret
);
5385 hr
= IDWriteFontFile_Analyze(This
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
5389 hr
= IDWriteFactory3_CreateFontFace(This
->factory
, face_type
, 1, &This
->file
, This
->index
, simulations
, &fontface
);
5390 if (SUCCEEDED(hr
)) {
5391 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)ret
);
5392 IDWriteFontFace_Release(fontface
);
5398 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
5400 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5401 IDWriteFontFile
*file
;
5404 TRACE("(%p)->(%p)\n", This
, ref
);
5406 if (FAILED(IDWriteFontFaceReference_GetFontFile(ref
, &file
)))
5409 ret
= is_same_fontfile(This
->file
, file
);
5410 IDWriteFontFile_Release(file
);
5415 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
5417 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5419 TRACE("(%p)\n", This
);
5424 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference
*iface
)
5426 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5428 TRACE("(%p)\n", This
);
5430 return This
->simulations
;
5433 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
5435 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5436 IDWriteFontFileLoader
*loader
;
5441 TRACE("(%p)->(%p)\n", This
, file
);
5443 hr
= IDWriteFontFile_GetReferenceKey(This
->file
, &key
, &key_size
);
5447 hr
= IDWriteFontFile_GetLoader(This
->file
, &loader
);
5451 hr
= IDWriteFactory3_CreateCustomFontFileReference(This
->factory
, key
, key_size
, loader
, file
);
5452 IDWriteFontFileLoader_Release(loader
);
5457 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
5459 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5461 FIXME("(%p): stub\n", This
);
5466 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference
*iface
)
5468 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5470 FIXME("(%p): stub\n", This
);
5475 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
5477 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5479 FIXME("(%p)->(%p): stub\n", This
, writetime
);
5484 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference
*iface
)
5486 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5488 FIXME("(%p): stub\n", This
);
5490 return DWRITE_LOCALITY_LOCAL
;
5493 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
5495 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5497 FIXME("(%p): stub\n", This
);
5502 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
, WCHAR
const *chars
,
5505 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5507 FIXME("(%p)->(%s:%u): stub\n", This
, debugstr_wn(chars
, count
), count
);
5512 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
, UINT16
const *glyphs
,
5515 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5517 FIXME("(%p)->(%p %u): stub\n", This
, glyphs
, count
);
5522 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
5523 UINT64 offset
, UINT64 size
)
5525 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5527 FIXME("(%p)->(%s %s): stub\n", This
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
5532 static const IDWriteFontFaceReferenceVtbl fontfacereferencevtbl
= {
5533 fontfacereference_QueryInterface
,
5534 fontfacereference_AddRef
,
5535 fontfacereference_Release
,
5536 fontfacereference_CreateFontFace
,
5537 fontfacereference_CreateFontFaceWithSimulations
,
5538 fontfacereference_Equals
,
5539 fontfacereference_GetFontFaceIndex
,
5540 fontfacereference_GetSimulations
,
5541 fontfacereference_GetFontFile
,
5542 fontfacereference_GetLocalFileSize
,
5543 fontfacereference_GetFileSize
,
5544 fontfacereference_GetFileTime
,
5545 fontfacereference_GetLocality
,
5546 fontfacereference_EnqueueFontDownloadRequest
,
5547 fontfacereference_EnqueueCharacterDownloadRequest
,
5548 fontfacereference_EnqueueGlyphDownloadRequest
,
5549 fontfacereference_EnqueueFileFragmentDownloadRequest
5552 HRESULT
create_fontfacereference(IDWriteFactory3
*factory
, IDWriteFontFile
*file
, UINT32 index
,
5553 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFaceReference
**ret
)
5555 struct dwrite_fontfacereference
*ref
;
5559 ref
= heap_alloc(sizeof(*ref
));
5561 return E_OUTOFMEMORY
;
5563 ref
->IDWriteFontFaceReference_iface
.lpVtbl
= &fontfacereferencevtbl
;
5566 ref
->factory
= factory
;
5567 IDWriteFactory3_AddRef(ref
->factory
);
5569 IDWriteFontFile_AddRef(ref
->file
);
5571 ref
->simulations
= simulations
;
5572 *ret
= &ref
->IDWriteFontFaceReference_iface
;