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 IDWriteFactory2
*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 IDWriteFontList IDWriteFontList_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 IDWriteFontCollection
* 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 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace3(IDWriteFontFace3
*iface
)
247 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace3_iface
);
250 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
252 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
255 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
257 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
260 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
262 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
265 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection1(IDWriteFontCollection1
*iface
)
267 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection1_iface
);
270 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
272 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
275 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
277 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
280 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList(IDWriteFontList
*iface
)
282 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList_iface
);
285 static inline const char *debugstr_tag(UINT32 tag
)
287 return debugstr_an((char*)&tag
, 4);
290 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
292 static const DWRITE_GLYPH_METRICS nil
;
293 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
295 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
296 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
300 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
302 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
305 /* start new block */
306 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
308 return E_OUTOFMEMORY
;
311 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
315 static void* get_fontface_table(IDWriteFontFace3
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
319 if (table
->data
|| !table
->exists
)
322 table
->exists
= FALSE
;
323 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
325 if (FAILED(hr
) || !table
->exists
) {
326 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
333 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
334 struct dwrite_font_propvec
*vec
)
336 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
337 vec
->style
= style
* 7.0f
;
338 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
341 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
343 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
346 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
348 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
351 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
353 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
356 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
358 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
361 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
363 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_GASP_TAG
, &fontface
->gasp
);
364 *size
= fontface
->gasp
.size
;
368 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
370 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
373 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
375 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_COLR_TAG
, &fontface
->colr
);
378 static void release_font_data(struct dwrite_font_data
*data
)
382 if (InterlockedDecrement(&data
->ref
) > 0)
385 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
386 if (data
->info_strings
[i
])
387 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
390 IDWriteLocalizedStrings_Release(data
->names
);
392 IDWriteFontFile_Release(data
->file
);
393 IDWriteFactory2_Release(data
->factory
);
394 heap_free(data
->facename
);
398 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
402 if (InterlockedDecrement(&data
->ref
) > 0)
405 for (i
= 0; i
< data
->font_count
; i
++)
406 release_font_data(data
->fonts
[i
]);
407 heap_free(data
->fonts
);
408 IDWriteLocalizedStrings_Release(data
->familyname
);
412 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace3
*iface
, REFIID riid
, void **obj
)
414 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
416 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
418 if (IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
419 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
420 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
421 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
422 IsEqualIID(riid
, &IID_IUnknown
))
425 IDWriteFontFace3_AddRef(iface
);
430 return E_NOINTERFACE
;
433 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace3
*iface
)
435 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
436 ULONG ref
= InterlockedIncrement(&This
->ref
);
437 TRACE("(%p)->(%d)\n", This
, ref
);
441 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace3
*iface
)
443 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
444 ULONG ref
= InterlockedDecrement(&This
->ref
);
446 TRACE("(%p)->(%d)\n", This
, ref
);
451 if (This
->cmap
.context
)
452 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cmap
.context
);
453 if (This
->vdmx
.context
)
454 IDWriteFontFace3_ReleaseFontTable(iface
, This
->vdmx
.context
);
455 if (This
->gasp
.context
)
456 IDWriteFontFace3_ReleaseFontTable(iface
, This
->gasp
.context
);
457 if (This
->cpal
.context
)
458 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cpal
.context
);
459 if (This
->colr
.context
)
460 IDWriteFontFace3_ReleaseFontTable(iface
, This
->colr
.context
);
461 for (i
= 0; i
< This
->file_count
; i
++) {
462 if (This
->streams
[i
])
463 IDWriteFontFileStream_Release(This
->streams
[i
]);
465 IDWriteFontFile_Release(This
->files
[i
]);
467 heap_free(This
->streams
);
468 heap_free(This
->files
);
470 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
471 heap_free(This
->glyphs
[i
]);
473 freetype_notify_cacheremove(iface
);
480 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace3
*iface
)
482 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
483 TRACE("(%p)\n", This
);
487 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace3
*iface
, UINT32
*number_of_files
,
488 IDWriteFontFile
**fontfiles
)
490 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
493 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
494 if (fontfiles
== NULL
)
496 *number_of_files
= This
->file_count
;
499 if (*number_of_files
< This
->file_count
)
502 for (i
= 0; i
< This
->file_count
; i
++)
504 IDWriteFontFile_AddRef(This
->files
[i
]);
505 fontfiles
[i
] = This
->files
[i
];
511 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace3
*iface
)
513 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
514 TRACE("(%p)\n", This
);
518 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace3
*iface
)
520 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
521 TRACE("(%p)\n", This
);
522 return This
->simulations
;
525 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace3
*iface
)
527 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
528 TRACE("(%p)\n", This
);
529 return This
->is_symbol
;
532 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS
*metrics
)
534 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
535 TRACE("(%p)->(%p)\n", This
, metrics
);
536 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
539 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace3
*iface
)
541 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
542 TRACE("(%p)\n", This
);
543 return freetype_get_glyphcount(iface
);
546 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace3
*iface
,
547 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
549 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
553 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
559 FIXME("sideways metrics are not supported.\n");
561 for (i
= 0; i
< glyph_count
; i
++) {
562 DWRITE_GLYPH_METRICS metrics
;
564 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
566 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
567 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
577 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace3
*iface
, UINT32
const *codepoints
,
578 UINT32 count
, UINT16
*glyph_indices
)
580 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
582 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
588 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
592 freetype_get_glyphs(iface
, This
->charmap
, codepoints
, count
, glyph_indices
);
596 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace3
*iface
, UINT32 table_tag
,
597 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
599 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
601 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
603 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
606 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace3
*iface
, void *table_context
)
608 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
610 TRACE("(%p)->(%p)\n", This
, table_context
);
612 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
615 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace3
*iface
, FLOAT emSize
,
616 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
617 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
619 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
621 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
622 count
, is_sideways
, is_rtl
, sink
);
624 if (!glyphs
|| !sink
)
628 FIXME("sideways mode is not supported.\n");
630 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
633 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
634 FLOAT ppem
, WORD gasp
)
636 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
640 case DWRITE_MEASURING_MODE_NATURAL
:
642 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
643 mode
= DWRITE_RENDERING_MODE_NATURAL
;
645 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
648 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
649 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
651 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
652 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
661 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
662 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
664 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
669 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
672 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
676 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
677 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
680 ppem
= emSize
* ppdip
;
682 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
683 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
687 ptr
= get_fontface_gasp(This
, &size
);
688 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
689 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
693 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
694 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
696 DWRITE_FONT_METRICS1 metrics1
;
697 HRESULT hr
= IDWriteFontFace3_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
698 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
702 static inline int round_metric(FLOAT metric
)
704 return (int)floorf(metric
+ 0.5f
);
707 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT ppdip
,
708 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
709 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
711 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
712 DWRITE_MEASURING_MODE mode
;
717 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
718 glyph_count
, metrics
, is_sideways
);
720 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
721 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
723 size
= emSize
* ppdip
;
724 scale
= size
/ This
->metrics
.designUnitsPerEm
;
725 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
727 for (i
= 0; i
< glyph_count
; i
++) {
728 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
729 DWRITE_GLYPH_METRICS design
;
731 hr
= IDWriteFontFace3_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
735 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
);
736 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
738 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
739 SCALE_METRIC(leftSideBearing
);
740 SCALE_METRIC(rightSideBearing
);
741 SCALE_METRIC(topSideBearing
);
742 SCALE_METRIC(advanceHeight
);
743 SCALE_METRIC(bottomSideBearing
);
744 SCALE_METRIC(verticalOriginY
);
751 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
753 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
754 TRACE("(%p)->(%p)\n", This
, metrics
);
755 *metrics
= This
->metrics
;
758 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
759 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
761 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
762 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
763 UINT16 ascent
, descent
;
766 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
768 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
769 memset(metrics
, 0, sizeof(*metrics
));
773 em_size
*= pixels_per_dip
;
774 if (m
&& m
->m22
!= 0.0f
)
775 em_size
*= fabs(m
->m22
);
777 scale
= em_size
/ design
->designUnitsPerEm
;
778 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
779 ascent
= round_metric(design
->ascent
* scale
);
780 descent
= round_metric(design
->descent
* scale
);
783 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
784 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
785 metrics
->ascent
= round_metric(ascent
/ scale
);
786 metrics
->descent
= round_metric(descent
/ scale
);
788 SCALE_METRIC(lineGap
);
789 SCALE_METRIC(capHeight
);
790 SCALE_METRIC(xHeight
);
791 SCALE_METRIC(underlinePosition
);
792 SCALE_METRIC(underlineThickness
);
793 SCALE_METRIC(strikethroughPosition
);
794 SCALE_METRIC(strikethroughThickness
);
795 SCALE_METRIC(glyphBoxLeft
);
796 SCALE_METRIC(glyphBoxTop
);
797 SCALE_METRIC(glyphBoxRight
);
798 SCALE_METRIC(glyphBoxBottom
);
799 SCALE_METRIC(subscriptPositionX
);
800 SCALE_METRIC(subscriptPositionY
);
801 SCALE_METRIC(subscriptSizeX
);
802 SCALE_METRIC(subscriptSizeY
);
803 SCALE_METRIC(superscriptPositionX
);
804 SCALE_METRIC(superscriptPositionY
);
805 SCALE_METRIC(superscriptSizeX
);
806 SCALE_METRIC(superscriptSizeY
);
808 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
814 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace3
*iface
, DWRITE_CARET_METRICS
*metrics
)
816 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
817 TRACE("(%p)->(%p)\n", This
, metrics
);
818 *metrics
= This
->caret
;
821 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace3
*iface
, UINT32 max_count
,
822 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
824 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
826 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
829 if (max_count
&& !ranges
)
832 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
835 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace3
*iface
)
837 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
838 TRACE("(%p)\n", This
);
839 return This
->is_monospaced
;
842 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3
*iface
,
843 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
845 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
848 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
851 FIXME("sideways mode not supported\n");
853 for (i
= 0; i
< glyph_count
; i
++)
854 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], DWRITE_MEASURING_MODE_NATURAL
);
859 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace3
*iface
,
860 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
861 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
863 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
864 DWRITE_MEASURING_MODE mode
;
867 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
868 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
870 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
871 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
876 if (em_size
== 0.0f
) {
877 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
881 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
882 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
884 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
885 for (i
= 0; i
< glyph_count
; i
++) {
886 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
);
887 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
893 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace3
*iface
, UINT32 count
,
894 const UINT16
*indices
, INT32
*adjustments
)
896 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
899 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
901 if (!(indices
|| adjustments
) || !count
)
904 if (!indices
|| count
== 1) {
905 memset(adjustments
, 0, count
*sizeof(INT32
));
909 if (!This
->has_kerning_pairs
) {
910 memset(adjustments
, 0, count
*sizeof(INT32
));
914 for (i
= 0; i
< count
-1; i
++)
915 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
916 adjustments
[count
-1] = 0;
921 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace3
*iface
)
923 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
924 TRACE("(%p)\n", This
);
925 return This
->has_kerning_pairs
;
928 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
,
929 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
930 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
932 DWRITE_GRID_FIT_MODE gridfitmode
;
933 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
934 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
937 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace3
*iface
, UINT32 glyph_count
,
938 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
940 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
941 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
945 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3
*iface
)
947 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
948 FIXME("(%p): stub\n", This
);
952 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace3
*iface
)
954 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
955 TRACE("(%p)\n", This
);
956 return get_fontface_cpal(This
) && get_fontface_colr(This
);
959 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace3
*iface
)
961 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
962 TRACE("(%p)\n", This
);
963 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
966 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace3
*iface
)
968 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
969 TRACE("(%p)\n", This
);
970 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
973 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace3
*iface
, UINT32 palette_index
,
974 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
976 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
977 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
978 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
981 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
982 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
983 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
984 DWRITE_GRID_FIT_MODE
*gridfitmode
)
986 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
991 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
992 measuringmode
, params
, renderingmode
, gridfitmode
);
995 FIXME("transform not supported %s\n", debugstr_matrix(m
));
998 FIXME("sideways mode not supported\n");
1000 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1002 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1003 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1005 IDWriteRenderingParams2
*params2
;
1008 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1010 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1011 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1012 IDWriteRenderingParams2_Release(params2
);
1015 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1018 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1020 ptr
= get_fontface_gasp(This
, &size
);
1021 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1023 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1024 if (emSize
>= emthreshold
)
1025 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1027 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1030 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1031 if (emSize
>= emthreshold
)
1032 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1033 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1034 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1036 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1042 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace3
*iface
, IDWriteFontFaceReference
**ref
)
1044 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1045 FIXME("(%p)->(%p): stub\n", This
, ref
);
1049 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace3
*iface
, DWRITE_PANOSE
*panose
)
1051 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1052 FIXME("(%p)->(%p): stub\n", This
, panose
);
1055 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace3
*iface
)
1057 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1058 FIXME("(%p): stub\n", This
);
1059 return DWRITE_FONT_WEIGHT_NORMAL
;
1062 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace3
*iface
)
1064 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1065 FIXME("(%p): stub\n", This
);
1066 return DWRITE_FONT_STRETCH_NORMAL
;
1069 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace3
*iface
)
1071 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1072 FIXME("(%p): stub\n", This
);
1073 return DWRITE_FONT_STYLE_NORMAL
;
1076 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1078 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1079 FIXME("(%p)->(%p): stub\n", This
, names
);
1083 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1085 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1086 FIXME("(%p)->(%p): stub\n", This
, names
);
1090 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace3
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1091 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1093 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1094 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1098 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace3
*iface
, UINT32 ch
)
1100 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1104 TRACE("(%p)->(0x%08x)\n", This
, ch
);
1107 hr
= IDWriteFontFace3_GetGlyphIndices(iface
, &ch
, 1, &index
);
1114 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emsize
, FLOAT dpi_x
, FLOAT dpi_y
,
1115 DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1116 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1118 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1119 FIXME("(%p)->(%f %f %f %p %d %u %u %p %p %p): stub\n", This
, emsize
, dpi_x
, dpi_y
, transform
, is_sideways
, threshold
,
1120 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1124 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace3
*iface
, UINT32 ch
)
1126 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1127 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1131 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace3
*iface
, UINT16 glyph
)
1133 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1134 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1138 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace3
*iface
, WCHAR
const *text
,
1139 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1141 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1142 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1146 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace3
*iface
, UINT16
const *glyphs
,
1147 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1149 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1150 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1154 static const IDWriteFontFace3Vtbl dwritefontfacevtbl
= {
1155 dwritefontface_QueryInterface
,
1156 dwritefontface_AddRef
,
1157 dwritefontface_Release
,
1158 dwritefontface_GetType
,
1159 dwritefontface_GetFiles
,
1160 dwritefontface_GetIndex
,
1161 dwritefontface_GetSimulations
,
1162 dwritefontface_IsSymbolFont
,
1163 dwritefontface_GetMetrics
,
1164 dwritefontface_GetGlyphCount
,
1165 dwritefontface_GetDesignGlyphMetrics
,
1166 dwritefontface_GetGlyphIndices
,
1167 dwritefontface_TryGetFontTable
,
1168 dwritefontface_ReleaseFontTable
,
1169 dwritefontface_GetGlyphRunOutline
,
1170 dwritefontface_GetRecommendedRenderingMode
,
1171 dwritefontface_GetGdiCompatibleMetrics
,
1172 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1173 dwritefontface1_GetMetrics
,
1174 dwritefontface1_GetGdiCompatibleMetrics
,
1175 dwritefontface1_GetCaretMetrics
,
1176 dwritefontface1_GetUnicodeRanges
,
1177 dwritefontface1_IsMonospacedFont
,
1178 dwritefontface1_GetDesignGlyphAdvances
,
1179 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1180 dwritefontface1_GetKerningPairAdjustments
,
1181 dwritefontface1_HasKerningPairs
,
1182 dwritefontface1_GetRecommendedRenderingMode
,
1183 dwritefontface1_GetVerticalGlyphVariants
,
1184 dwritefontface1_HasVerticalGlyphVariants
,
1185 dwritefontface2_IsColorFont
,
1186 dwritefontface2_GetColorPaletteCount
,
1187 dwritefontface2_GetPaletteEntryCount
,
1188 dwritefontface2_GetPaletteEntries
,
1189 dwritefontface2_GetRecommendedRenderingMode
,
1190 dwritefontface3_GetFontFaceReference
,
1191 dwritefontface3_GetPanose
,
1192 dwritefontface3_GetWeight
,
1193 dwritefontface3_GetStretch
,
1194 dwritefontface3_GetStyle
,
1195 dwritefontface3_GetFamilyNames
,
1196 dwritefontface3_GetFaceNames
,
1197 dwritefontface3_GetInformationalStrings
,
1198 dwritefontface3_HasCharacter
,
1199 dwritefontface3_GetRecommendedRenderingMode
,
1200 dwritefontface3_IsCharacterLocal
,
1201 dwritefontface3_IsGlyphLocal
,
1202 dwritefontface3_AreCharactersLocal
,
1203 dwritefontface3_AreGlyphsLocal
1206 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace3
**fontface
)
1208 struct dwrite_font_data
*data
= font
->data
;
1209 IDWriteFontFace
*face
;
1214 hr
= IDWriteFactory2_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
1215 data
->face_index
, font
->data
->simulations
, &face
);
1219 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void**)fontface
);
1220 IDWriteFontFace_Release(face
);
1225 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1227 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1229 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1231 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1232 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1233 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1234 IsEqualIID(riid
, &IID_IUnknown
))
1237 IDWriteFont3_AddRef(iface
);
1242 return E_NOINTERFACE
;
1245 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1247 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1248 ULONG ref
= InterlockedIncrement(&This
->ref
);
1249 TRACE("(%p)->(%d)\n", This
, ref
);
1253 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1255 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1256 ULONG ref
= InterlockedDecrement(&This
->ref
);
1258 TRACE("(%p)->(%d)\n", This
, ref
);
1261 IDWriteFontFamily1_Release(This
->family
);
1262 release_font_data(This
->data
);
1269 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1271 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1272 TRACE("(%p)->(%p)\n", This
, family
);
1274 *family
= (IDWriteFontFamily
*)This
->family
;
1275 IDWriteFontFamily_AddRef(*family
);
1279 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1281 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1282 TRACE("(%p)\n", This
);
1283 return This
->data
->weight
;
1286 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1288 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1289 TRACE("(%p)\n", This
);
1290 return This
->data
->stretch
;
1293 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1295 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1296 TRACE("(%p)\n", This
);
1300 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1302 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1303 IDWriteFontFace3
*fontface
;
1306 TRACE("(%p)\n", This
);
1308 hr
= get_fontface_from_font(This
, &fontface
);
1312 return IDWriteFontFace3_IsSymbolFont(fontface
);
1315 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1317 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1318 TRACE("(%p)->(%p)\n", This
, names
);
1319 return clone_localizedstring(This
->data
->names
, names
);
1322 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1323 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1325 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1326 struct dwrite_font_data
*data
= This
->data
;
1329 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1334 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1337 if (!data
->info_strings
[stringid
]) {
1338 IDWriteFontFace3
*fontface
;
1339 const void *table_data
;
1344 hr
= get_fontface_from_font(This
, &fontface
);
1348 table_exists
= FALSE
;
1349 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1350 if (FAILED(hr
) || !table_exists
)
1351 WARN("no NAME table found.\n");
1354 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1355 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1357 IDWriteFontFace3_ReleaseFontTable(fontface
, context
);
1361 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1369 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1371 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1372 TRACE("(%p)\n", This
);
1373 return This
->data
->simulations
;
1376 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1378 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1380 TRACE("(%p)->(%p)\n", This
, metrics
);
1381 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1384 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 value
, BOOL
*exists
)
1386 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1387 IDWriteFontFace3
*fontface
;
1391 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1395 hr
= get_fontface_from_font(This
, &fontface
);
1400 hr
= IDWriteFontFace3_GetGlyphIndices(fontface
, &value
, 1, &index
);
1404 *exists
= index
!= 0;
1408 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**face
)
1410 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1413 TRACE("(%p)->(%p)\n", This
, face
);
1415 hr
= get_fontface_from_font(This
, (IDWriteFontFace3
**)face
);
1417 IDWriteFontFace_AddRef(*face
);
1422 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1424 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1425 TRACE("(%p)->(%p)\n", This
, metrics
);
1426 *metrics
= This
->data
->metrics
;
1429 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1431 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1432 TRACE("(%p)->(%p)\n", This
, panose
);
1433 *panose
= This
->data
->panose
;
1436 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1438 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1439 IDWriteFontFace3
*fontface
;
1442 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1444 hr
= get_fontface_from_font(This
, &fontface
);
1448 return IDWriteFontFace3_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1451 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1453 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1454 IDWriteFontFace3
*fontface
;
1457 TRACE("(%p)\n", This
);
1459 hr
= get_fontface_from_font(This
, &fontface
);
1463 return IDWriteFontFace3_IsMonospacedFont(fontface
);
1466 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1468 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1469 IDWriteFontFace3
*fontface
;
1472 TRACE("(%p)\n", This
);
1474 hr
= get_fontface_from_font(This
, &fontface
);
1478 return IDWriteFontFace3_IsColorFont(fontface
);
1481 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1483 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1484 FIXME("(%p)->(%p): stub\n", This
, fontface
);
1488 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1490 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1491 FIXME("(%p)->(%p): stub\n", This
, font
);
1495 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1497 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1498 FIXME("(%p)->(%p): stub\n", This
, reference
);
1502 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1504 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1505 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1509 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1511 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1512 FIXME("(%p): stub\n", This
);
1513 return DWRITE_LOCALITY_LOCAL
;
1516 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1517 dwritefont_QueryInterface
,
1520 dwritefont_GetFontFamily
,
1521 dwritefont_GetWeight
,
1522 dwritefont_GetStretch
,
1523 dwritefont_GetStyle
,
1524 dwritefont_IsSymbolFont
,
1525 dwritefont_GetFaceNames
,
1526 dwritefont_GetInformationalStrings
,
1527 dwritefont_GetSimulations
,
1528 dwritefont_GetMetrics
,
1529 dwritefont_HasCharacter
,
1530 dwritefont_CreateFontFace
,
1531 dwritefont1_GetMetrics
,
1532 dwritefont1_GetPanose
,
1533 dwritefont1_GetUnicodeRanges
,
1534 dwritefont1_IsMonospacedFont
,
1535 dwritefont2_IsColorFont
,
1536 dwritefont3_CreateFontFace
,
1538 dwritefont3_GetFontFaceReference
,
1539 dwritefont3_HasCharacter
,
1540 dwritefont3_GetLocality
1543 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily1
*family
, IDWriteFont3
**font
)
1545 struct dwrite_font
*This
;
1548 This
= heap_alloc(sizeof(struct dwrite_font
));
1549 if (!This
) return E_OUTOFMEMORY
;
1551 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1553 This
->family
= family
;
1554 IDWriteFontFamily1_AddRef(family
);
1555 This
->style
= data
->style
;
1557 InterlockedIncrement(&This
->data
->ref
);
1559 *font
= &This
->IDWriteFont3_iface
;
1564 /* IDWriteFontList */
1565 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList
*iface
, REFIID riid
, void **obj
)
1567 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1569 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1571 if (IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1572 IsEqualIID(riid
, &IID_IUnknown
))
1575 IDWriteFontList_AddRef(iface
);
1580 return E_NOINTERFACE
;
1583 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList
*iface
)
1585 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1586 ULONG ref
= InterlockedIncrement(&This
->ref
);
1587 TRACE("(%p)->(%d)\n", This
, ref
);
1591 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList
*iface
)
1593 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1594 ULONG ref
= InterlockedDecrement(&This
->ref
);
1596 TRACE("(%p)->(%d)\n", This
, ref
);
1601 for (i
= 0; i
< This
->font_count
; i
++)
1602 release_font_data(This
->fonts
[i
]);
1603 IDWriteFontFamily1_Release(This
->family
);
1610 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList
*iface
, IDWriteFontCollection
**collection
)
1612 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1613 return IDWriteFontFamily1_GetFontCollection(This
->family
, collection
);
1616 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList
*iface
)
1618 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1619 TRACE("(%p)\n", This
);
1620 return This
->font_count
;
1623 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList
*iface
, UINT32 index
, IDWriteFont
**font
)
1625 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1627 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1631 if (This
->font_count
== 0)
1634 if (index
>= This
->font_count
)
1635 return E_INVALIDARG
;
1637 return create_font(This
->fonts
[index
], This
->family
, (IDWriteFont3
**)font
);
1640 static const IDWriteFontListVtbl dwritefontlistvtbl
= {
1641 dwritefontlist_QueryInterface
,
1642 dwritefontlist_AddRef
,
1643 dwritefontlist_Release
,
1644 dwritefontlist_GetFontCollection
,
1645 dwritefontlist_GetFontCount
,
1646 dwritefontlist_GetFont
1649 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1651 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1653 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1655 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1656 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1657 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1658 IsEqualIID(riid
, &IID_IUnknown
))
1661 IDWriteFontFamily1_AddRef(iface
);
1666 return E_NOINTERFACE
;
1669 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1671 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1672 ULONG ref
= InterlockedIncrement(&This
->ref
);
1673 TRACE("(%p)->(%d)\n", This
, ref
);
1677 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1679 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1680 ULONG ref
= InterlockedDecrement(&This
->ref
);
1682 TRACE("(%p)->(%d)\n", This
, ref
);
1686 IDWriteFontCollection_Release(This
->collection
);
1687 release_fontfamily_data(This
->data
);
1694 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
1696 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1697 TRACE("(%p)->(%p)\n", This
, collection
);
1699 *collection
= This
->collection
;
1700 IDWriteFontCollection_AddRef(This
->collection
);
1704 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
1706 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1707 TRACE("(%p)\n", This
);
1708 return This
->data
->font_count
;
1711 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
1713 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1715 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1719 if (This
->data
->font_count
== 0)
1722 if (index
>= This
->data
->font_count
)
1723 return E_INVALIDARG
;
1725 return create_font(This
->data
->fonts
[index
], iface
, (IDWriteFont3
**)font
);
1728 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
1730 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1731 return clone_localizedstring(This
->data
->familyname
, names
);
1734 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
1735 const struct dwrite_font_propvec
*req
)
1737 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
1738 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
1739 FLOAT cur_req_prod
, next_req_prod
;
1741 if (next_to_req
< cur_to_req
)
1744 if (next_to_req
> cur_to_req
)
1747 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
1748 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
1750 if (next_req_prod
> cur_req_prod
)
1753 if (next_req_prod
< cur_req_prod
)
1756 if (next
->stretch
> cur
->stretch
)
1758 if (next
->stretch
< cur
->stretch
)
1761 if (next
->style
> cur
->style
)
1763 if (next
->style
< cur
->style
)
1766 if (next
->weight
> cur
->weight
)
1768 if (next
->weight
< cur
->weight
)
1771 /* full match, no reason to prefer new variant */
1775 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1776 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1778 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1779 struct dwrite_font_propvec req
;
1780 struct dwrite_font_data
*match
;
1783 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1785 if (This
->data
->font_count
== 0) {
1787 return DWRITE_E_NOFONT
;
1790 init_font_prop_vec(weight
, stretch
, style
, &req
);
1791 match
= This
->data
->fonts
[0];
1793 for (i
= 1; i
< This
->data
->font_count
; i
++) {
1794 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &match
->propvec
, &req
))
1795 match
= This
->data
->fonts
[i
];
1798 return create_font(match
, iface
, (IDWriteFont3
**)font
);
1801 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
1803 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
1805 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1808 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
1810 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1813 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
1815 UINT32 b
= fonts
->font_count
- 1, j
, t
;
1820 for (j
= 0; j
< b
; j
++) {
1821 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
1822 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
1823 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
1824 fonts
->fonts
[j
+1] = s
;
1835 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1836 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
1838 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1839 matching_filter_func func
= NULL
;
1840 struct dwrite_font_propvec req
;
1841 struct dwrite_fontlist
*fonts
;
1844 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
1848 fonts
= heap_alloc(sizeof(*fonts
));
1850 return E_OUTOFMEMORY
;
1852 /* Allocate as many as family has, not all of them will be necessary used. */
1853 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
1854 if (!fonts
->fonts
) {
1856 return E_OUTOFMEMORY
;
1859 fonts
->IDWriteFontList_iface
.lpVtbl
= &dwritefontlistvtbl
;
1861 fonts
->family
= iface
;
1862 IDWriteFontFamily1_AddRef(fonts
->family
);
1863 fonts
->font_count
= 0;
1865 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
1866 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
1867 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
1868 func
= is_font_acceptable_for_normal
;
1870 else /* requested oblique or italic */ {
1871 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
1872 func
= is_font_acceptable_for_oblique_italic
;
1875 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1876 if (!func
|| func(This
->data
->fonts
[i
])) {
1877 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
1878 InterlockedIncrement(&This
->data
->fonts
[i
]->ref
);
1879 fonts
->font_count
++;
1883 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
1884 init_font_prop_vec(weight
, stretch
, style
, &req
);
1885 matchingfonts_sort(fonts
, &req
);
1887 *ret
= &fonts
->IDWriteFontList_iface
;
1891 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
1893 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1895 FIXME("(%p)->(%u): stub\n", This
, index
);
1897 return DWRITE_LOCALITY_LOCAL
;
1900 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1902 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1904 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1908 if (This
->data
->font_count
== 0)
1911 if (index
>= This
->data
->font_count
)
1914 return create_font(This
->data
->fonts
[index
], iface
, font
);
1917 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
1918 IDWriteFontFaceReference
**ref
)
1920 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1922 FIXME("(%p)->(%u %p): stub\n", This
, index
, ref
);
1927 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
1928 dwritefontfamily_QueryInterface
,
1929 dwritefontfamily_AddRef
,
1930 dwritefontfamily_Release
,
1931 dwritefontfamily_GetFontCollection
,
1932 dwritefontfamily_GetFontCount
,
1933 dwritefontfamily_GetFont
,
1934 dwritefontfamily_GetFamilyNames
,
1935 dwritefontfamily_GetFirstMatchingFont
,
1936 dwritefontfamily_GetMatchingFonts
,
1937 dwritefontfamily1_GetFontLocality
,
1938 dwritefontfamily1_GetFont
,
1939 dwritefontfamily1_GetFontFaceReference
1942 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily1
**family
)
1944 struct dwrite_fontfamily
*This
;
1948 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1949 if (!This
) return E_OUTOFMEMORY
;
1951 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
1953 This
->collection
= collection
;
1954 IDWriteFontCollection_AddRef(collection
);
1956 InterlockedIncrement(&This
->data
->ref
);
1958 *family
= &This
->IDWriteFontFamily1_iface
;
1963 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1966 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1969 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
1971 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
1972 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1974 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
1975 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
1976 IsEqualIID(riid
, &IID_IUnknown
))
1979 IDWriteFontCollection1_AddRef(iface
);
1985 if (IsEqualIID(riid
, &IID_issystemcollection
))
1988 return E_NOINTERFACE
;
1991 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
1993 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
1994 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1996 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
1997 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
1998 IsEqualIID(riid
, &IID_IUnknown
))
2001 IDWriteFontCollection1_AddRef(iface
);
2007 return E_NOINTERFACE
;
2010 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2012 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2013 ULONG ref
= InterlockedIncrement(&This
->ref
);
2014 TRACE("(%p)->(%d)\n", This
, ref
);
2018 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2021 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2022 ULONG ref
= InterlockedDecrement(&This
->ref
);
2023 TRACE("(%p)->(%d)\n", This
, ref
);
2026 for (i
= 0; i
< This
->family_count
; i
++)
2027 release_fontfamily_data(This
->family_data
[i
]);
2028 heap_free(This
->family_data
);
2035 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2037 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2038 TRACE("(%p)\n", This
);
2039 return This
->family_count
;
2042 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2044 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2046 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2048 if (index
>= This
->family_count
) {
2053 return create_fontfamily(This
->family_data
[index
], (IDWriteFontCollection
*)iface
, (IDWriteFontFamily1
**)family
);
2056 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2060 for (i
= 0; i
< collection
->family_count
; i
++) {
2061 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2062 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2065 for (j
= 0; j
< count
; j
++) {
2067 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2068 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2076 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2078 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2079 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2080 *index
= collection_find_family(This
, name
);
2081 *exists
= *index
!= ~0u;
2085 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2087 UINT32 left_key_size
, right_key_size
;
2088 const void *left_key
, *right_key
;
2094 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2098 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2102 if (left_key_size
!= right_key_size
)
2105 return !memcmp(left_key
, right_key
, left_key_size
);
2108 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2110 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2111 struct dwrite_fontfamily_data
*found_family
= NULL
;
2112 struct dwrite_font_data
*found_font
= NULL
;
2113 IDWriteFontFamily1
*family
;
2114 UINT32 i
, j
, face_index
;
2115 IDWriteFontFile
*file
;
2118 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2123 return E_INVALIDARG
;
2126 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2129 face_index
= IDWriteFontFace_GetIndex(face
);
2131 for (i
= 0; i
< This
->family_count
; i
++) {
2132 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2133 for (j
= 0; j
< family_data
->font_count
; j
++) {
2134 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2136 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2137 found_font
= font_data
;
2138 found_family
= family_data
;
2145 return DWRITE_E_NOFONT
;
2147 hr
= create_fontfamily(found_family
, (IDWriteFontCollection
*)iface
, &family
);
2151 hr
= create_font(found_font
, family
, (IDWriteFont3
**)font
);
2152 IDWriteFontFamily1_Release(family
);
2156 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2158 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2160 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2165 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2167 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2169 FIXME("(%p)->(%p): stub\n", This
, family
);
2174 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2175 dwritefontcollection_QueryInterface
,
2176 dwritefontcollection_AddRef
,
2177 dwritefontcollection_Release
,
2178 dwritefontcollection_GetFontFamilyCount
,
2179 dwritefontcollection_GetFontFamily
,
2180 dwritefontcollection_FindFamilyName
,
2181 dwritefontcollection_GetFontFromFontFace
,
2182 dwritefontcollection1_GetFontSet
,
2183 dwritefontcollection1_GetFontFamily
2186 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2187 dwritesystemfontcollection_QueryInterface
,
2188 dwritefontcollection_AddRef
,
2189 dwritefontcollection_Release
,
2190 dwritefontcollection_GetFontFamilyCount
,
2191 dwritefontcollection_GetFontFamily
,
2192 dwritefontcollection_FindFamilyName
,
2193 dwritefontcollection_GetFontFromFontFace
,
2194 dwritefontcollection1_GetFontSet
,
2195 dwritefontcollection1_GetFontFamily
2198 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2200 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2201 struct dwrite_font_data
**new_list
;
2204 new_alloc
= family_data
->font_alloc
* 2;
2205 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2207 return E_OUTOFMEMORY
;
2208 family_data
->fonts
= new_list
;
2209 family_data
->font_alloc
= new_alloc
;
2212 family_data
->fonts
[family_data
->font_count
] = font_data
;
2213 family_data
->font_count
++;
2214 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2215 family_data
->has_normal_face
= 1;
2216 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2217 family_data
->has_oblique_face
= 1;
2219 family_data
->has_italic_face
= 1;
2223 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2225 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2226 struct dwrite_fontfamily_data
**new_list
;
2229 new_alloc
= collection
->family_alloc
* 2;
2230 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2232 return E_OUTOFMEMORY
;
2234 collection
->family_alloc
= new_alloc
;
2235 collection
->family_data
= new_list
;
2238 collection
->family_data
[collection
->family_count
] = family
;
2239 collection
->family_count
++;
2244 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2246 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2247 collection
->ref
= 1;
2248 collection
->family_count
= 0;
2249 collection
->family_alloc
= is_system
? 30 : 5;
2250 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2251 if (!collection
->family_data
)
2252 return E_OUTOFMEMORY
;
2257 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2259 IDWriteFontFileLoader
*loader
;
2266 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2270 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2274 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2275 IDWriteFontFileLoader_Release(loader
);
2282 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2284 BOOL exists
= FALSE
;
2289 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2290 if (FAILED(hr
) || !exists
)
2293 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2296 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2300 while (isspaceW(*in
))
2304 if (!(len
= strlenW(in
)))
2307 while (isspaceW(in
[len
-1]))
2310 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2319 INT len
; /* token length */
2320 INT fulllen
; /* full length including following separators */
2323 static inline BOOL
is_name_separator_char(WCHAR ch
)
2325 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2328 struct name_pattern
{
2329 const WCHAR
*part1
; /* NULL indicates end of list */
2330 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2333 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2335 const struct name_pattern
*pattern
;
2336 struct name_token
*token
;
2339 while ((pattern
= &patterns
[i
++])->part1
) {
2340 int len_part1
= strlenW(pattern
->part1
);
2341 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2343 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2344 if (len_part2
== 0) {
2345 /* simple case with single part pattern */
2346 if (token
->len
!= len_part1
)
2349 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2350 if (match
) *match
= *token
;
2351 list_remove(&token
->entry
);
2357 struct name_token
*next_token
;
2358 struct list
*next_entry
;
2360 /* pattern parts are stored in reading order, tokens list is reversed */
2361 if (token
->len
< len_part2
)
2364 /* it's possible to have combined string as a token, like ExtraCondensed */
2365 if (token
->len
== len_part1
+ len_part2
) {
2366 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2369 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2372 /* combined string match */
2373 if (match
) *match
= *token
;
2374 list_remove(&token
->entry
);
2379 /* now it's only possible to have two tokens matched to respective pattern parts */
2380 if (token
->len
!= len_part2
)
2383 next_entry
= list_next(tokens
, &token
->entry
);
2385 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2386 if (next_token
->len
!= len_part1
)
2389 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2392 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2395 /* both parts matched, remove tokens */
2397 match
->ptr
= next_token
->ptr
;
2398 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2400 list_remove(&token
->entry
);
2401 list_remove(&next_token
->entry
);
2402 heap_free(next_token
);
2417 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2419 static const WCHAR itaW
[] = {'i','t','a',0};
2420 static const WCHAR italW
[] = {'i','t','a','l',0};
2421 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2422 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2424 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2425 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2426 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2427 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2429 static const struct name_pattern italic_patterns
[] = {
2438 static const struct name_pattern oblique_patterns
[] = {
2447 /* italic patterns first */
2448 if (match_pattern_list(tokens
, italic_patterns
, match
))
2449 return DWRITE_FONT_STYLE_ITALIC
;
2451 /* oblique patterns */
2452 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2453 return DWRITE_FONT_STYLE_OBLIQUE
;
2458 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2459 struct name_token
*match
)
2461 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2462 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2463 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2464 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2465 static const WCHAR wideW
[] = {'w','i','d','e',0};
2466 static const WCHAR condW
[] = {'c','o','n','d',0};
2468 static const struct name_pattern ultracondensed_patterns
[] = {
2469 { extraW
, compressedW
},
2470 { extW
, compressedW
},
2471 { ultraW
, compressedW
},
2472 { ultraW
, condensedW
},
2477 static const struct name_pattern extracondensed_patterns
[] = {
2479 { extraW
, condensedW
},
2480 { extW
, condensedW
},
2486 static const struct name_pattern semicondensed_patterns
[] = {
2489 { semiW
, condensedW
},
2494 static const struct name_pattern semiexpanded_patterns
[] = {
2496 { semiW
, expandedW
},
2497 { semiW
, extendedW
},
2501 static const struct name_pattern extraexpanded_patterns
[] = {
2502 { extraW
, expandedW
},
2503 { extW
, expandedW
},
2504 { extraW
, extendedW
},
2505 { extW
, extendedW
},
2509 static const struct name_pattern ultraexpanded_patterns
[] = {
2510 { ultraW
, expandedW
},
2511 { ultraW
, extendedW
},
2515 static const struct name_pattern condensed_patterns
[] = {
2521 static const struct name_pattern expanded_patterns
[] = {
2527 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2528 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2530 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2531 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2533 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2534 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2536 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2537 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2539 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2540 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2542 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2543 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2545 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2546 return DWRITE_FONT_STRETCH_CONDENSED
;
2548 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2549 return DWRITE_FONT_STRETCH_EXPANDED
;
2554 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2555 struct name_token
*match
)
2557 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2558 static const WCHAR nordW
[] = {'n','o','r','d',0};
2560 static const struct name_pattern thin_patterns
[] = {
2567 static const struct name_pattern extralight_patterns
[] = {
2574 static const struct name_pattern semilight_patterns
[] = {
2579 static const struct name_pattern demibold_patterns
[] = {
2585 static const struct name_pattern extrabold_patterns
[] = {
2592 static const struct name_pattern extrablack_patterns
[] = {
2599 static const struct name_pattern bold_patterns
[] = {
2604 static const struct name_pattern thin2_patterns
[] = {
2609 static const struct name_pattern light_patterns
[] = {
2614 static const struct name_pattern medium_patterns
[] = {
2619 static const struct name_pattern black_patterns
[] = {
2626 static const struct name_pattern demibold2_patterns
[] = {
2631 static const struct name_pattern extrabold2_patterns
[] = {
2636 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2637 matching pattern. */
2639 if (match_pattern_list(tokens
, thin_patterns
, match
))
2640 return DWRITE_FONT_WEIGHT_THIN
;
2642 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2643 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2645 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2646 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2648 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2649 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2651 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2652 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2654 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2655 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2657 if (match_pattern_list(tokens
, bold_patterns
, match
))
2658 return DWRITE_FONT_WEIGHT_BOLD
;
2660 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2661 return DWRITE_FONT_WEIGHT_THIN
;
2663 if (match_pattern_list(tokens
, light_patterns
, match
))
2664 return DWRITE_FONT_WEIGHT_LIGHT
;
2666 if (match_pattern_list(tokens
, medium_patterns
, match
))
2667 return DWRITE_FONT_WEIGHT_MEDIUM
;
2669 if (match_pattern_list(tokens
, black_patterns
, match
))
2670 return DWRITE_FONT_WEIGHT_BLACK
;
2672 if (match_pattern_list(tokens
, black_patterns
, match
))
2673 return DWRITE_FONT_WEIGHT_BLACK
;
2675 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2676 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2678 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2679 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2681 /* FIXME: use abbreviated names to extract weight */
2686 struct knownweight_entry
{
2688 DWRITE_FONT_WEIGHT weight
;
2691 static int compare_knownweights(const void *a
, const void* b
)
2693 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2694 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2697 if (target
> entry
->weight
)
2699 else if (target
< entry
->weight
)
2705 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2707 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2708 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2709 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2710 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2711 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2712 const struct knownweight_entry
*ptr
;
2714 static const struct knownweight_entry knownweights
[] = {
2715 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
2716 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
2717 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
2718 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
2719 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
2720 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
2721 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
2722 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
2723 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
2724 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
2727 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
2728 compare_knownweights
);
2734 strcpyW(nameW
, ptr
->nameW
);
2738 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
2740 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
2741 strW
[name
->len
] = 0;
2744 /* Modifies facenameW string, and returns pointer to regular term that was removed */
2745 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
2747 static const WCHAR bookW
[] = {'B','o','o','k',0};
2748 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
2749 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
2750 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
2751 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
2753 static const WCHAR
*regular_patterns
[] = {
2762 const WCHAR
*regular_ptr
= NULL
, *ptr
;
2766 len
= strlenW(facenameW
);
2768 /* remove rightmost regular variant from face name */
2769 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
2770 int pattern_len
= strlenW(ptr
);
2773 if (pattern_len
> len
)
2776 src
= facenameW
+ len
- pattern_len
;
2777 while (src
>= facenameW
) {
2778 if (!strncmpiW(src
, ptr
, pattern_len
)) {
2779 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
2780 len
= strlenW(facenameW
);
2792 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
2800 struct name_token
*token
= heap_alloc(sizeof(*token
));
2805 while (*ptr
&& !is_name_separator_char(*ptr
)) {
2811 /* skip separators */
2812 while (is_name_separator_char(*ptr
)) {
2817 list_add_head(tokens
, &token
->entry
);
2821 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
2823 struct name_token
*token
, *token2
;
2824 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
2827 list_remove(&token
->entry
);
2829 /* don't include last separator */
2830 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
2831 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
2839 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
2841 struct name_token stretch_name
, weight_name
, style_name
;
2842 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
2843 WCHAR weightW
[32], stretchW
[32], styleW
[32];
2844 const WCHAR
*regular_ptr
= NULL
;
2845 DWRITE_FONT_STRETCH stretch
;
2846 DWRITE_FONT_WEIGHT weight
;
2850 /* remove leading and trailing spaces from family and face name */
2851 trim_spaces(familyW
, familynameW
);
2852 len
= trim_spaces(faceW
, facenameW
);
2854 /* remove rightmost regular variant from face name */
2855 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
2857 /* append face name to family name, FIXME check if face name is a substring of family name */
2859 strcatW(familynameW
, spaceW
);
2860 strcatW(familynameW
, facenameW
);
2863 /* tokenize with " .-_" */
2864 fontname_tokenize(&tokens
, familynameW
);
2866 /* extract and resolve style */
2867 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
2869 /* extract stretch */
2870 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
2872 /* extract weight */
2873 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
2875 /* resolve weight */
2876 if (weight
!= font
->weight
) {
2877 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
2878 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
2879 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
2880 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
2881 !(abs(weight
- font
->weight
) <= 150 &&
2882 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
2883 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
2884 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
2886 font
->weight
= weight
;
2890 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
2891 it's leaning in opposite direction from normal comparing to specified stretch or if specified
2892 stretch itself is normal (extracted stretch is never normal). */
2893 if (stretch
!= font
->stretch
) {
2894 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
2895 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
2896 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
2898 font
->stretch
= stretch
;
2902 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
2904 /* get final combined string from what's left in token list, list is released */
2905 fontname_tokens_to_str(&tokens
, finalW
);
2907 if (!strcmpW(familyW
, finalW
))
2910 /* construct face name */
2911 strcpyW(familyW
, finalW
);
2913 /* resolved weight name */
2914 if (weight_name
.ptr
)
2915 font_name_token_to_str(&weight_name
, weightW
);
2916 /* ignore normal weight */
2917 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
2919 /* for known weight values use appropriate names */
2920 else if (is_known_weight_value(font
->weight
, weightW
)) {
2922 /* use Wnnn format as a fallback in case weight is not one of known values */
2924 static const WCHAR fmtW
[] = {'W','%','d',0};
2925 sprintfW(weightW
, fmtW
, font
->weight
);
2928 /* resolved stretch name */
2929 if (stretch_name
.ptr
)
2930 font_name_token_to_str(&stretch_name
, stretchW
);
2931 /* ignore normal stretch */
2932 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
2934 /* use predefined stretch names */
2936 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2937 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2938 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
2939 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
2940 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
2941 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
2943 static const WCHAR
*stretchnamesW
[] = {
2948 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
2954 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
2957 /* resolved style name */
2959 font_name_token_to_str(&style_name
, styleW
);
2960 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
2962 /* use predefined names */
2964 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
2965 strcpyW(styleW
, italicW
);
2967 strcpyW(styleW
, obliqueW
);
2970 /* use Regular match if it was found initially */
2971 if (!*weightW
&& !*stretchW
&& !*styleW
)
2972 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
2976 strcpyW(faceW
, stretchW
);
2979 strcatW(faceW
, spaceW
);
2980 strcatW(faceW
, weightW
);
2984 strcatW(faceW
, spaceW
);
2985 strcatW(faceW
, styleW
);
2989 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
2993 static HRESULT
init_font_data(IDWriteFactory2
*factory
, IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
, UINT32 face_index
,
2994 IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
2996 struct dwrite_font_props props
;
2997 struct dwrite_font_data
*data
;
2998 IDWriteFontFileStream
*stream
;
2999 WCHAR familyW
[255], faceW
[255];
3003 data
= heap_alloc_zero(sizeof(*data
));
3005 return E_OUTOFMEMORY
;
3007 hr
= get_filestream_from_file(file
, &stream
);
3014 data
->factory
= factory
;
3016 data
->face_index
= face_index
;
3017 data
->face_type
= face_type
;
3018 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3019 data
->bold_sim_tested
= 0;
3020 data
->oblique_sim_tested
= 0;
3021 IDWriteFontFile_AddRef(file
);
3022 IDWriteFactory2_AddRef(factory
);
3024 opentype_get_font_properties(stream
, face_type
, face_index
, &props
);
3025 opentype_get_font_metrics(stream
, face_type
, face_index
, &data
->metrics
, NULL
);
3026 opentype_get_font_facename(stream
, face_type
, face_index
, &data
->names
);
3028 /* get family name from font file */
3029 hr
= opentype_get_font_familyname(stream
, face_type
, face_index
, family_name
);
3030 IDWriteFontFileStream_Release(stream
);
3032 WARN("unable to get family name from font\n");
3033 release_font_data(data
);
3037 data
->style
= props
.style
;
3038 data
->stretch
= props
.stretch
;
3039 data
->weight
= props
.weight
;
3040 data
->panose
= props
.panose
;
3042 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3043 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3044 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3045 set_en_localizedstring(*family_name
, familyW
);
3046 set_en_localizedstring(data
->names
, faceW
);
3049 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3055 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
, const WCHAR
*facenameW
,
3056 struct dwrite_font_data
**ret
)
3058 struct dwrite_font_data
*data
;
3061 data
= heap_alloc_zero(sizeof(*data
));
3063 return E_OUTOFMEMORY
;
3067 data
->simulations
|= sim
;
3068 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3069 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3070 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3071 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3072 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3074 IDWriteFactory2_AddRef(data
->factory
);
3075 IDWriteFontFile_AddRef(data
->file
);
3077 create_localizedstrings(&data
->names
);
3078 add_localizedstring(data
->names
, enusW
, facenameW
);
3080 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3086 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3088 struct dwrite_fontfamily_data
*data
;
3090 data
= heap_alloc(sizeof(*data
));
3092 return E_OUTOFMEMORY
;
3095 data
->font_count
= 0;
3096 data
->font_alloc
= 2;
3097 data
->has_normal_face
= 0;
3098 data
->has_oblique_face
= 0;
3099 data
->has_italic_face
= 0;
3101 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3104 return E_OUTOFMEMORY
;
3107 data
->familyname
= familyname
;
3108 IDWriteLocalizedStrings_AddRef(familyname
);
3114 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3116 UINT32 i
, j
, heaviest
;
3118 for (i
= 0; i
< family
->font_count
; i
++) {
3119 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3122 if (family
->fonts
[i
]->bold_sim_tested
)
3125 family
->fonts
[i
]->bold_sim_tested
= 1;
3126 for (j
= i
; j
< family
->font_count
; j
++) {
3127 if (family
->fonts
[j
]->bold_sim_tested
)
3130 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3131 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3132 if (family
->fonts
[j
]->weight
> weight
) {
3133 weight
= family
->fonts
[j
]->weight
;
3136 family
->fonts
[j
]->bold_sim_tested
= 1;
3140 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3141 static const struct name_pattern weightsim_patterns
[] = {
3156 WCHAR facenameW
[255], initialW
[255];
3157 struct dwrite_font_data
*boldface
;
3160 /* add Bold simulation based on heaviest face data */
3162 /* Simulated face name should only contain Bold as weight term,
3163 so remove existing regular and weight terms. */
3164 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3165 facename_remove_regular_term(initialW
, -1);
3167 /* remove current weight pattern */
3168 fontname_tokenize(&tokens
, initialW
);
3169 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3170 fontname_tokens_to_str(&tokens
, facenameW
);
3172 /* Bold suffix for new name */
3174 strcatW(facenameW
, spaceW
);
3175 strcatW(facenameW
, boldW
);
3177 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3178 boldface
->bold_sim_tested
= 1;
3179 fontfamily_add_font(family
, boldface
);
3185 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3189 for (i
= 0; i
< family
->font_count
; i
++) {
3190 UINT32 regular
= ~0u, oblique
= ~0u;
3191 struct dwrite_font_data
*obliqueface
;
3192 WCHAR facenameW
[255];
3194 if (family
->fonts
[i
]->oblique_sim_tested
)
3197 family
->fonts
[i
]->oblique_sim_tested
= 1;
3198 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3200 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3203 /* find regular style with same weight/stretch values */
3204 for (j
= i
; j
< family
->font_count
; j
++) {
3205 if (family
->fonts
[j
]->oblique_sim_tested
)
3208 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3209 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3211 family
->fonts
[j
]->oblique_sim_tested
= 1;
3212 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3215 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3219 if (regular
!= ~0u && oblique
!= ~0u)
3223 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3227 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3231 /* add oblique simulation based on this regular face */
3233 /* remove regular term if any, append 'Oblique' */
3234 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3235 facename_remove_regular_term(facenameW
, -1);
3238 strcatW(facenameW
, spaceW
);
3239 strcatW(facenameW
, obliqueW
);
3241 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3242 obliqueface
->oblique_sim_tested
= 1;
3243 fontfamily_add_font(family
, obliqueface
);
3248 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3249 const WCHAR
*replacement_name
)
3251 UINT32 i
= collection_find_family(collection
, replacement_name
);
3252 struct dwrite_fontfamily_data
*target
;
3253 IDWriteLocalizedStrings
*strings
;
3256 /* replacement does not exist */
3260 hr
= create_localizedstrings(&strings
);
3264 /* add a new family with target name, reuse font data from replacement */
3265 add_localizedstring(strings
, enusW
, target_name
);
3266 hr
= init_fontfamily_data(strings
, &target
);
3268 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3271 for (i
= 0; i
< replacement
->font_count
; i
++)
3272 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3274 fontcollection_add_family(collection
, target
);
3275 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3276 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3278 IDWriteLocalizedStrings_Release(strings
);
3282 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3283 system font collections. */
3284 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3286 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3291 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3294 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3299 max_namelen
++; /* returned value doesn't include room for '\0' */
3300 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3301 data
= heap_alloc(max_datalen
);
3303 datalen
= max_datalen
;
3304 namelen
= max_namelen
;
3305 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3306 if (collection_find_family(collection
, name
) == ~0u) {
3307 if (type
== REG_MULTI_SZ
) {
3308 WCHAR
*replacement
= data
;
3309 while (*replacement
) {
3310 if (fontcollection_add_replacement(collection
, name
, replacement
))
3312 replacement
+= strlenW(replacement
) + 1;
3315 else if (type
== REG_SZ
)
3316 fontcollection_add_replacement(collection
, name
, data
);
3319 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3321 datalen
= max_datalen
;
3322 namelen
= max_namelen
;
3330 HRESULT
create_font_collection(IDWriteFactory2
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
3332 struct fontfile_enum
{
3334 IDWriteFontFile
*file
;
3336 struct fontfile_enum
*fileenum
, *fileenum2
;
3337 struct dwrite_fontcollection
*collection
;
3338 struct list scannedfiles
;
3339 BOOL current
= FALSE
;
3345 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3346 if (!collection
) return E_OUTOFMEMORY
;
3348 hr
= init_font_collection(collection
, is_system
);
3350 heap_free(collection
);
3354 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3356 TRACE("building font collection:\n");
3358 list_init(&scannedfiles
);
3359 while (hr
== S_OK
) {
3360 DWRITE_FONT_FACE_TYPE face_type
;
3361 DWRITE_FONT_FILE_TYPE file_type
;
3362 BOOL supported
, same
= FALSE
;
3363 IDWriteFontFile
*file
;
3367 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3368 if (FAILED(hr
) || !current
)
3371 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3375 /* check if we've scanned this file already */
3376 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3377 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3382 IDWriteFontFile_Release(file
);
3386 /* failed font files are skipped */
3387 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3388 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3389 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3390 IDWriteFontFile_Release(file
);
3395 /* add to scanned list */
3396 fileenum
= heap_alloc(sizeof(*fileenum
));
3397 fileenum
->file
= file
;
3398 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3400 for (i
= 0; i
< face_count
; i
++) {
3401 IDWriteLocalizedStrings
*family_name
= NULL
;
3402 struct dwrite_font_data
*font_data
;
3406 /* alloc and init new font data structure */
3407 hr
= init_font_data(factory
, file
, face_type
, i
, &family_name
, &font_data
);
3409 /* move to next one */
3414 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3416 index
= collection_find_family(collection
, familyW
);
3418 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3420 struct dwrite_fontfamily_data
*family_data
;
3422 /* create and init new family */
3423 hr
= init_fontfamily_data(family_name
, &family_data
);
3425 /* add font to family, family - to collection */
3426 hr
= fontfamily_add_font(family_data
, font_data
);
3428 hr
= fontcollection_add_family(collection
, family_data
);
3431 release_fontfamily_data(family_data
);
3435 IDWriteLocalizedStrings_Release(family_name
);
3442 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3443 IDWriteFontFile_Release(fileenum
->file
);
3444 list_remove(&fileenum
->entry
);
3445 heap_free(fileenum
);
3448 for (i
= 0; i
< collection
->family_count
; i
++) {
3449 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3450 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3454 fontcollection_add_replacements(collection
);
3459 struct system_fontfile_enumerator
3461 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3464 IDWriteFactory2
*factory
;
3469 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3471 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3474 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3478 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3479 IDWriteFontFileEnumerator_AddRef(iface
);
3484 return E_NOINTERFACE
;
3487 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3489 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3490 return InterlockedIncrement(&enumerator
->ref
);
3493 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3495 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3496 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3499 IDWriteFactory2_Release(enumerator
->factory
);
3500 RegCloseKey(enumerator
->hkey
);
3501 heap_free(enumerator
);
3507 static HRESULT
create_local_file_reference(IDWriteFactory2
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3511 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3512 if (!strchrW(filename
, '\\')) {
3513 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3514 WCHAR fullpathW
[MAX_PATH
];
3516 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3517 strcatW(fullpathW
, fontsW
);
3518 strcatW(fullpathW
, filename
);
3520 hr
= IDWriteFactory2_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3523 hr
= IDWriteFactory2_CreateFontFileReference(factory
, filename
, NULL
, file
);
3528 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3530 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3531 DWORD ret
, type
, val_count
, count
;
3532 WCHAR
*value
, *filename
;
3537 if (enumerator
->index
< 0)
3540 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3541 if (ret
!= ERROR_SUCCESS
)
3545 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3546 filename
= heap_alloc(count
);
3547 if (!value
|| !filename
) {
3549 heap_free(filename
);
3550 return E_OUTOFMEMORY
;
3553 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3556 heap_free(filename
);
3560 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3563 heap_free(filename
);
3567 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3569 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3570 DWORD ret
, max_val_count
;
3574 enumerator
->index
++;
3576 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
3577 if (ret
!= ERROR_SUCCESS
)
3581 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
3582 return E_OUTOFMEMORY
;
3584 /* iterate until we find next string value */
3586 DWORD type
= 0, count
, val_count
;
3587 val_count
= max_val_count
;
3588 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
3590 if (type
== REG_SZ
) {
3594 enumerator
->index
++;
3597 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3602 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3604 systemfontfileenumerator_QueryInterface
,
3605 systemfontfileenumerator_AddRef
,
3606 systemfontfileenumerator_Release
,
3607 systemfontfileenumerator_MoveNext
,
3608 systemfontfileenumerator_GetCurrentFontFile
3611 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory2
*factory
, IDWriteFontFileEnumerator
**ret
)
3613 struct system_fontfile_enumerator
*enumerator
;
3614 static const WCHAR fontslistW
[] = {
3615 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3616 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3617 'F','o','n','t','s',0
3622 enumerator
= heap_alloc(sizeof(*enumerator
));
3624 return E_OUTOFMEMORY
;
3626 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3627 enumerator
->ref
= 1;
3628 enumerator
->factory
= factory
;
3629 enumerator
->index
= -1;
3630 IDWriteFactory2_AddRef(factory
);
3632 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3633 ERR("failed to open fonts list key\n");
3634 IDWriteFactory2_Release(factory
);
3635 heap_free(enumerator
);
3639 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3644 HRESULT
get_system_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
3646 IDWriteFontFileEnumerator
*enumerator
;
3651 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3655 TRACE("building system font collection for factory %p\n", factory
);
3656 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3657 IDWriteFontFileEnumerator_Release(enumerator
);
3661 static HRESULT
eudc_collection_add_family(IDWriteFactory2
*factory
, struct dwrite_fontcollection
*collection
,
3662 const WCHAR
*keynameW
, const WCHAR
*pathW
)
3664 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};
3665 static const WCHAR emptyW
[] = {0};
3666 IDWriteLocalizedStrings
*names
;
3667 DWRITE_FONT_FACE_TYPE face_type
;
3668 DWRITE_FONT_FILE_TYPE file_type
;
3670 UINT32 face_count
, i
;
3671 IDWriteFontFile
*file
;
3673 struct dwrite_fontfamily_data
*family_data
;
3675 /* create font file from this path */
3676 hr
= create_local_file_reference(factory
, pathW
, &file
);
3680 /* failed font files are skipped */
3681 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3682 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3683 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3684 IDWriteFontFile_Release(file
);
3688 /* create and init new family */
3690 /* Family names are added for non-specific locale, represented with empty string.
3691 Default family appears with empty family name. */
3692 create_localizedstrings(&names
);
3693 if (!strcmpiW(keynameW
, defaultfontW
))
3694 add_localizedstring(names
, emptyW
, emptyW
);
3696 add_localizedstring(names
, emptyW
, keynameW
);
3698 hr
= init_fontfamily_data(names
, &family_data
);
3699 IDWriteLocalizedStrings_Release(names
);
3701 IDWriteFontFile_Release(file
);
3705 /* fill with faces */
3706 for (i
= 0; i
< face_count
; i
++) {
3707 struct dwrite_font_data
*font_data
;
3709 /* alloc and init new font data structure */
3710 hr
= init_font_data(factory
, file
, face_type
, i
, &names
, &font_data
);
3714 IDWriteLocalizedStrings_Release(names
);
3716 /* add font to family */
3717 hr
= fontfamily_add_font(family_data
, font_data
);
3719 release_font_data(font_data
);
3722 /* add family to collection */
3723 hr
= fontcollection_add_family(collection
, family_data
);
3725 release_fontfamily_data(family_data
);
3726 IDWriteFontFile_Release(file
);
3731 HRESULT
get_eudc_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**ret
)
3733 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
3734 struct dwrite_fontcollection
*collection
;
3735 static const WCHAR emptyW
[] = {0};
3736 WCHAR eudckeypathW
[16];
3744 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
3748 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3749 if (!collection
) return E_OUTOFMEMORY
;
3751 hr
= init_font_collection(collection
, FALSE
);
3753 heap_free(collection
);
3757 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3759 /* return empty collection if EUDC fonts are not configured */
3760 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
3761 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
3764 retval
= ERROR_SUCCESS
;
3766 while (retval
!= ERROR_NO_MORE_ITEMS
) {
3767 WCHAR keynameW
[64], pathW
[MAX_PATH
];
3768 DWORD type
, path_len
, name_len
;
3770 path_len
= sizeof(pathW
)/sizeof(*pathW
);
3771 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
3772 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
3773 if (retval
|| type
!= REG_SZ
)
3776 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
3778 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
3780 RegCloseKey(eudckey
);
3782 /* try to add global default if not defined for specific codepage */
3784 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
3786 if (FAILED(hr
) || !exists
) {
3787 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
3788 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
3790 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
3793 /* EUDC collection offers simulated faces too */
3794 for (i
= 0; i
< collection
->family_count
; i
++) {
3795 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3796 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3802 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
3804 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3806 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3808 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
3811 IDWriteFontFile_AddRef(iface
);
3816 return E_NOINTERFACE
;
3819 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
3821 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3822 ULONG ref
= InterlockedIncrement(&This
->ref
);
3823 TRACE("(%p)->(%d)\n", This
, ref
);
3827 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
3829 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3830 ULONG ref
= InterlockedDecrement(&This
->ref
);
3832 TRACE("(%p)->(%d)\n", This
, ref
);
3836 IDWriteFontFileLoader_Release(This
->loader
);
3837 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
3838 heap_free(This
->reference_key
);
3845 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
3847 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3848 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
3849 *fontFileReferenceKey
= This
->reference_key
;
3850 *fontFileReferenceKeySize
= This
->key_size
;
3855 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
3857 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3858 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
3859 *fontFileLoader
= This
->loader
;
3860 IDWriteFontFileLoader_AddRef(This
->loader
);
3865 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
3866 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
3868 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3869 IDWriteFontFileStream
*stream
;
3872 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
3874 *isSupportedFontType
= FALSE
;
3875 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3877 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3880 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
3884 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
3886 /* TODO: Further Analysis */
3887 IDWriteFontFileStream_Release(stream
);
3891 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
3892 dwritefontfile_QueryInterface
,
3893 dwritefontfile_AddRef
,
3894 dwritefontfile_Release
,
3895 dwritefontfile_GetReferenceKey
,
3896 dwritefontfile_GetLoader
,
3897 dwritefontfile_Analyze
,
3900 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
3902 struct dwrite_fontfile
*This
;
3904 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
3905 if (!This
) return E_OUTOFMEMORY
;
3907 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
3909 IDWriteFontFileLoader_AddRef(loader
);
3910 This
->loader
= loader
;
3911 This
->stream
= NULL
;
3912 This
->reference_key
= heap_alloc(key_size
);
3913 memcpy(This
->reference_key
, reference_key
, key_size
);
3914 This
->key_size
= key_size
;
3916 *font_file
= &This
->IDWriteFontFile_iface
;
3921 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3923 IDWriteFontFileLoader
*loader
;
3929 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3933 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3935 IDWriteFontFileLoader_Release(loader
);
3939 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3940 IDWriteFontFileLoader_Release(loader
);
3945 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
3946 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
3948 struct dwrite_fontface
*fontface
;
3954 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
3956 return E_OUTOFMEMORY
;
3958 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
3959 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
3961 if (!fontface
->files
|| !fontface
->streams
) {
3962 heap_free(fontface
->files
);
3963 heap_free(fontface
->streams
);
3964 heap_free(fontface
);
3965 return E_OUTOFMEMORY
;
3968 fontface
->IDWriteFontFace3_iface
.lpVtbl
= &dwritefontfacevtbl
;
3970 fontface
->type
= facetype
;
3971 fontface
->file_count
= files_number
;
3972 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
3973 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
3974 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
3975 memset(&fontface
->cpal
, 0, sizeof(fontface
->cpal
));
3976 memset(&fontface
->colr
, 0, sizeof(fontface
->colr
));
3977 fontface
->cmap
.exists
= TRUE
;
3978 fontface
->vdmx
.exists
= TRUE
;
3979 fontface
->gasp
.exists
= TRUE
;
3980 fontface
->cpal
.exists
= TRUE
;
3981 fontface
->colr
.exists
= TRUE
;
3982 fontface
->index
= index
;
3983 fontface
->simulations
= simulations
;
3984 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
3986 for (i
= 0; i
< fontface
->file_count
; i
++) {
3987 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
3989 IDWriteFontFace3_Release(&fontface
->IDWriteFontFace3_iface
);
3993 fontface
->files
[i
] = font_files
[i
];
3994 IDWriteFontFile_AddRef(font_files
[i
]);
3997 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
3998 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
3999 /* TODO: test what happens if caret is already slanted */
4000 if (fontface
->caret
.slopeRise
== 1) {
4001 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4002 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4005 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace3_iface
, &fontface
->is_symbol
);
4006 fontface
->has_kerning_pairs
= freetype_has_kerning_pairs(&fontface
->IDWriteFontFace3_iface
);
4007 fontface
->is_monospaced
= freetype_is_monospaced(&fontface
->IDWriteFontFace3_iface
);
4009 *ret
= &fontface
->IDWriteFontFace3_iface
;
4013 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4020 struct local_cached_stream
4023 IDWriteFontFileStream
*stream
;
4024 struct local_refkey
*key
;
4028 struct dwrite_localfontfilestream
4030 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4033 struct local_cached_stream
*entry
;
4034 const void *file_ptr
;
4038 struct dwrite_localfontfileloader
{
4039 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4042 struct list streams
;
4045 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4047 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4050 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4052 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4055 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4057 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4058 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4059 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
4062 IDWriteFontFileStream_AddRef(iface
);
4067 return E_NOINTERFACE
;
4070 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4072 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4073 ULONG ref
= InterlockedIncrement(&This
->ref
);
4074 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4078 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4080 list_remove(&stream
->entry
);
4081 heap_free(stream
->key
);
4085 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4087 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4088 ULONG ref
= InterlockedDecrement(&This
->ref
);
4090 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4093 UnmapViewOfFile(This
->file_ptr
);
4094 release_cached_stream(This
->entry
);
4101 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4103 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4105 TRACE_(dwrite_file
)("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
4106 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4108 *fragment_context
= NULL
;
4110 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4111 *fragment_start
= NULL
;
4115 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4119 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4121 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4122 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4125 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4127 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4128 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4133 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4135 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4138 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4140 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4141 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4142 *last_writetime
= li
.QuadPart
;
4147 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4149 localfontfilestream_QueryInterface
,
4150 localfontfilestream_AddRef
,
4151 localfontfilestream_Release
,
4152 localfontfilestream_ReadFileFragment
,
4153 localfontfilestream_ReleaseFileFragment
,
4154 localfontfilestream_GetFileSize
,
4155 localfontfilestream_GetLastWriteTime
4158 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4160 struct dwrite_localfontfilestream
*This
;
4164 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4166 return E_OUTOFMEMORY
;
4168 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4171 This
->file_ptr
= file_ptr
;
4173 This
->entry
= entry
;
4175 *ret
= &This
->IDWriteFontFileStream_iface
;
4179 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4181 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4183 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4185 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
4188 IDWriteLocalFontFileLoader_AddRef(iface
);
4193 return E_NOINTERFACE
;
4196 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4198 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4199 ULONG ref
= InterlockedIncrement(&This
->ref
);
4200 TRACE("(%p)->(%d)\n", This
, ref
);
4204 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4206 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4207 ULONG ref
= InterlockedDecrement(&This
->ref
);
4209 TRACE("(%p)->(%d)\n", This
, ref
);
4212 struct local_cached_stream
*stream
, *stream2
;
4214 /* This will detach all entries from cache. Entries are released together with streams,
4215 so stream controls cache entry lifetime. */
4216 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
4217 list_init(&stream
->entry
);
4225 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
4227 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4228 const struct local_refkey
*refkey
= key
;
4229 struct local_cached_stream
*stream
;
4230 IDWriteFontFileStream
*filestream
;
4231 HANDLE file
, mapping
;
4236 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
4237 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4239 /* search cache first */
4240 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4241 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4242 *ret
= stream
->stream
;
4243 IDWriteFontFileStream_AddRef(*ret
);
4250 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4251 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4252 if (file
== INVALID_HANDLE_VALUE
)
4255 GetFileSizeEx(file
, &size
);
4256 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4261 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4262 CloseHandle(mapping
);
4264 stream
= heap_alloc(sizeof(*stream
));
4266 UnmapViewOfFile(file_ptr
);
4267 return E_OUTOFMEMORY
;
4270 stream
->key
= heap_alloc(key_size
);
4272 UnmapViewOfFile(file_ptr
);
4274 return E_OUTOFMEMORY
;
4277 stream
->key_size
= key_size
;
4278 memcpy(stream
->key
, key
, key_size
);
4280 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4282 UnmapViewOfFile(file_ptr
);
4283 heap_free(stream
->key
);
4288 stream
->stream
= filestream
;
4289 list_add_head(&This
->streams
, &stream
->entry
);
4291 *ret
= stream
->stream
;
4296 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4298 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4299 const struct local_refkey
*refkey
= key
;
4301 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4303 *length
= strlenW(refkey
->name
);
4307 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4309 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4310 const struct local_refkey
*refkey
= key
;
4312 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4314 if (length
< strlenW(refkey
->name
))
4315 return E_INVALIDARG
;
4317 strcpyW(path
, refkey
->name
);
4321 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
4323 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4324 const struct local_refkey
*refkey
= key
;
4326 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
4328 *writetime
= refkey
->writetime
;
4332 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4333 localfontfileloader_QueryInterface
,
4334 localfontfileloader_AddRef
,
4335 localfontfileloader_Release
,
4336 localfontfileloader_CreateStreamFromKey
,
4337 localfontfileloader_GetFilePathLengthFromKey
,
4338 localfontfileloader_GetFilePathFromKey
,
4339 localfontfileloader_GetLastWriteTimeFromKey
4342 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
**ret
)
4344 struct dwrite_localfontfileloader
*This
;
4348 This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
4350 return E_OUTOFMEMORY
;
4352 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4354 list_init(&This
->streams
);
4356 *ret
= &This
->IDWriteLocalFontFileLoader_iface
;
4360 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4362 struct local_refkey
*refkey
;
4364 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4367 refkey
= heap_alloc(*size
);
4369 return E_OUTOFMEMORY
;
4372 refkey
->writetime
= *writetime
;
4374 WIN32_FILE_ATTRIBUTE_DATA info
;
4376 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4377 refkey
->writetime
= info
.ftLastWriteTime
;
4379 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4381 strcpyW(refkey
->name
, path
);
4388 /* IDWriteGlyphRunAnalysis */
4389 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4391 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4393 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4395 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4396 IsEqualIID(riid
, &IID_IUnknown
))
4399 IDWriteGlyphRunAnalysis_AddRef(iface
);
4404 return E_NOINTERFACE
;
4407 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4409 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4410 ULONG ref
= InterlockedIncrement(&This
->ref
);
4411 TRACE("(%p)->(%u)\n", This
, ref
);
4415 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4417 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4418 ULONG ref
= InterlockedDecrement(&This
->ref
);
4420 TRACE("(%p)->(%u)\n", This
, ref
);
4423 if (This
->run
.fontFace
)
4424 IDWriteFontFace_Release(This
->run
.fontFace
);
4425 heap_free(This
->glyphs
);
4426 heap_free(This
->advances
);
4427 heap_free(This
->advanceoffsets
);
4428 heap_free(This
->ascenderoffsets
);
4429 heap_free(This
->bitmap
);
4436 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4438 struct dwrite_glyphbitmap glyph_bitmap
;
4439 IDWriteFontFace3
*fontface3
;
4440 D2D_POINT_2F origin
;
4445 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4446 *bounds
= analysis
->bounds
;
4450 if (analysis
->run
.isSideways
)
4451 FIXME("sideways runs are not supported.\n");
4453 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
4455 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4457 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
4458 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
4459 for any non-zero glyph ascender */
4460 origin
.x
= origin
.y
= 0.0f
;
4461 is_rtl
= analysis
->run
.bidiLevel
& 1;
4463 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4464 glyph_bitmap
.fontface
= fontface3
;
4465 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4466 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4467 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4468 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4469 glyph_bitmap
.m
= &analysis
->m
;
4471 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4472 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4473 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4474 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4475 RECT
*bbox
= &glyph_bitmap
.bbox
;
4477 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4478 freetype_get_glyph_bbox(&glyph_bitmap
);
4481 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4483 OffsetRect(bbox
, origin
.x
, origin
.y
);
4486 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4488 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4489 origin
.x
+= advance
->x
;
4490 origin
.y
+= advance
->y
;
4493 IDWriteFontFace3_Release(fontface3
);
4495 /* translate to given run origin */
4496 OffsetRect(&analysis
->bounds
, analysis
->origin
.x
, analysis
->origin
.y
);
4497 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4498 OffsetRect(&analysis
->bounds
, analysis
->m
.dx
, analysis
->m
.dy
);
4500 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4501 *bounds
= analysis
->bounds
;
4504 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4506 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4508 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4510 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4511 memset(bounds
, 0, sizeof(*bounds
));
4512 return E_INVALIDARG
;
4515 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
4516 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
4517 memset(bounds
, 0, sizeof(*bounds
));
4521 glyphrunanalysis_get_texturebounds(This
, bounds
);
4525 static inline int get_dib_stride( int width
, int bpp
)
4527 return ((width
* bpp
+ 31) >> 3) & ~3;
4530 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4532 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4533 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4534 (runbounds
->left
- bounds
->left
) * 3;
4536 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4537 runbounds
->left
- bounds
->left
;
4540 static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
, DWRITE_TEXTURE_TYPE type
)
4542 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4543 struct dwrite_glyphbitmap glyph_bitmap
;
4544 IDWriteFontFace3
*fontface2
;
4545 D2D_POINT_2F origin
;
4551 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface2
);
4553 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4557 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4558 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4560 analysis
->bitmap
= heap_alloc_zero(size
);
4562 origin
.x
= origin
.y
= 0.0f
;
4563 is_rtl
= analysis
->run
.bidiLevel
& 1;
4565 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4566 glyph_bitmap
.fontface
= fontface2
;
4567 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4568 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4569 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4570 glyph_bitmap
.type
= type
;
4571 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4572 glyph_bitmap
.m
= &analysis
->m
;
4573 bbox
= &glyph_bitmap
.bbox
;
4575 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4576 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4577 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4578 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4579 int x
, y
, width
, height
;
4583 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4584 freetype_get_glyph_bbox(&glyph_bitmap
);
4586 if (IsRectEmpty(bbox
)) {
4587 origin
.x
+= advance
->x
;
4588 origin
.y
+= advance
->y
;
4592 width
= bbox
->right
- bbox
->left
;
4593 height
= bbox
->bottom
- bbox
->top
;
4595 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4596 glyph_bitmap
.pitch
= (width
+ 3) / 4 * 4;
4598 glyph_bitmap
.pitch
= ((width
+ 31) >> 5) << 2;
4600 glyph_bitmap
.buf
= src
= heap_alloc_zero(height
* glyph_bitmap
.pitch
);
4601 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4604 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4606 OffsetRect(bbox
, origin
.x
, origin
.y
);
4609 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4611 OffsetRect(bbox
, analysis
->origin
.x
, analysis
->origin
.y
);
4612 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4613 OffsetRect(bbox
, analysis
->m
.dx
, analysis
->m
.dy
);
4615 /* blit to analysis bitmap */
4616 dst
= get_pixel_ptr(analysis
->bitmap
, type
, bbox
, &analysis
->bounds
);
4619 /* convert 1bpp to 8bpp/24bpp */
4620 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4621 for (y
= 0; y
< height
; y
++) {
4622 for (x
= 0; x
< width
; x
++)
4623 if (src
[x
/ 8] & masks
[x
% 8])
4624 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4625 src
+= glyph_bitmap
.pitch
;
4626 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4630 for (y
= 0; y
< height
; y
++) {
4631 for (x
= 0; x
< width
; x
++)
4632 if (src
[x
/ 8] & masks
[x
% 8])
4633 dst
[x
] = DWRITE_ALPHA_MAX
;
4634 src
+= get_dib_stride(width
, 1);
4635 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
4640 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
4641 for (y
= 0; y
< height
; y
++) {
4642 for (x
= 0; x
< width
; x
++)
4643 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
4644 src
+= glyph_bitmap
.pitch
;
4645 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4649 heap_free(glyph_bitmap
.buf
);
4651 origin
.x
+= advance
->x
;
4652 origin
.y
+= advance
->y
;
4655 IDWriteFontFace3_Release(fontface2
);
4657 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
4659 /* we don't need this anymore */
4660 heap_free(analysis
->glyphs
);
4661 heap_free(analysis
->advances
);
4662 heap_free(analysis
->advanceoffsets
);
4663 heap_free(analysis
->ascenderoffsets
);
4664 IDWriteFontFace_Release(analysis
->run
.fontFace
);
4666 analysis
->glyphs
= NULL
;
4667 analysis
->advances
= NULL
;
4668 analysis
->advanceoffsets
= NULL
;
4669 analysis
->ascenderoffsets
= NULL
;
4670 analysis
->run
.glyphIndices
= NULL
;
4671 analysis
->run
.fontFace
= NULL
;
4674 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
4675 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
4677 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4681 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
4683 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
4684 return E_INVALIDARG
;
4686 /* make sure buffer is large enough for requested texture type */
4687 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
4688 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4691 if (size
< required
)
4692 return E_NOT_SUFFICIENT_BUFFER
;
4694 /* validate requested texture type with rendering mode */
4695 switch (This
->rendering_mode
)
4697 case DWRITE_RENDERING_MODE_ALIASED
:
4698 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
4699 return DWRITE_E_UNSUPPORTEDOPERATION
;
4701 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4702 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4703 case DWRITE_RENDERING_MODE_NATURAL
:
4704 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4705 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
4706 return DWRITE_E_UNSUPPORTEDOPERATION
;
4712 memset(bitmap
, 0, size
);
4713 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
4714 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
4715 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
4716 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
4717 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
4718 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
4722 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
))
4723 glyphrunanalysis_render(This
, type
);
4725 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
4726 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
4728 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
4729 memcpy(dst
, src
, draw_width
);
4738 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
4739 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
4741 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4743 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
4746 return E_INVALIDARG
;
4748 switch (This
->rendering_mode
)
4750 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4751 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4754 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
4755 *gamma
= (FLOAT
)value
/ 1000.0f
;
4757 *cleartypelevel
= 1.0f
;
4760 case DWRITE_RENDERING_MODE_ALIASED
:
4761 case DWRITE_RENDERING_MODE_NATURAL
:
4762 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4763 *gamma
= IDWriteRenderingParams_GetGamma(params
);
4764 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
4765 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
4774 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
4775 glyphrunanalysis_QueryInterface
,
4776 glyphrunanalysis_AddRef
,
4777 glyphrunanalysis_Release
,
4778 glyphrunanalysis_GetAlphaTextureBounds
,
4779 glyphrunanalysis_CreateAlphaTexture
,
4780 glyphrunanalysis_GetAlphaBlendParams
4783 static inline void init_2d_vec(D2D_POINT_2F
*vec
, FLOAT length
, BOOL is_vertical
)
4795 static inline void transform_2d_vec(D2D_POINT_2F
*vec
, const DWRITE_MATRIX
*m
)
4798 ret
.x
= vec
->x
* m
->m11
+ vec
->y
* m
->m21
;
4799 ret
.y
= vec
->x
* m
->m12
+ vec
->y
* m
->m22
;
4803 HRESULT
create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_GLYPH_RUN
const *run
,
4804 FLOAT ppdip
, const DWRITE_MATRIX
*transform
, DWRITE_GRID_FIT_MODE gridfit_mode
, DWRITE_TEXT_ANTIALIAS_MODE aa_mode
,
4805 FLOAT originX
, FLOAT originY
, IDWriteGlyphRunAnalysis
**ret
)
4807 struct dwrite_glyphrunanalysis
*analysis
;
4813 /* check for valid rendering mode */
4814 if ((UINT32
)rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
4815 return E_INVALIDARG
;
4817 analysis
= heap_alloc(sizeof(*analysis
));
4819 return E_OUTOFMEMORY
;
4821 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
4823 analysis
->rendering_mode
= rendering_mode
;
4824 analysis
->flags
= 0;
4825 analysis
->bitmap
= NULL
;
4826 analysis
->ppdip
= ppdip
;
4827 analysis
->origin
.x
= originX
* ppdip
;
4828 analysis
->origin
.y
= originY
* ppdip
;
4829 SetRectEmpty(&analysis
->bounds
);
4830 analysis
->run
= *run
;
4831 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
4832 analysis
->glyphs
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphIndices
));
4833 analysis
->advances
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advances
));
4834 if (run
->glyphOffsets
) {
4835 analysis
->advanceoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advanceoffsets
));
4836 analysis
->ascenderoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->ascenderoffsets
));
4839 analysis
->advanceoffsets
= NULL
;
4840 analysis
->ascenderoffsets
= NULL
;
4843 if (!analysis
->glyphs
|| !analysis
->advances
|| ((!analysis
->advanceoffsets
|| !analysis
->ascenderoffsets
) && run
->glyphOffsets
)) {
4844 heap_free(analysis
->glyphs
);
4845 heap_free(analysis
->advances
);
4846 heap_free(analysis
->advanceoffsets
);
4847 heap_free(analysis
->ascenderoffsets
);
4849 analysis
->glyphs
= NULL
;
4850 analysis
->advances
= NULL
;
4851 analysis
->advanceoffsets
= NULL
;
4852 analysis
->ascenderoffsets
= NULL
;
4854 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
4855 return E_OUTOFMEMORY
;
4858 /* check if transform is usable */
4859 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
))) {
4860 analysis
->m
= *transform
;
4861 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
4864 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
4866 analysis
->run
.glyphIndices
= analysis
->glyphs
;
4867 analysis
->run
.glyphAdvances
= NULL
;
4868 analysis
->run
.glyphOffsets
= NULL
;
4870 rtl_factor
= run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
4872 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4873 transform_2d_vec(&analysis
->origin
, &analysis
->m
);
4875 memcpy(analysis
->glyphs
, run
->glyphIndices
, run
->glyphCount
*sizeof(*run
->glyphIndices
));
4877 if (run
->glyphAdvances
) {
4878 for (i
= 0; i
< run
->glyphCount
; i
++) {
4879 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* run
->glyphAdvances
[i
] * ppdip
, run
->isSideways
);
4880 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4881 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4885 DWRITE_FONT_METRICS metrics
;
4886 IDWriteFontFace1
*fontface1
;
4888 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
4889 IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4891 for (i
= 0; i
< run
->glyphCount
; i
++) {
4895 switch (measuring_mode
)
4897 case DWRITE_MEASURING_MODE_NATURAL
:
4898 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
4901 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
) * ppdip
,
4904 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
4905 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
4906 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, run
->fontEmSize
, ppdip
, transform
,
4907 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
4909 init_2d_vec(analysis
->advances
+ i
, 0.0f
, FALSE
);
4911 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* floorf(a
* run
->fontEmSize
* ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
),
4918 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4919 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4922 IDWriteFontFace1_Release(fontface1
);
4925 if (run
->glyphOffsets
) {
4926 for (i
= 0; i
< run
->glyphCount
; i
++) {
4927 init_2d_vec(analysis
->advanceoffsets
+ i
, rtl_factor
* run
->glyphOffsets
[i
].advanceOffset
* ppdip
, run
->isSideways
);
4928 /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
4929 init_2d_vec(analysis
->ascenderoffsets
+ i
, -run
->glyphOffsets
[i
].ascenderOffset
* ppdip
, !run
->isSideways
);
4930 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
) {
4931 transform_2d_vec(analysis
->advanceoffsets
+ i
, &analysis
->m
);
4932 transform_2d_vec(analysis
->ascenderoffsets
+ i
, &analysis
->m
);
4937 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
4941 /* IDWriteColorGlyphRunEnumerator */
4942 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
4944 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4946 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4948 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
4949 IsEqualIID(riid
, &IID_IUnknown
))
4952 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
4957 return E_NOINTERFACE
;
4960 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
4962 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4963 ULONG ref
= InterlockedIncrement(&This
->ref
);
4964 TRACE("(%p)->(%u)\n", This
, ref
);
4968 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
4970 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4971 ULONG ref
= InterlockedDecrement(&This
->ref
);
4973 TRACE("(%p)->(%u)\n", This
, ref
);
4976 heap_free(This
->advances
);
4977 heap_free(This
->color_advances
);
4978 heap_free(This
->offsets
);
4979 heap_free(This
->color_offsets
);
4980 heap_free(This
->glyphindices
);
4981 heap_free(This
->glyphs
);
4982 if (This
->colr
.context
)
4983 IDWriteFontFace3_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
4984 IDWriteFontFace3_Release(This
->fontface
);
4991 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
4993 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
4994 FLOAT origin
= 0.0f
;
5000 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5004 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5006 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5007 FLOAT advance_adj
= 0.0f
;
5008 BOOL got_palette_index
;
5011 /* start with regular glyphs */
5012 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5013 UINT32 first_glyph
= 0;
5015 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5016 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5017 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5018 first_glyph
= min(first_glyph
, g
);
5021 glyphenum
->glyphindices
[g
] = 1;
5022 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5023 if (glyphenum
->color_offsets
)
5024 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5027 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5028 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5029 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5030 colorrun
->paletteIndex
= 0xffff;
5031 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5032 glyphenum
->has_regular_glyphs
= FALSE
;
5036 colorrun
->glyphRun
.glyphCount
= 0;
5037 got_palette_index
= FALSE
;
5041 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5043 glyphenum
->glyphindices
[g
] = 1;
5045 /* all glyph layers were returned */
5046 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5047 advance_adj
+= glyphenum
->advances
[g
];
5051 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5052 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5053 if (!got_palette_index
) {
5054 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5055 /* use foreground color or request one from the font */
5056 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5057 if (colorrun
->paletteIndex
!= 0xffff) {
5058 HRESULT hr
= IDWriteFontFace3_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5059 1, &colorrun
->runColor
);
5061 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5062 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5064 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5065 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5066 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5067 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5068 got_palette_index
= TRUE
;
5071 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5072 /* offsets are relative to glyph origin, nothing to fix up */
5073 if (glyphenum
->color_offsets
)
5074 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5075 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5077 glyphenum
->color_advances
[index
-1] += advance_adj
;
5078 colorrun
->glyphRun
.glyphCount
++;
5082 advance_adj
+= glyphenum
->advances
[g
];
5085 /* reset last advance */
5086 if (colorrun
->glyphRun
.glyphCount
)
5087 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5089 return colorrun
->glyphRun
.glyphCount
> 0;
5092 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5094 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5096 TRACE("(%p)->(%p)\n", This
, has_run
);
5100 This
->colorrun
.glyphRun
.glyphCount
= 0;
5101 while (This
->current_layer
< This
->max_layer_num
) {
5102 if (colorglyphenum_build_color_run(This
))
5105 This
->current_layer
++;
5108 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5113 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5115 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5117 TRACE("(%p)->(%p)\n", This
, run
);
5119 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5121 return E_NOT_VALID_STATE
;
5124 *run
= &This
->colorrun
;
5128 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5129 colorglyphenum_QueryInterface
,
5130 colorglyphenum_AddRef
,
5131 colorglyphenum_Release
,
5132 colorglyphenum_MoveNext
,
5133 colorglyphenum_GetCurrentRun
5136 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5137 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5139 struct dwrite_colorglyphenum
*colorglyphenum
;
5140 BOOL colorfont
, has_colored_glyph
;
5141 IDWriteFontFace3
*fontface3
;
5147 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
5149 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
5153 colorfont
= IDWriteFontFace3_IsColorFont(fontface3
) && IDWriteFontFace3_GetColorPaletteCount(fontface3
) > palette
;
5155 hr
= DWRITE_E_NOCOLOR
;
5159 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5160 if (!colorglyphenum
) {
5165 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5166 colorglyphenum
->ref
= 1;
5167 colorglyphenum
->origin_x
= originX
;
5168 colorglyphenum
->origin_y
= originY
;
5169 colorglyphenum
->fontface
= fontface3
;
5170 colorglyphenum
->glyphs
= NULL
;
5171 colorglyphenum
->run
= *run
;
5172 colorglyphenum
->run
.glyphIndices
= NULL
;
5173 colorglyphenum
->run
.glyphAdvances
= NULL
;
5174 colorglyphenum
->run
.glyphOffsets
= NULL
;
5175 colorglyphenum
->palette
= palette
;
5176 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5177 colorglyphenum
->colr
.exists
= TRUE
;
5178 get_fontface_table(fontface3
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5179 colorglyphenum
->current_layer
= 0;
5180 colorglyphenum
->max_layer_num
= 0;
5182 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5184 has_colored_glyph
= FALSE
;
5185 colorglyphenum
->has_regular_glyphs
= FALSE
;
5186 for (i
= 0; i
< run
->glyphCount
; i
++) {
5187 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5188 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5189 has_colored_glyph
= TRUE
;
5191 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5192 colorglyphenum
->has_regular_glyphs
= TRUE
;
5195 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5196 is supposed to proceed normally, like if font had no color info at all. */
5197 if (!has_colored_glyph
) {
5198 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5199 return DWRITE_E_NOCOLOR
;
5202 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5203 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5204 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5205 if (run
->glyphOffsets
) {
5206 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5207 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5208 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5211 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5212 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5213 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5214 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5216 if (run
->glyphAdvances
)
5217 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5219 DWRITE_FONT_METRICS metrics
;
5221 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5222 for (i
= 0; i
< run
->glyphCount
; i
++) {
5226 switch (measuring_mode
)
5228 case DWRITE_MEASURING_MODE_NATURAL
:
5229 hr
= IDWriteFontFace3_GetDesignGlyphAdvances(fontface3
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5232 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5234 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5235 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5236 hr
= IDWriteFontFace3_GetGdiCompatibleGlyphAdvances(fontface3
, run
->fontEmSize
, 1.0f
, transform
,
5237 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5239 colorglyphenum
->advances
[i
] = 0.0f
;
5241 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5249 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5253 IDWriteFontFace3_Release(fontface3
);