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 IDWriteFontCollection IDWriteFontCollection_iface
;
125 struct dwrite_fontfamily_data
**family_data
;
131 struct dwrite_fontfamily
{
132 IDWriteFontFamily1 IDWriteFontFamily1_iface
;
135 struct dwrite_fontfamily_data
*data
;
137 IDWriteFontCollection
* collection
;
141 IDWriteFont3 IDWriteFont3_iface
;
144 IDWriteFontFamily1
*family
;
146 DWRITE_FONT_STYLE style
;
147 struct dwrite_font_data
*data
;
150 struct dwrite_fonttable
{
157 enum runanalysis_flags
{
158 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
159 RUNANALYSIS_BITMAP_READY
= 1 << 1,
160 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
163 struct dwrite_glyphrunanalysis
{
164 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
167 DWRITE_RENDERING_MODE rendering_mode
;
168 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
173 D2D_POINT_2F
*advances
;
174 D2D_POINT_2F
*advanceoffsets
;
175 D2D_POINT_2F
*ascenderoffsets
;
182 struct dwrite_colorglyphenum
{
183 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
186 FLOAT origin_x
; /* original run origin */
189 IDWriteFontFace3
*fontface
; /* for convenience */
190 DWRITE_COLOR_GLYPH_RUN colorrun
; /* returned with GetCurrentRun() */
191 DWRITE_GLYPH_RUN run
; /* base run */
192 UINT32 palette
; /* palette index to get layer color from */
193 FLOAT
*advances
; /* original or measured advances for base glyphs */
194 FLOAT
*color_advances
; /* returned color run points to this */
195 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
196 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
197 UINT16
*glyphindices
; /* returned color run points to this */
198 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
199 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
200 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
201 UINT16 max_layer_num
; /* max number of layers for this run */
202 struct dwrite_fonttable colr
; /* used to access layers */
205 #define GLYPH_BLOCK_SHIFT 8
206 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
207 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
208 #define GLYPH_MAX 65536
210 struct dwrite_fontface
{
211 IDWriteFontFace3 IDWriteFontFace3_iface
;
214 IDWriteFontFileStream
**streams
;
215 IDWriteFontFile
**files
;
220 DWRITE_FONT_FACE_TYPE type
;
221 DWRITE_FONT_METRICS1 metrics
;
222 DWRITE_CARET_METRICS caret
;
225 BOOL has_kerning_pairs
: 1;
226 BOOL is_monospaced
: 1;
228 struct dwrite_fonttable cmap
;
229 struct dwrite_fonttable vdmx
;
230 struct dwrite_fonttable gasp
;
231 struct dwrite_fonttable cpal
;
232 struct dwrite_fonttable colr
;
233 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
236 struct dwrite_fontfile
{
237 IDWriteFontFile IDWriteFontFile_iface
;
240 IDWriteFontFileLoader
*loader
;
243 IDWriteFontFileStream
*stream
;
246 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace3(IDWriteFontFace3
*iface
)
248 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace3_iface
);
251 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
253 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
256 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
258 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
261 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
263 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
266 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
268 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
271 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
273 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
276 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
278 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
281 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList(IDWriteFontList
*iface
)
283 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList_iface
);
286 static inline const char *debugstr_tag(UINT32 tag
)
288 return debugstr_an((char*)&tag
, 4);
291 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
293 static const DWRITE_GLYPH_METRICS nil
;
294 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
296 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
297 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
301 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
303 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
306 /* start new block */
307 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
309 return E_OUTOFMEMORY
;
312 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
316 static void* get_fontface_table(IDWriteFontFace3
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
320 if (table
->data
|| !table
->exists
)
323 table
->exists
= FALSE
;
324 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
326 if (FAILED(hr
) || !table
->exists
) {
327 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
334 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
335 struct dwrite_font_propvec
*vec
)
337 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
338 vec
->style
= style
* 7.0f
;
339 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
342 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
344 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
347 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
349 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
352 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
354 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
357 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
359 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
362 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
364 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_GASP_TAG
, &fontface
->gasp
);
365 *size
= fontface
->gasp
.size
;
369 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
371 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
374 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
376 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_COLR_TAG
, &fontface
->colr
);
379 static void release_font_data(struct dwrite_font_data
*data
)
383 if (InterlockedDecrement(&data
->ref
) > 0)
386 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
387 if (data
->info_strings
[i
])
388 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
391 IDWriteLocalizedStrings_Release(data
->names
);
393 IDWriteFontFile_Release(data
->file
);
394 IDWriteFactory2_Release(data
->factory
);
395 heap_free(data
->facename
);
399 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
403 if (InterlockedDecrement(&data
->ref
) > 0)
406 for (i
= 0; i
< data
->font_count
; i
++)
407 release_font_data(data
->fonts
[i
]);
408 heap_free(data
->fonts
);
409 IDWriteLocalizedStrings_Release(data
->familyname
);
413 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace3
*iface
, REFIID riid
, void **obj
)
415 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
417 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
419 if (IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
420 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
421 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
422 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
423 IsEqualIID(riid
, &IID_IUnknown
))
426 IDWriteFontFace3_AddRef(iface
);
431 return E_NOINTERFACE
;
434 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace3
*iface
)
436 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
437 ULONG ref
= InterlockedIncrement(&This
->ref
);
438 TRACE("(%p)->(%d)\n", This
, ref
);
442 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace3
*iface
)
444 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
445 ULONG ref
= InterlockedDecrement(&This
->ref
);
447 TRACE("(%p)->(%d)\n", This
, ref
);
452 if (This
->cmap
.context
)
453 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cmap
.context
);
454 if (This
->vdmx
.context
)
455 IDWriteFontFace3_ReleaseFontTable(iface
, This
->vdmx
.context
);
456 if (This
->gasp
.context
)
457 IDWriteFontFace3_ReleaseFontTable(iface
, This
->gasp
.context
);
458 if (This
->cpal
.context
)
459 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cpal
.context
);
460 if (This
->colr
.context
)
461 IDWriteFontFace3_ReleaseFontTable(iface
, This
->colr
.context
);
462 for (i
= 0; i
< This
->file_count
; i
++) {
463 if (This
->streams
[i
])
464 IDWriteFontFileStream_Release(This
->streams
[i
]);
466 IDWriteFontFile_Release(This
->files
[i
]);
468 heap_free(This
->streams
);
469 heap_free(This
->files
);
471 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
472 heap_free(This
->glyphs
[i
]);
474 freetype_notify_cacheremove(iface
);
481 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace3
*iface
)
483 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
484 TRACE("(%p)\n", This
);
488 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace3
*iface
, UINT32
*number_of_files
,
489 IDWriteFontFile
**fontfiles
)
491 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
494 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
495 if (fontfiles
== NULL
)
497 *number_of_files
= This
->file_count
;
500 if (*number_of_files
< This
->file_count
)
503 for (i
= 0; i
< This
->file_count
; i
++)
505 IDWriteFontFile_AddRef(This
->files
[i
]);
506 fontfiles
[i
] = This
->files
[i
];
512 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace3
*iface
)
514 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
515 TRACE("(%p)\n", This
);
519 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace3
*iface
)
521 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
522 TRACE("(%p)\n", This
);
523 return This
->simulations
;
526 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace3
*iface
)
528 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
529 TRACE("(%p)\n", This
);
530 return This
->is_symbol
;
533 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS
*metrics
)
535 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
536 TRACE("(%p)->(%p)\n", This
, metrics
);
537 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
540 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace3
*iface
)
542 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
543 TRACE("(%p)\n", This
);
544 return freetype_get_glyphcount(iface
);
547 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace3
*iface
,
548 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
550 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
554 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
560 FIXME("sideways metrics are not supported.\n");
562 for (i
= 0; i
< glyph_count
; i
++) {
563 DWRITE_GLYPH_METRICS metrics
;
565 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
567 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
568 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
578 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace3
*iface
, UINT32
const *codepoints
,
579 UINT32 count
, UINT16
*glyph_indices
)
581 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
583 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
589 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
593 freetype_get_glyphs(iface
, This
->charmap
, codepoints
, count
, glyph_indices
);
597 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace3
*iface
, UINT32 table_tag
,
598 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
600 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
602 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
604 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
607 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace3
*iface
, void *table_context
)
609 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
611 TRACE("(%p)->(%p)\n", This
, table_context
);
613 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
616 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace3
*iface
, FLOAT emSize
,
617 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
618 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
620 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
622 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
623 count
, is_sideways
, is_rtl
, sink
);
625 if (!glyphs
|| !sink
)
629 FIXME("sideways mode is not supported.\n");
631 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
634 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
635 FLOAT ppem
, WORD gasp
)
637 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
641 case DWRITE_MEASURING_MODE_NATURAL
:
643 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
644 mode
= DWRITE_RENDERING_MODE_NATURAL
;
646 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
649 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
650 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
652 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
653 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
662 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
663 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
665 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
670 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
673 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
677 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
678 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
681 ppem
= emSize
* ppdip
;
683 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
684 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
688 ptr
= get_fontface_gasp(This
, &size
);
689 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
690 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
694 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
695 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
697 DWRITE_FONT_METRICS1 metrics1
;
698 HRESULT hr
= IDWriteFontFace3_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
699 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
703 static inline int round_metric(FLOAT metric
)
705 return (int)floorf(metric
+ 0.5f
);
708 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT ppdip
,
709 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
710 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
712 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
713 DWRITE_MEASURING_MODE mode
;
718 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
719 glyph_count
, metrics
, is_sideways
);
721 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
722 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
724 size
= emSize
* ppdip
;
725 scale
= size
/ This
->metrics
.designUnitsPerEm
;
726 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
728 for (i
= 0; i
< glyph_count
; i
++) {
729 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
730 DWRITE_GLYPH_METRICS design
;
732 hr
= IDWriteFontFace3_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
736 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
);
737 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
739 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
740 SCALE_METRIC(leftSideBearing
);
741 SCALE_METRIC(rightSideBearing
);
742 SCALE_METRIC(topSideBearing
);
743 SCALE_METRIC(advanceHeight
);
744 SCALE_METRIC(bottomSideBearing
);
745 SCALE_METRIC(verticalOriginY
);
752 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
754 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
755 TRACE("(%p)->(%p)\n", This
, metrics
);
756 *metrics
= This
->metrics
;
759 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
760 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
762 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
763 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
764 UINT16 ascent
, descent
;
767 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
769 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
770 memset(metrics
, 0, sizeof(*metrics
));
774 em_size
*= pixels_per_dip
;
775 if (m
&& m
->m22
!= 0.0f
)
776 em_size
*= fabs(m
->m22
);
778 scale
= em_size
/ design
->designUnitsPerEm
;
779 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
780 ascent
= round_metric(design
->ascent
* scale
);
781 descent
= round_metric(design
->descent
* scale
);
784 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
785 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
786 metrics
->ascent
= round_metric(ascent
/ scale
);
787 metrics
->descent
= round_metric(descent
/ scale
);
789 SCALE_METRIC(lineGap
);
790 SCALE_METRIC(capHeight
);
791 SCALE_METRIC(xHeight
);
792 SCALE_METRIC(underlinePosition
);
793 SCALE_METRIC(underlineThickness
);
794 SCALE_METRIC(strikethroughPosition
);
795 SCALE_METRIC(strikethroughThickness
);
796 SCALE_METRIC(glyphBoxLeft
);
797 SCALE_METRIC(glyphBoxTop
);
798 SCALE_METRIC(glyphBoxRight
);
799 SCALE_METRIC(glyphBoxBottom
);
800 SCALE_METRIC(subscriptPositionX
);
801 SCALE_METRIC(subscriptPositionY
);
802 SCALE_METRIC(subscriptSizeX
);
803 SCALE_METRIC(subscriptSizeY
);
804 SCALE_METRIC(superscriptPositionX
);
805 SCALE_METRIC(superscriptPositionY
);
806 SCALE_METRIC(superscriptSizeX
);
807 SCALE_METRIC(superscriptSizeY
);
809 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
815 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace3
*iface
, DWRITE_CARET_METRICS
*metrics
)
817 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
818 TRACE("(%p)->(%p)\n", This
, metrics
);
819 *metrics
= This
->caret
;
822 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace3
*iface
, UINT32 max_count
,
823 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
825 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
827 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
830 if (max_count
&& !ranges
)
833 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
836 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace3
*iface
)
838 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
839 TRACE("(%p)\n", This
);
840 return This
->is_monospaced
;
843 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3
*iface
,
844 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
846 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
849 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
852 FIXME("sideways mode not supported\n");
854 for (i
= 0; i
< glyph_count
; i
++)
855 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], DWRITE_MEASURING_MODE_NATURAL
);
860 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace3
*iface
,
861 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
862 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
864 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
865 DWRITE_MEASURING_MODE mode
;
868 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
869 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
871 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
872 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
877 if (em_size
== 0.0f
) {
878 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
882 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
883 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
885 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
886 for (i
= 0; i
< glyph_count
; i
++) {
887 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
);
888 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
894 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace3
*iface
, UINT32 count
,
895 const UINT16
*indices
, INT32
*adjustments
)
897 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
900 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
902 if (!(indices
|| adjustments
) || !count
)
905 if (!indices
|| count
== 1) {
906 memset(adjustments
, 0, count
*sizeof(INT32
));
910 if (!This
->has_kerning_pairs
) {
911 memset(adjustments
, 0, count
*sizeof(INT32
));
915 for (i
= 0; i
< count
-1; i
++)
916 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
917 adjustments
[count
-1] = 0;
922 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace3
*iface
)
924 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
925 TRACE("(%p)\n", This
);
926 return This
->has_kerning_pairs
;
929 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
,
930 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
931 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
933 DWRITE_GRID_FIT_MODE gridfitmode
;
934 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
935 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
938 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace3
*iface
, UINT32 glyph_count
,
939 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
941 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
942 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
946 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3
*iface
)
948 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
949 FIXME("(%p): stub\n", This
);
953 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace3
*iface
)
955 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
956 TRACE("(%p)\n", This
);
957 return get_fontface_cpal(This
) && get_fontface_colr(This
);
960 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace3
*iface
)
962 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
963 TRACE("(%p)\n", This
);
964 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
967 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace3
*iface
)
969 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
970 TRACE("(%p)\n", This
);
971 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
974 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace3
*iface
, UINT32 palette_index
,
975 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
977 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
978 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
979 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
982 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
983 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
984 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
985 DWRITE_GRID_FIT_MODE
*gridfitmode
)
987 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
992 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
993 measuringmode
, params
, renderingmode
, gridfitmode
);
996 FIXME("transform not supported %s\n", debugstr_matrix(m
));
999 FIXME("sideways mode not supported\n");
1001 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1003 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1004 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1006 IDWriteRenderingParams2
*params2
;
1009 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1011 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1012 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1013 IDWriteRenderingParams2_Release(params2
);
1016 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1019 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1021 ptr
= get_fontface_gasp(This
, &size
);
1022 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1024 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1025 if (emSize
>= emthreshold
)
1026 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1028 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1031 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1032 if (emSize
>= emthreshold
)
1033 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1034 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1035 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1037 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1043 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace3
*iface
, IDWriteFontFaceReference
**ref
)
1045 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1046 FIXME("(%p)->(%p): stub\n", This
, ref
);
1050 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace3
*iface
, DWRITE_PANOSE
*panose
)
1052 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1053 FIXME("(%p)->(%p): stub\n", This
, panose
);
1056 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace3
*iface
)
1058 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1059 FIXME("(%p): stub\n", This
);
1060 return DWRITE_FONT_WEIGHT_NORMAL
;
1063 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace3
*iface
)
1065 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1066 FIXME("(%p): stub\n", This
);
1067 return DWRITE_FONT_STRETCH_NORMAL
;
1070 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace3
*iface
)
1072 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1073 FIXME("(%p): stub\n", This
);
1074 return DWRITE_FONT_STYLE_NORMAL
;
1077 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1079 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1080 FIXME("(%p)->(%p): stub\n", This
, names
);
1084 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1086 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1087 FIXME("(%p)->(%p): stub\n", This
, names
);
1091 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace3
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1092 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1094 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1095 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1099 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace3
*iface
, UINT32 ch
)
1101 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1105 TRACE("(%p)->(0x%08x)\n", This
, ch
);
1108 hr
= IDWriteFontFace3_GetGlyphIndices(iface
, &ch
, 1, &index
);
1115 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emsize
, FLOAT dpi_x
, FLOAT dpi_y
,
1116 DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1117 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1119 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1120 FIXME("(%p)->(%f %f %f %p %d %u %u %p %p %p): stub\n", This
, emsize
, dpi_x
, dpi_y
, transform
, is_sideways
, threshold
,
1121 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1125 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace3
*iface
, UINT32 ch
)
1127 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1128 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1132 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace3
*iface
, UINT16 glyph
)
1134 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1135 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1139 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace3
*iface
, WCHAR
const *text
,
1140 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1142 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1143 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1147 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace3
*iface
, UINT16
const *glyphs
,
1148 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1150 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1151 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1155 static const IDWriteFontFace3Vtbl dwritefontfacevtbl
= {
1156 dwritefontface_QueryInterface
,
1157 dwritefontface_AddRef
,
1158 dwritefontface_Release
,
1159 dwritefontface_GetType
,
1160 dwritefontface_GetFiles
,
1161 dwritefontface_GetIndex
,
1162 dwritefontface_GetSimulations
,
1163 dwritefontface_IsSymbolFont
,
1164 dwritefontface_GetMetrics
,
1165 dwritefontface_GetGlyphCount
,
1166 dwritefontface_GetDesignGlyphMetrics
,
1167 dwritefontface_GetGlyphIndices
,
1168 dwritefontface_TryGetFontTable
,
1169 dwritefontface_ReleaseFontTable
,
1170 dwritefontface_GetGlyphRunOutline
,
1171 dwritefontface_GetRecommendedRenderingMode
,
1172 dwritefontface_GetGdiCompatibleMetrics
,
1173 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1174 dwritefontface1_GetMetrics
,
1175 dwritefontface1_GetGdiCompatibleMetrics
,
1176 dwritefontface1_GetCaretMetrics
,
1177 dwritefontface1_GetUnicodeRanges
,
1178 dwritefontface1_IsMonospacedFont
,
1179 dwritefontface1_GetDesignGlyphAdvances
,
1180 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1181 dwritefontface1_GetKerningPairAdjustments
,
1182 dwritefontface1_HasKerningPairs
,
1183 dwritefontface1_GetRecommendedRenderingMode
,
1184 dwritefontface1_GetVerticalGlyphVariants
,
1185 dwritefontface1_HasVerticalGlyphVariants
,
1186 dwritefontface2_IsColorFont
,
1187 dwritefontface2_GetColorPaletteCount
,
1188 dwritefontface2_GetPaletteEntryCount
,
1189 dwritefontface2_GetPaletteEntries
,
1190 dwritefontface2_GetRecommendedRenderingMode
,
1191 dwritefontface3_GetFontFaceReference
,
1192 dwritefontface3_GetPanose
,
1193 dwritefontface3_GetWeight
,
1194 dwritefontface3_GetStretch
,
1195 dwritefontface3_GetStyle
,
1196 dwritefontface3_GetFamilyNames
,
1197 dwritefontface3_GetFaceNames
,
1198 dwritefontface3_GetInformationalStrings
,
1199 dwritefontface3_HasCharacter
,
1200 dwritefontface3_GetRecommendedRenderingMode
,
1201 dwritefontface3_IsCharacterLocal
,
1202 dwritefontface3_IsGlyphLocal
,
1203 dwritefontface3_AreCharactersLocal
,
1204 dwritefontface3_AreGlyphsLocal
1207 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace3
**fontface
)
1209 struct dwrite_font_data
*data
= font
->data
;
1210 IDWriteFontFace
*face
;
1215 hr
= IDWriteFactory2_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
1216 data
->face_index
, font
->data
->simulations
, &face
);
1220 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void**)fontface
);
1221 IDWriteFontFace_Release(face
);
1226 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1228 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1230 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1232 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1233 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1234 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1235 IsEqualIID(riid
, &IID_IUnknown
))
1238 IDWriteFont3_AddRef(iface
);
1243 return E_NOINTERFACE
;
1246 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1248 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1249 ULONG ref
= InterlockedIncrement(&This
->ref
);
1250 TRACE("(%p)->(%d)\n", This
, ref
);
1254 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1256 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1257 ULONG ref
= InterlockedDecrement(&This
->ref
);
1259 TRACE("(%p)->(%d)\n", This
, ref
);
1262 IDWriteFontFamily1_Release(This
->family
);
1263 release_font_data(This
->data
);
1270 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1272 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1273 TRACE("(%p)->(%p)\n", This
, family
);
1275 *family
= (IDWriteFontFamily
*)This
->family
;
1276 IDWriteFontFamily_AddRef(*family
);
1280 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1282 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1283 TRACE("(%p)\n", This
);
1284 return This
->data
->weight
;
1287 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1289 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1290 TRACE("(%p)\n", This
);
1291 return This
->data
->stretch
;
1294 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1296 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1297 TRACE("(%p)\n", This
);
1301 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1303 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1304 IDWriteFontFace3
*fontface
;
1307 TRACE("(%p)\n", This
);
1309 hr
= get_fontface_from_font(This
, &fontface
);
1313 return IDWriteFontFace3_IsSymbolFont(fontface
);
1316 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1318 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1319 TRACE("(%p)->(%p)\n", This
, names
);
1320 return clone_localizedstring(This
->data
->names
, names
);
1323 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1324 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1326 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1327 struct dwrite_font_data
*data
= This
->data
;
1330 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1335 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1338 if (!data
->info_strings
[stringid
]) {
1339 IDWriteFontFace3
*fontface
;
1340 const void *table_data
;
1345 hr
= get_fontface_from_font(This
, &fontface
);
1349 table_exists
= FALSE
;
1350 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1351 if (FAILED(hr
) || !table_exists
)
1352 WARN("no NAME table found.\n");
1355 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1356 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1358 IDWriteFontFace3_ReleaseFontTable(fontface
, context
);
1362 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1370 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1372 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1373 TRACE("(%p)\n", This
);
1374 return This
->data
->simulations
;
1377 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1379 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1381 TRACE("(%p)->(%p)\n", This
, metrics
);
1382 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1385 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 value
, BOOL
*exists
)
1387 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1388 IDWriteFontFace3
*fontface
;
1392 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1396 hr
= get_fontface_from_font(This
, &fontface
);
1401 hr
= IDWriteFontFace3_GetGlyphIndices(fontface
, &value
, 1, &index
);
1405 *exists
= index
!= 0;
1409 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**face
)
1411 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1414 TRACE("(%p)->(%p)\n", This
, face
);
1416 hr
= get_fontface_from_font(This
, (IDWriteFontFace3
**)face
);
1418 IDWriteFontFace_AddRef(*face
);
1423 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1425 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1426 TRACE("(%p)->(%p)\n", This
, metrics
);
1427 *metrics
= This
->data
->metrics
;
1430 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1432 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1433 TRACE("(%p)->(%p)\n", This
, panose
);
1434 *panose
= This
->data
->panose
;
1437 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1439 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1440 IDWriteFontFace3
*fontface
;
1443 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1445 hr
= get_fontface_from_font(This
, &fontface
);
1449 return IDWriteFontFace3_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1452 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1454 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1455 IDWriteFontFace3
*fontface
;
1458 TRACE("(%p)\n", This
);
1460 hr
= get_fontface_from_font(This
, &fontface
);
1464 return IDWriteFontFace3_IsMonospacedFont(fontface
);
1467 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1469 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1470 IDWriteFontFace3
*fontface
;
1473 TRACE("(%p)\n", This
);
1475 hr
= get_fontface_from_font(This
, &fontface
);
1479 return IDWriteFontFace3_IsColorFont(fontface
);
1482 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1484 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1485 FIXME("(%p)->(%p): stub\n", This
, fontface
);
1489 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1491 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1492 FIXME("(%p)->(%p): stub\n", This
, font
);
1496 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1498 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1499 FIXME("(%p)->(%p): stub\n", This
, reference
);
1503 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1505 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1506 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1510 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1512 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1513 FIXME("(%p): stub\n", This
);
1514 return DWRITE_LOCALITY_LOCAL
;
1517 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1518 dwritefont_QueryInterface
,
1521 dwritefont_GetFontFamily
,
1522 dwritefont_GetWeight
,
1523 dwritefont_GetStretch
,
1524 dwritefont_GetStyle
,
1525 dwritefont_IsSymbolFont
,
1526 dwritefont_GetFaceNames
,
1527 dwritefont_GetInformationalStrings
,
1528 dwritefont_GetSimulations
,
1529 dwritefont_GetMetrics
,
1530 dwritefont_HasCharacter
,
1531 dwritefont_CreateFontFace
,
1532 dwritefont1_GetMetrics
,
1533 dwritefont1_GetPanose
,
1534 dwritefont1_GetUnicodeRanges
,
1535 dwritefont1_IsMonospacedFont
,
1536 dwritefont2_IsColorFont
,
1537 dwritefont3_CreateFontFace
,
1539 dwritefont3_GetFontFaceReference
,
1540 dwritefont3_HasCharacter
,
1541 dwritefont3_GetLocality
1544 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily1
*family
, IDWriteFont
**font
)
1546 struct dwrite_font
*This
;
1549 This
= heap_alloc(sizeof(struct dwrite_font
));
1550 if (!This
) return E_OUTOFMEMORY
;
1552 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1554 This
->family
= family
;
1555 IDWriteFontFamily1_AddRef(family
);
1556 This
->style
= data
->style
;
1558 InterlockedIncrement(&This
->data
->ref
);
1560 *font
= (IDWriteFont
*)&This
->IDWriteFont3_iface
;
1565 /* IDWriteFontList */
1566 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList
*iface
, REFIID riid
, void **obj
)
1568 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1570 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1572 if (IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1573 IsEqualIID(riid
, &IID_IUnknown
))
1576 IDWriteFontList_AddRef(iface
);
1581 return E_NOINTERFACE
;
1584 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList
*iface
)
1586 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1587 ULONG ref
= InterlockedIncrement(&This
->ref
);
1588 TRACE("(%p)->(%d)\n", This
, ref
);
1592 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList
*iface
)
1594 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1595 ULONG ref
= InterlockedDecrement(&This
->ref
);
1597 TRACE("(%p)->(%d)\n", This
, ref
);
1602 for (i
= 0; i
< This
->font_count
; i
++)
1603 release_font_data(This
->fonts
[i
]);
1604 IDWriteFontFamily1_Release(This
->family
);
1611 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList
*iface
, IDWriteFontCollection
**collection
)
1613 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1614 return IDWriteFontFamily1_GetFontCollection(This
->family
, collection
);
1617 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList
*iface
)
1619 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1620 TRACE("(%p)\n", This
);
1621 return This
->font_count
;
1624 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList
*iface
, UINT32 index
, IDWriteFont
**font
)
1626 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1628 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1632 if (This
->font_count
== 0)
1635 if (index
>= This
->font_count
)
1636 return E_INVALIDARG
;
1638 return create_font(This
->fonts
[index
], This
->family
, font
);
1641 static const IDWriteFontListVtbl dwritefontlistvtbl
= {
1642 dwritefontlist_QueryInterface
,
1643 dwritefontlist_AddRef
,
1644 dwritefontlist_Release
,
1645 dwritefontlist_GetFontCollection
,
1646 dwritefontlist_GetFontCount
,
1647 dwritefontlist_GetFont
1650 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1652 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1654 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1656 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1657 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1658 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1659 IsEqualIID(riid
, &IID_IUnknown
))
1662 IDWriteFontFamily1_AddRef(iface
);
1667 return E_NOINTERFACE
;
1670 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1672 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1673 ULONG ref
= InterlockedIncrement(&This
->ref
);
1674 TRACE("(%p)->(%d)\n", This
, ref
);
1678 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1680 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1681 ULONG ref
= InterlockedDecrement(&This
->ref
);
1683 TRACE("(%p)->(%d)\n", This
, ref
);
1687 IDWriteFontCollection_Release(This
->collection
);
1688 release_fontfamily_data(This
->data
);
1695 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
1697 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1698 TRACE("(%p)->(%p)\n", This
, collection
);
1700 *collection
= This
->collection
;
1701 IDWriteFontCollection_AddRef(This
->collection
);
1705 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
1707 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1708 TRACE("(%p)\n", This
);
1709 return This
->data
->font_count
;
1712 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
1714 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1716 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1720 if (This
->data
->font_count
== 0)
1723 if (index
>= This
->data
->font_count
)
1724 return E_INVALIDARG
;
1726 return create_font(This
->data
->fonts
[index
], iface
, font
);
1729 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
1731 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1732 return clone_localizedstring(This
->data
->familyname
, names
);
1735 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
1736 const struct dwrite_font_propvec
*req
)
1738 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
1739 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
1740 FLOAT cur_req_prod
, next_req_prod
;
1742 if (next_to_req
< cur_to_req
)
1745 if (next_to_req
> cur_to_req
)
1748 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
1749 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
1751 if (next_req_prod
> cur_req_prod
)
1754 if (next_req_prod
< cur_req_prod
)
1757 if (next
->stretch
> cur
->stretch
)
1759 if (next
->stretch
< cur
->stretch
)
1762 if (next
->style
> cur
->style
)
1764 if (next
->style
< cur
->style
)
1767 if (next
->weight
> cur
->weight
)
1769 if (next
->weight
< cur
->weight
)
1772 /* full match, no reason to prefer new variant */
1776 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1777 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1779 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1780 struct dwrite_font_propvec req
;
1781 struct dwrite_font_data
*match
;
1784 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1786 if (This
->data
->font_count
== 0) {
1788 return DWRITE_E_NOFONT
;
1791 init_font_prop_vec(weight
, stretch
, style
, &req
);
1792 match
= This
->data
->fonts
[0];
1794 for (i
= 1; i
< This
->data
->font_count
; i
++) {
1795 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &match
->propvec
, &req
))
1796 match
= This
->data
->fonts
[i
];
1799 return create_font(match
, iface
, font
);
1802 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
1804 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
1806 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1809 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
1811 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1814 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
1816 UINT32 b
= fonts
->font_count
- 1, j
, t
;
1821 for (j
= 0; j
< b
; j
++) {
1822 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
1823 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
1824 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
1825 fonts
->fonts
[j
+1] = s
;
1836 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1837 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
1839 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1840 matching_filter_func func
= NULL
;
1841 struct dwrite_font_propvec req
;
1842 struct dwrite_fontlist
*fonts
;
1845 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
1849 fonts
= heap_alloc(sizeof(*fonts
));
1851 return E_OUTOFMEMORY
;
1853 /* Allocate as many as family has, not all of them will be necessary used. */
1854 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
1855 if (!fonts
->fonts
) {
1857 return E_OUTOFMEMORY
;
1860 fonts
->IDWriteFontList_iface
.lpVtbl
= &dwritefontlistvtbl
;
1862 fonts
->family
= iface
;
1863 IDWriteFontFamily1_AddRef(fonts
->family
);
1864 fonts
->font_count
= 0;
1866 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
1867 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
1868 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
1869 func
= is_font_acceptable_for_normal
;
1871 else /* requested oblique or italic */ {
1872 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
1873 func
= is_font_acceptable_for_oblique_italic
;
1876 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1877 if (!func
|| func(This
->data
->fonts
[i
])) {
1878 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
1879 InterlockedIncrement(&This
->data
->fonts
[i
]->ref
);
1880 fonts
->font_count
++;
1884 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
1885 init_font_prop_vec(weight
, stretch
, style
, &req
);
1886 matchingfonts_sort(fonts
, &req
);
1888 *ret
= &fonts
->IDWriteFontList_iface
;
1892 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
1894 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1896 FIXME("(%p)->(%u): stub\n", This
, index
);
1898 return DWRITE_LOCALITY_LOCAL
;
1901 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1903 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1905 FIXME("(%p)->(%u %p): stub\n", This
, index
, font
);
1910 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
1911 IDWriteFontFaceReference
**ref
)
1913 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1915 FIXME("(%p)->(%u %p): stub\n", This
, index
, ref
);
1920 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
1921 dwritefontfamily_QueryInterface
,
1922 dwritefontfamily_AddRef
,
1923 dwritefontfamily_Release
,
1924 dwritefontfamily_GetFontCollection
,
1925 dwritefontfamily_GetFontCount
,
1926 dwritefontfamily_GetFont
,
1927 dwritefontfamily_GetFamilyNames
,
1928 dwritefontfamily_GetFirstMatchingFont
,
1929 dwritefontfamily_GetMatchingFonts
,
1930 dwritefontfamily1_GetFontLocality
,
1931 dwritefontfamily1_GetFont
,
1932 dwritefontfamily1_GetFontFaceReference
1935 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily1
**family
)
1937 struct dwrite_fontfamily
*This
;
1941 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1942 if (!This
) return E_OUTOFMEMORY
;
1944 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
1946 This
->collection
= collection
;
1947 IDWriteFontCollection_AddRef(collection
);
1949 InterlockedIncrement(&This
->data
->ref
);
1951 *family
= &This
->IDWriteFontFamily1_iface
;
1956 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1959 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1962 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
1964 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1965 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1967 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1968 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
1971 IDWriteFontCollection_AddRef(iface
);
1977 if (This
->is_system
&& IsEqualIID(riid
, &IID_issystemcollection
))
1980 return E_NOINTERFACE
;
1983 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection
*iface
)
1985 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1986 ULONG ref
= InterlockedIncrement(&This
->ref
);
1987 TRACE("(%p)->(%d)\n", This
, ref
);
1991 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection
*iface
)
1994 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1995 ULONG ref
= InterlockedDecrement(&This
->ref
);
1996 TRACE("(%p)->(%d)\n", This
, ref
);
1999 for (i
= 0; i
< This
->family_count
; i
++)
2000 release_fontfamily_data(This
->family_data
[i
]);
2001 heap_free(This
->family_data
);
2008 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
2010 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
2011 TRACE("(%p)\n", This
);
2012 return This
->family_count
;
2015 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2017 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
2019 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2021 if (index
>= This
->family_count
) {
2026 return create_fontfamily(This
->family_data
[index
], iface
, (IDWriteFontFamily1
**)family
);
2029 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2033 for (i
= 0; i
< collection
->family_count
; i
++) {
2034 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2035 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2038 for (j
= 0; j
< count
; j
++) {
2040 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2041 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2049 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2051 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
2052 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2053 *index
= collection_find_family(This
, name
);
2054 *exists
= *index
!= ~0u;
2058 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2060 UINT32 left_key_size
, right_key_size
;
2061 const void *left_key
, *right_key
;
2067 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2071 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2075 if (left_key_size
!= right_key_size
)
2078 return !memcmp(left_key
, right_key
, left_key_size
);
2081 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2083 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
2084 struct dwrite_fontfamily_data
*found_family
= NULL
;
2085 struct dwrite_font_data
*found_font
= NULL
;
2086 IDWriteFontFamily1
*family
;
2087 UINT32 i
, j
, face_index
;
2088 IDWriteFontFile
*file
;
2091 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2096 return E_INVALIDARG
;
2099 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2102 face_index
= IDWriteFontFace_GetIndex(face
);
2104 for (i
= 0; i
< This
->family_count
; i
++) {
2105 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2106 for (j
= 0; j
< family_data
->font_count
; j
++) {
2107 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2109 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2110 found_font
= font_data
;
2111 found_family
= family_data
;
2118 return DWRITE_E_NOFONT
;
2120 hr
= create_fontfamily(found_family
, iface
, &family
);
2124 hr
= create_font(found_font
, family
, font
);
2125 IDWriteFontFamily1_Release(family
);
2129 static const IDWriteFontCollectionVtbl fontcollectionvtbl
= {
2130 dwritefontcollection_QueryInterface
,
2131 dwritefontcollection_AddRef
,
2132 dwritefontcollection_Release
,
2133 dwritefontcollection_GetFontFamilyCount
,
2134 dwritefontcollection_GetFontFamily
,
2135 dwritefontcollection_FindFamilyName
,
2136 dwritefontcollection_GetFontFromFontFace
2139 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2141 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2142 struct dwrite_font_data
**new_list
;
2145 new_alloc
= family_data
->font_alloc
* 2;
2146 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2148 return E_OUTOFMEMORY
;
2149 family_data
->fonts
= new_list
;
2150 family_data
->font_alloc
= new_alloc
;
2153 family_data
->fonts
[family_data
->font_count
] = font_data
;
2154 family_data
->font_count
++;
2155 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2156 family_data
->has_normal_face
= 1;
2157 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2158 family_data
->has_oblique_face
= 1;
2160 family_data
->has_italic_face
= 1;
2164 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2166 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2167 struct dwrite_fontfamily_data
**new_list
;
2170 new_alloc
= collection
->family_alloc
* 2;
2171 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2173 return E_OUTOFMEMORY
;
2175 collection
->family_alloc
= new_alloc
;
2176 collection
->family_data
= new_list
;
2179 collection
->family_data
[collection
->family_count
] = family
;
2180 collection
->family_count
++;
2185 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2187 collection
->IDWriteFontCollection_iface
.lpVtbl
= &fontcollectionvtbl
;
2188 collection
->ref
= 1;
2189 collection
->family_count
= 0;
2190 collection
->family_alloc
= is_system
? 30 : 5;
2191 collection
->is_system
= is_system
;
2193 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2194 if (!collection
->family_data
)
2195 return E_OUTOFMEMORY
;
2200 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2202 IDWriteFontFileLoader
*loader
;
2209 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2213 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2217 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2218 IDWriteFontFileLoader_Release(loader
);
2225 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2227 BOOL exists
= FALSE
;
2232 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2233 if (FAILED(hr
) || !exists
)
2236 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2239 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2243 while (isspaceW(*in
))
2247 if (!(len
= strlenW(in
)))
2250 while (isspaceW(in
[len
-1]))
2253 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2262 INT len
; /* token length */
2263 INT fulllen
; /* full length including following separators */
2266 static inline BOOL
is_name_separator_char(WCHAR ch
)
2268 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2271 struct name_pattern
{
2272 const WCHAR
*part1
; /* NULL indicates end of list */
2273 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2276 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2278 const struct name_pattern
*pattern
;
2279 struct name_token
*token
;
2282 while ((pattern
= &patterns
[i
++])->part1
) {
2283 int len_part1
= strlenW(pattern
->part1
);
2284 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2286 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2287 if (len_part2
== 0) {
2288 /* simple case with single part pattern */
2289 if (token
->len
!= len_part1
)
2292 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2293 if (match
) *match
= *token
;
2294 list_remove(&token
->entry
);
2300 struct name_token
*next_token
;
2301 struct list
*next_entry
;
2303 /* pattern parts are stored in reading order, tokens list is reversed */
2304 if (token
->len
< len_part2
)
2307 /* it's possible to have combined string as a token, like ExtraCondensed */
2308 if (token
->len
== len_part1
+ len_part2
) {
2309 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2312 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2315 /* combined string match */
2316 if (match
) *match
= *token
;
2317 list_remove(&token
->entry
);
2322 /* now it's only possible to have two tokens matched to respective pattern parts */
2323 if (token
->len
!= len_part2
)
2326 next_entry
= list_next(tokens
, &token
->entry
);
2328 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2329 if (next_token
->len
!= len_part1
)
2332 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2335 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2338 /* both parts matched, remove tokens */
2340 match
->ptr
= next_token
->ptr
;
2341 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2343 list_remove(&token
->entry
);
2344 list_remove(&next_token
->entry
);
2345 heap_free(next_token
);
2360 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2362 static const WCHAR itaW
[] = {'i','t','a',0};
2363 static const WCHAR italW
[] = {'i','t','a','l',0};
2364 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2365 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2367 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2368 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2369 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2370 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2372 static const struct name_pattern italic_patterns
[] = {
2381 static const struct name_pattern oblique_patterns
[] = {
2390 /* italic patterns first */
2391 if (match_pattern_list(tokens
, italic_patterns
, match
))
2392 return DWRITE_FONT_STYLE_ITALIC
;
2394 /* oblique patterns */
2395 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2396 return DWRITE_FONT_STYLE_OBLIQUE
;
2401 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2402 struct name_token
*match
)
2404 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2405 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2406 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2407 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2408 static const WCHAR wideW
[] = {'w','i','d','e',0};
2409 static const WCHAR condW
[] = {'c','o','n','d',0};
2411 static const struct name_pattern ultracondensed_patterns
[] = {
2412 { extraW
, compressedW
},
2413 { extW
, compressedW
},
2414 { ultraW
, compressedW
},
2415 { ultraW
, condensedW
},
2420 static const struct name_pattern extracondensed_patterns
[] = {
2422 { extraW
, condensedW
},
2423 { extW
, condensedW
},
2429 static const struct name_pattern semicondensed_patterns
[] = {
2432 { semiW
, condensedW
},
2437 static const struct name_pattern semiexpanded_patterns
[] = {
2439 { semiW
, expandedW
},
2440 { semiW
, extendedW
},
2444 static const struct name_pattern extraexpanded_patterns
[] = {
2445 { extraW
, expandedW
},
2446 { extW
, expandedW
},
2447 { extraW
, extendedW
},
2448 { extW
, extendedW
},
2452 static const struct name_pattern ultraexpanded_patterns
[] = {
2453 { ultraW
, expandedW
},
2454 { ultraW
, extendedW
},
2458 static const struct name_pattern condensed_patterns
[] = {
2464 static const struct name_pattern expanded_patterns
[] = {
2470 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2471 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2473 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2474 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2476 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2477 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2479 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2480 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2482 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2483 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2485 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2486 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2488 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2489 return DWRITE_FONT_STRETCH_CONDENSED
;
2491 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2492 return DWRITE_FONT_STRETCH_EXPANDED
;
2497 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2498 struct name_token
*match
)
2500 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2501 static const WCHAR nordW
[] = {'n','o','r','d',0};
2503 static const struct name_pattern thin_patterns
[] = {
2510 static const struct name_pattern extralight_patterns
[] = {
2517 static const struct name_pattern semilight_patterns
[] = {
2522 static const struct name_pattern demibold_patterns
[] = {
2528 static const struct name_pattern extrabold_patterns
[] = {
2535 static const struct name_pattern extrablack_patterns
[] = {
2542 static const struct name_pattern bold_patterns
[] = {
2547 static const struct name_pattern thin2_patterns
[] = {
2552 static const struct name_pattern light_patterns
[] = {
2557 static const struct name_pattern medium_patterns
[] = {
2562 static const struct name_pattern black_patterns
[] = {
2569 static const struct name_pattern demibold2_patterns
[] = {
2574 static const struct name_pattern extrabold2_patterns
[] = {
2579 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2580 matching pattern. */
2582 if (match_pattern_list(tokens
, thin_patterns
, match
))
2583 return DWRITE_FONT_WEIGHT_THIN
;
2585 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2586 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2588 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2589 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2591 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2592 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2594 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2595 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2597 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2598 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2600 if (match_pattern_list(tokens
, bold_patterns
, match
))
2601 return DWRITE_FONT_WEIGHT_BOLD
;
2603 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2604 return DWRITE_FONT_WEIGHT_THIN
;
2606 if (match_pattern_list(tokens
, light_patterns
, match
))
2607 return DWRITE_FONT_WEIGHT_LIGHT
;
2609 if (match_pattern_list(tokens
, medium_patterns
, match
))
2610 return DWRITE_FONT_WEIGHT_MEDIUM
;
2612 if (match_pattern_list(tokens
, black_patterns
, match
))
2613 return DWRITE_FONT_WEIGHT_BLACK
;
2615 if (match_pattern_list(tokens
, black_patterns
, match
))
2616 return DWRITE_FONT_WEIGHT_BLACK
;
2618 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2619 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2621 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2622 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2624 /* FIXME: use abbreviated names to extract weight */
2629 struct knownweight_entry
{
2631 DWRITE_FONT_WEIGHT weight
;
2634 static int compare_knownweights(const void *a
, const void* b
)
2636 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2637 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2640 if (target
> entry
->weight
)
2642 else if (target
< entry
->weight
)
2648 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2650 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2651 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2652 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2653 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2654 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2655 const struct knownweight_entry
*ptr
;
2657 static const struct knownweight_entry knownweights
[] = {
2658 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
2659 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
2660 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
2661 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
2662 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
2663 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
2664 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
2665 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
2666 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
2667 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
2670 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
2671 compare_knownweights
);
2677 strcpyW(nameW
, ptr
->nameW
);
2681 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
2683 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
2684 strW
[name
->len
] = 0;
2687 /* Modifies facenameW string, and returns pointer to regular term that was removed */
2688 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
2690 static const WCHAR bookW
[] = {'B','o','o','k',0};
2691 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
2692 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
2693 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
2694 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
2696 static const WCHAR
*regular_patterns
[] = {
2705 const WCHAR
*regular_ptr
= NULL
, *ptr
;
2709 len
= strlenW(facenameW
);
2711 /* remove rightmost regular variant from face name */
2712 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
2713 int pattern_len
= strlenW(ptr
);
2716 if (pattern_len
> len
)
2719 src
= facenameW
+ len
- pattern_len
;
2720 while (src
>= facenameW
) {
2721 if (!strncmpiW(src
, ptr
, pattern_len
)) {
2722 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
2723 len
= strlenW(facenameW
);
2735 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
2743 struct name_token
*token
= heap_alloc(sizeof(*token
));
2748 while (*ptr
&& !is_name_separator_char(*ptr
)) {
2754 /* skip separators */
2755 while (is_name_separator_char(*ptr
)) {
2760 list_add_head(tokens
, &token
->entry
);
2764 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
2766 struct name_token
*token
, *token2
;
2767 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
2770 list_remove(&token
->entry
);
2772 /* don't include last separator */
2773 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
2774 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
2782 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
2784 struct name_token stretch_name
, weight_name
, style_name
;
2785 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
2786 WCHAR weightW
[32], stretchW
[32], styleW
[32];
2787 const WCHAR
*regular_ptr
= NULL
;
2788 DWRITE_FONT_STRETCH stretch
;
2789 DWRITE_FONT_WEIGHT weight
;
2793 /* remove leading and trailing spaces from family and face name */
2794 trim_spaces(familyW
, familynameW
);
2795 len
= trim_spaces(faceW
, facenameW
);
2797 /* remove rightmost regular variant from face name */
2798 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
2800 /* append face name to family name, FIXME check if face name is a substring of family name */
2802 strcatW(familynameW
, spaceW
);
2803 strcatW(familynameW
, facenameW
);
2806 /* tokenize with " .-_" */
2807 fontname_tokenize(&tokens
, familynameW
);
2809 /* extract and resolve style */
2810 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
2812 /* extract stretch */
2813 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
2815 /* extract weight */
2816 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
2818 /* resolve weight */
2819 if (weight
!= font
->weight
) {
2820 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
2821 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
2822 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
2823 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
2824 !(abs(weight
- font
->weight
) <= 150 &&
2825 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
2826 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
2827 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
2829 font
->weight
= weight
;
2833 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
2834 it's leaning in opposite direction from normal comparing to specified stretch or if specified
2835 stretch itself is normal (extracted stretch is never normal). */
2836 if (stretch
!= font
->stretch
) {
2837 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
2838 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
2839 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
2841 font
->stretch
= stretch
;
2845 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
2847 /* get final combined string from what's left in token list, list is released */
2848 fontname_tokens_to_str(&tokens
, finalW
);
2850 if (!strcmpW(familyW
, finalW
))
2853 /* construct face name */
2854 strcpyW(familyW
, finalW
);
2856 /* resolved weight name */
2857 if (weight_name
.ptr
)
2858 font_name_token_to_str(&weight_name
, weightW
);
2859 /* ignore normal weight */
2860 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
2862 /* for known weight values use appropriate names */
2863 else if (is_known_weight_value(font
->weight
, weightW
)) {
2865 /* use Wnnn format as a fallback in case weight is not one of known values */
2867 static const WCHAR fmtW
[] = {'W','%','d',0};
2868 sprintfW(weightW
, fmtW
, font
->weight
);
2871 /* resolved stretch name */
2872 if (stretch_name
.ptr
)
2873 font_name_token_to_str(&stretch_name
, stretchW
);
2874 /* ignore normal stretch */
2875 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
2877 /* use predefined stretch names */
2879 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2880 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2881 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
2882 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
2883 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
2884 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
2886 static const WCHAR
*stretchnamesW
[] = {
2891 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
2897 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
2900 /* resolved style name */
2902 font_name_token_to_str(&style_name
, styleW
);
2903 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
2905 /* use predefined names */
2907 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
2908 strcpyW(styleW
, italicW
);
2910 strcpyW(styleW
, obliqueW
);
2913 /* use Regular match if it was found initially */
2914 if (!*weightW
&& !*stretchW
&& !*styleW
)
2915 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
2919 strcpyW(faceW
, stretchW
);
2922 strcatW(faceW
, spaceW
);
2923 strcatW(faceW
, weightW
);
2927 strcatW(faceW
, spaceW
);
2928 strcatW(faceW
, styleW
);
2932 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
2936 static HRESULT
init_font_data(IDWriteFactory2
*factory
, IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
, UINT32 face_index
,
2937 IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
2939 struct dwrite_font_props props
;
2940 struct dwrite_font_data
*data
;
2941 IDWriteFontFileStream
*stream
;
2942 WCHAR familyW
[255], faceW
[255];
2946 data
= heap_alloc_zero(sizeof(*data
));
2948 return E_OUTOFMEMORY
;
2950 hr
= get_filestream_from_file(file
, &stream
);
2957 data
->factory
= factory
;
2959 data
->face_index
= face_index
;
2960 data
->face_type
= face_type
;
2961 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
2962 data
->bold_sim_tested
= 0;
2963 data
->oblique_sim_tested
= 0;
2964 IDWriteFontFile_AddRef(file
);
2965 IDWriteFactory2_AddRef(factory
);
2967 opentype_get_font_properties(stream
, face_type
, face_index
, &props
);
2968 opentype_get_font_metrics(stream
, face_type
, face_index
, &data
->metrics
, NULL
);
2969 opentype_get_font_facename(stream
, face_type
, face_index
, &data
->names
);
2971 /* get family name from font file */
2972 hr
= opentype_get_font_familyname(stream
, face_type
, face_index
, family_name
);
2973 IDWriteFontFileStream_Release(stream
);
2975 WARN("unable to get family name from font\n");
2976 release_font_data(data
);
2980 data
->style
= props
.style
;
2981 data
->stretch
= props
.stretch
;
2982 data
->weight
= props
.weight
;
2983 data
->panose
= props
.panose
;
2985 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
2986 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
2987 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
2988 set_en_localizedstring(*family_name
, familyW
);
2989 set_en_localizedstring(data
->names
, faceW
);
2992 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
2998 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
, const WCHAR
*facenameW
,
2999 struct dwrite_font_data
**ret
)
3001 struct dwrite_font_data
*data
;
3004 data
= heap_alloc_zero(sizeof(*data
));
3006 return E_OUTOFMEMORY
;
3010 data
->simulations
|= sim
;
3011 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3012 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3013 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3014 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3015 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3017 IDWriteFactory2_AddRef(data
->factory
);
3018 IDWriteFontFile_AddRef(data
->file
);
3020 create_localizedstrings(&data
->names
);
3021 add_localizedstring(data
->names
, enusW
, facenameW
);
3023 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3029 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3031 struct dwrite_fontfamily_data
*data
;
3033 data
= heap_alloc(sizeof(*data
));
3035 return E_OUTOFMEMORY
;
3038 data
->font_count
= 0;
3039 data
->font_alloc
= 2;
3040 data
->has_normal_face
= 0;
3041 data
->has_oblique_face
= 0;
3042 data
->has_italic_face
= 0;
3044 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3047 return E_OUTOFMEMORY
;
3050 data
->familyname
= familyname
;
3051 IDWriteLocalizedStrings_AddRef(familyname
);
3057 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3059 UINT32 i
, j
, heaviest
;
3061 for (i
= 0; i
< family
->font_count
; i
++) {
3062 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3065 if (family
->fonts
[i
]->bold_sim_tested
)
3068 family
->fonts
[i
]->bold_sim_tested
= 1;
3069 for (j
= i
; j
< family
->font_count
; j
++) {
3070 if (family
->fonts
[j
]->bold_sim_tested
)
3073 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3074 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3075 if (family
->fonts
[j
]->weight
> weight
) {
3076 weight
= family
->fonts
[j
]->weight
;
3079 family
->fonts
[j
]->bold_sim_tested
= 1;
3083 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3084 static const struct name_pattern weightsim_patterns
[] = {
3099 WCHAR facenameW
[255], initialW
[255];
3100 struct dwrite_font_data
*boldface
;
3103 /* add Bold simulation based on heaviest face data */
3105 /* Simulated face name should only contain Bold as weight term,
3106 so remove existing regular and weight terms. */
3107 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3108 facename_remove_regular_term(initialW
, -1);
3110 /* remove current weight pattern */
3111 fontname_tokenize(&tokens
, initialW
);
3112 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3113 fontname_tokens_to_str(&tokens
, facenameW
);
3115 /* Bold suffix for new name */
3117 strcatW(facenameW
, spaceW
);
3118 strcatW(facenameW
, boldW
);
3120 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3121 boldface
->bold_sim_tested
= 1;
3122 fontfamily_add_font(family
, boldface
);
3128 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3132 for (i
= 0; i
< family
->font_count
; i
++) {
3133 UINT32 regular
= ~0u, oblique
= ~0u;
3134 struct dwrite_font_data
*obliqueface
;
3135 WCHAR facenameW
[255];
3137 if (family
->fonts
[i
]->oblique_sim_tested
)
3140 family
->fonts
[i
]->oblique_sim_tested
= 1;
3141 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3143 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3146 /* find regular style with same weight/stretch values */
3147 for (j
= i
; j
< family
->font_count
; j
++) {
3148 if (family
->fonts
[j
]->oblique_sim_tested
)
3151 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3152 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3154 family
->fonts
[j
]->oblique_sim_tested
= 1;
3155 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3158 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3162 if (regular
!= ~0u && oblique
!= ~0u)
3166 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3170 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3174 /* add oblique simulation based on this regular face */
3176 /* remove regular term if any, append 'Oblique' */
3177 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3178 facename_remove_regular_term(facenameW
, -1);
3181 strcatW(facenameW
, spaceW
);
3182 strcatW(facenameW
, obliqueW
);
3184 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3185 obliqueface
->oblique_sim_tested
= 1;
3186 fontfamily_add_font(family
, obliqueface
);
3191 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3192 const WCHAR
*replacement_name
)
3194 UINT32 i
= collection_find_family(collection
, replacement_name
);
3195 struct dwrite_fontfamily_data
*target
;
3196 IDWriteLocalizedStrings
*strings
;
3199 /* replacement does not exist */
3203 hr
= create_localizedstrings(&strings
);
3207 /* add a new family with target name, reuse font data from replacement */
3208 add_localizedstring(strings
, enusW
, target_name
);
3209 hr
= init_fontfamily_data(strings
, &target
);
3211 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3214 for (i
= 0; i
< replacement
->font_count
; i
++)
3215 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3217 fontcollection_add_family(collection
, target
);
3218 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3219 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3221 IDWriteLocalizedStrings_Release(strings
);
3225 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3226 system font collections. */
3227 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3229 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3234 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3237 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3242 max_namelen
++; /* returned value doesn't include room for '\0' */
3243 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3244 data
= heap_alloc(max_datalen
);
3246 datalen
= max_datalen
;
3247 namelen
= max_namelen
;
3248 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3249 if (collection_find_family(collection
, name
) == ~0u) {
3250 if (type
== REG_MULTI_SZ
) {
3251 WCHAR
*replacement
= data
;
3252 while (*replacement
) {
3253 if (fontcollection_add_replacement(collection
, name
, replacement
))
3255 replacement
+= strlenW(replacement
) + 1;
3258 else if (type
== REG_SZ
)
3259 fontcollection_add_replacement(collection
, name
, data
);
3262 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3264 datalen
= max_datalen
;
3265 namelen
= max_namelen
;
3273 HRESULT
create_font_collection(IDWriteFactory2
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
3275 struct fontfile_enum
{
3277 IDWriteFontFile
*file
;
3279 struct fontfile_enum
*fileenum
, *fileenum2
;
3280 struct dwrite_fontcollection
*collection
;
3281 struct list scannedfiles
;
3282 BOOL current
= FALSE
;
3288 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3289 if (!collection
) return E_OUTOFMEMORY
;
3291 hr
= init_font_collection(collection
, is_system
);
3293 heap_free(collection
);
3297 *ret
= &collection
->IDWriteFontCollection_iface
;
3299 TRACE("building font collection:\n");
3301 list_init(&scannedfiles
);
3302 while (hr
== S_OK
) {
3303 DWRITE_FONT_FACE_TYPE face_type
;
3304 DWRITE_FONT_FILE_TYPE file_type
;
3305 BOOL supported
, same
= FALSE
;
3306 IDWriteFontFile
*file
;
3310 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3311 if (FAILED(hr
) || !current
)
3314 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3318 /* check if we've scanned this file already */
3319 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3320 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3325 IDWriteFontFile_Release(file
);
3329 /* failed font files are skipped */
3330 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3331 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3332 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3333 IDWriteFontFile_Release(file
);
3338 /* add to scanned list */
3339 fileenum
= heap_alloc(sizeof(*fileenum
));
3340 fileenum
->file
= file
;
3341 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3343 for (i
= 0; i
< face_count
; i
++) {
3344 IDWriteLocalizedStrings
*family_name
= NULL
;
3345 struct dwrite_font_data
*font_data
;
3349 /* alloc and init new font data structure */
3350 hr
= init_font_data(factory
, file
, face_type
, i
, &family_name
, &font_data
);
3352 /* move to next one */
3357 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3359 index
= collection_find_family(collection
, familyW
);
3361 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3363 struct dwrite_fontfamily_data
*family_data
;
3365 /* create and init new family */
3366 hr
= init_fontfamily_data(family_name
, &family_data
);
3368 /* add font to family, family - to collection */
3369 hr
= fontfamily_add_font(family_data
, font_data
);
3371 hr
= fontcollection_add_family(collection
, family_data
);
3374 release_fontfamily_data(family_data
);
3378 IDWriteLocalizedStrings_Release(family_name
);
3385 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3386 IDWriteFontFile_Release(fileenum
->file
);
3387 list_remove(&fileenum
->entry
);
3388 heap_free(fileenum
);
3391 for (i
= 0; i
< collection
->family_count
; i
++) {
3392 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3393 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3397 fontcollection_add_replacements(collection
);
3402 struct system_fontfile_enumerator
3404 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3407 IDWriteFactory2
*factory
;
3412 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3414 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3417 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3421 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3422 IDWriteFontFileEnumerator_AddRef(iface
);
3427 return E_NOINTERFACE
;
3430 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3432 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3433 return InterlockedIncrement(&enumerator
->ref
);
3436 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3438 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3439 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3442 IDWriteFactory2_Release(enumerator
->factory
);
3443 RegCloseKey(enumerator
->hkey
);
3444 heap_free(enumerator
);
3450 static HRESULT
create_local_file_reference(IDWriteFactory2
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3454 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3455 if (!strchrW(filename
, '\\')) {
3456 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3457 WCHAR fullpathW
[MAX_PATH
];
3459 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3460 strcatW(fullpathW
, fontsW
);
3461 strcatW(fullpathW
, filename
);
3463 hr
= IDWriteFactory2_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3466 hr
= IDWriteFactory2_CreateFontFileReference(factory
, filename
, NULL
, file
);
3471 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3473 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3474 DWORD ret
, type
, val_count
, count
;
3475 WCHAR
*value
, *filename
;
3480 if (enumerator
->index
< 0)
3483 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3484 if (ret
!= ERROR_SUCCESS
)
3488 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3489 filename
= heap_alloc(count
);
3490 if (!value
|| !filename
) {
3492 heap_free(filename
);
3493 return E_OUTOFMEMORY
;
3496 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3499 heap_free(filename
);
3503 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3506 heap_free(filename
);
3510 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3512 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3513 DWORD ret
, max_val_count
;
3517 enumerator
->index
++;
3519 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
3520 if (ret
!= ERROR_SUCCESS
)
3524 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
3525 return E_OUTOFMEMORY
;
3527 /* iterate until we find next string value */
3529 DWORD type
= 0, count
, val_count
;
3530 val_count
= max_val_count
;
3531 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
3533 if (type
== REG_SZ
) {
3537 enumerator
->index
++;
3540 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3545 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3547 systemfontfileenumerator_QueryInterface
,
3548 systemfontfileenumerator_AddRef
,
3549 systemfontfileenumerator_Release
,
3550 systemfontfileenumerator_MoveNext
,
3551 systemfontfileenumerator_GetCurrentFontFile
3554 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory2
*factory
, IDWriteFontFileEnumerator
**ret
)
3556 struct system_fontfile_enumerator
*enumerator
;
3557 static const WCHAR fontslistW
[] = {
3558 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3559 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3560 'F','o','n','t','s',0
3565 enumerator
= heap_alloc(sizeof(*enumerator
));
3567 return E_OUTOFMEMORY
;
3569 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3570 enumerator
->ref
= 1;
3571 enumerator
->factory
= factory
;
3572 enumerator
->index
= -1;
3573 IDWriteFactory2_AddRef(factory
);
3575 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3576 ERR("failed to open fonts list key\n");
3577 IDWriteFactory2_Release(factory
);
3578 heap_free(enumerator
);
3582 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3587 HRESULT
get_system_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
3589 IDWriteFontFileEnumerator
*enumerator
;
3594 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3598 TRACE("building system font collection for factory %p\n", factory
);
3599 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3600 IDWriteFontFileEnumerator_Release(enumerator
);
3604 static HRESULT
eudc_collection_add_family(IDWriteFactory2
*factory
, struct dwrite_fontcollection
*collection
,
3605 const WCHAR
*keynameW
, const WCHAR
*pathW
)
3607 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};
3608 static const WCHAR emptyW
[] = {0};
3609 IDWriteLocalizedStrings
*names
;
3610 DWRITE_FONT_FACE_TYPE face_type
;
3611 DWRITE_FONT_FILE_TYPE file_type
;
3613 UINT32 face_count
, i
;
3614 IDWriteFontFile
*file
;
3616 struct dwrite_fontfamily_data
*family_data
;
3618 /* create font file from this path */
3619 hr
= create_local_file_reference(factory
, pathW
, &file
);
3623 /* failed font files are skipped */
3624 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3625 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3626 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3627 IDWriteFontFile_Release(file
);
3631 /* create and init new family */
3633 /* Family names are added for non-specific locale, represented with empty string.
3634 Default family appears with empty family name. */
3635 create_localizedstrings(&names
);
3636 if (!strcmpiW(keynameW
, defaultfontW
))
3637 add_localizedstring(names
, emptyW
, emptyW
);
3639 add_localizedstring(names
, emptyW
, keynameW
);
3641 hr
= init_fontfamily_data(names
, &family_data
);
3642 IDWriteLocalizedStrings_Release(names
);
3644 IDWriteFontFile_Release(file
);
3648 /* fill with faces */
3649 for (i
= 0; i
< face_count
; i
++) {
3650 struct dwrite_font_data
*font_data
;
3652 /* alloc and init new font data structure */
3653 hr
= init_font_data(factory
, file
, face_type
, i
, &names
, &font_data
);
3657 IDWriteLocalizedStrings_Release(names
);
3659 /* add font to family */
3660 hr
= fontfamily_add_font(family_data
, font_data
);
3662 release_font_data(font_data
);
3665 /* add family to collection */
3666 hr
= fontcollection_add_family(collection
, family_data
);
3668 release_fontfamily_data(family_data
);
3669 IDWriteFontFile_Release(file
);
3674 HRESULT
get_eudc_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**ret
)
3676 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
3677 struct dwrite_fontcollection
*collection
;
3678 static const WCHAR emptyW
[] = {0};
3679 WCHAR eudckeypathW
[16];
3687 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
3691 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3692 if (!collection
) return E_OUTOFMEMORY
;
3694 hr
= init_font_collection(collection
, FALSE
);
3696 heap_free(collection
);
3700 *ret
= &collection
->IDWriteFontCollection_iface
;
3702 /* return empty collection if EUDC fonts are not configured */
3703 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
3704 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
3707 retval
= ERROR_SUCCESS
;
3709 while (retval
!= ERROR_NO_MORE_ITEMS
) {
3710 WCHAR keynameW
[64], pathW
[MAX_PATH
];
3711 DWORD type
, path_len
, name_len
;
3713 path_len
= sizeof(pathW
)/sizeof(*pathW
);
3714 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
3715 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
3716 if (retval
|| type
!= REG_SZ
)
3719 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
3721 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
3723 RegCloseKey(eudckey
);
3725 /* try to add global default if not defined for specific codepage */
3727 hr
= IDWriteFontCollection_FindFamilyName(&collection
->IDWriteFontCollection_iface
, emptyW
,
3729 if (FAILED(hr
) || !exists
) {
3730 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
3731 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
3733 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
3736 /* EUDC collection offers simulated faces too */
3737 for (i
= 0; i
< collection
->family_count
; i
++) {
3738 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3739 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3745 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
3747 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3749 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3751 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
3754 IDWriteFontFile_AddRef(iface
);
3759 return E_NOINTERFACE
;
3762 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
3764 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3765 ULONG ref
= InterlockedIncrement(&This
->ref
);
3766 TRACE("(%p)->(%d)\n", This
, ref
);
3770 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
3772 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3773 ULONG ref
= InterlockedDecrement(&This
->ref
);
3775 TRACE("(%p)->(%d)\n", This
, ref
);
3779 IDWriteFontFileLoader_Release(This
->loader
);
3780 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
3781 heap_free(This
->reference_key
);
3788 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
3790 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3791 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
3792 *fontFileReferenceKey
= This
->reference_key
;
3793 *fontFileReferenceKeySize
= This
->key_size
;
3798 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
3800 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3801 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
3802 *fontFileLoader
= This
->loader
;
3803 IDWriteFontFileLoader_AddRef(This
->loader
);
3808 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
3809 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
3811 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3812 IDWriteFontFileStream
*stream
;
3815 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
3817 *isSupportedFontType
= FALSE
;
3818 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3820 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3823 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
3827 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
3829 /* TODO: Further Analysis */
3830 IDWriteFontFileStream_Release(stream
);
3834 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
3835 dwritefontfile_QueryInterface
,
3836 dwritefontfile_AddRef
,
3837 dwritefontfile_Release
,
3838 dwritefontfile_GetReferenceKey
,
3839 dwritefontfile_GetLoader
,
3840 dwritefontfile_Analyze
,
3843 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
3845 struct dwrite_fontfile
*This
;
3847 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
3848 if (!This
) return E_OUTOFMEMORY
;
3850 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
3852 IDWriteFontFileLoader_AddRef(loader
);
3853 This
->loader
= loader
;
3854 This
->stream
= NULL
;
3855 This
->reference_key
= heap_alloc(key_size
);
3856 memcpy(This
->reference_key
, reference_key
, key_size
);
3857 This
->key_size
= key_size
;
3859 *font_file
= &This
->IDWriteFontFile_iface
;
3864 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3866 IDWriteFontFileLoader
*loader
;
3872 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3876 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3878 IDWriteFontFileLoader_Release(loader
);
3882 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3883 IDWriteFontFileLoader_Release(loader
);
3888 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
3889 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
3891 struct dwrite_fontface
*fontface
;
3897 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
3899 return E_OUTOFMEMORY
;
3901 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
3902 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
3904 if (!fontface
->files
|| !fontface
->streams
) {
3905 heap_free(fontface
->files
);
3906 heap_free(fontface
->streams
);
3907 heap_free(fontface
);
3908 return E_OUTOFMEMORY
;
3911 fontface
->IDWriteFontFace3_iface
.lpVtbl
= &dwritefontfacevtbl
;
3913 fontface
->type
= facetype
;
3914 fontface
->file_count
= files_number
;
3915 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
3916 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
3917 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
3918 memset(&fontface
->cpal
, 0, sizeof(fontface
->cpal
));
3919 memset(&fontface
->colr
, 0, sizeof(fontface
->colr
));
3920 fontface
->cmap
.exists
= TRUE
;
3921 fontface
->vdmx
.exists
= TRUE
;
3922 fontface
->gasp
.exists
= TRUE
;
3923 fontface
->cpal
.exists
= TRUE
;
3924 fontface
->colr
.exists
= TRUE
;
3925 fontface
->index
= index
;
3926 fontface
->simulations
= simulations
;
3927 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
3929 for (i
= 0; i
< fontface
->file_count
; i
++) {
3930 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
3932 IDWriteFontFace3_Release(&fontface
->IDWriteFontFace3_iface
);
3936 fontface
->files
[i
] = font_files
[i
];
3937 IDWriteFontFile_AddRef(font_files
[i
]);
3940 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
3941 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
3942 /* TODO: test what happens if caret is already slanted */
3943 if (fontface
->caret
.slopeRise
== 1) {
3944 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
3945 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
3948 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace3_iface
, &fontface
->is_symbol
);
3949 fontface
->has_kerning_pairs
= freetype_has_kerning_pairs(&fontface
->IDWriteFontFace3_iface
);
3950 fontface
->is_monospaced
= freetype_is_monospaced(&fontface
->IDWriteFontFace3_iface
);
3952 *ret
= &fontface
->IDWriteFontFace3_iface
;
3956 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
3963 struct local_cached_stream
3966 IDWriteFontFileStream
*stream
;
3967 struct local_refkey
*key
;
3971 struct dwrite_localfontfilestream
3973 IDWriteFontFileStream IDWriteFontFileStream_iface
;
3976 struct local_cached_stream
*entry
;
3977 const void *file_ptr
;
3981 struct dwrite_localfontfileloader
{
3982 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
3985 struct list streams
;
3988 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
3990 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
3993 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
3995 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
3998 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4000 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4001 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4002 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
4005 IDWriteFontFileStream_AddRef(iface
);
4010 return E_NOINTERFACE
;
4013 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4015 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4016 ULONG ref
= InterlockedIncrement(&This
->ref
);
4017 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4021 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4023 list_remove(&stream
->entry
);
4024 heap_free(stream
->key
);
4028 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4030 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4031 ULONG ref
= InterlockedDecrement(&This
->ref
);
4033 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4036 UnmapViewOfFile(This
->file_ptr
);
4037 release_cached_stream(This
->entry
);
4044 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4046 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4048 TRACE_(dwrite_file
)("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
4049 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4051 *fragment_context
= NULL
;
4053 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4054 *fragment_start
= NULL
;
4058 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4062 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4064 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4065 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4068 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4070 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4071 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4076 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4078 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4081 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4083 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4084 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4085 *last_writetime
= li
.QuadPart
;
4090 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4092 localfontfilestream_QueryInterface
,
4093 localfontfilestream_AddRef
,
4094 localfontfilestream_Release
,
4095 localfontfilestream_ReadFileFragment
,
4096 localfontfilestream_ReleaseFileFragment
,
4097 localfontfilestream_GetFileSize
,
4098 localfontfilestream_GetLastWriteTime
4101 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4103 struct dwrite_localfontfilestream
*This
;
4107 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4109 return E_OUTOFMEMORY
;
4111 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4114 This
->file_ptr
= file_ptr
;
4116 This
->entry
= entry
;
4118 *ret
= &This
->IDWriteFontFileStream_iface
;
4122 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4124 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4126 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4128 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
4131 IDWriteLocalFontFileLoader_AddRef(iface
);
4136 return E_NOINTERFACE
;
4139 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4141 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4142 ULONG ref
= InterlockedIncrement(&This
->ref
);
4143 TRACE("(%p)->(%d)\n", This
, ref
);
4147 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4149 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4150 ULONG ref
= InterlockedDecrement(&This
->ref
);
4152 TRACE("(%p)->(%d)\n", This
, ref
);
4155 struct local_cached_stream
*stream
, *stream2
;
4157 /* This will detach all entries from cache. Entries are released together with streams,
4158 so stream controls cache entry lifetime. */
4159 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
4160 list_init(&stream
->entry
);
4168 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
4170 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4171 const struct local_refkey
*refkey
= key
;
4172 struct local_cached_stream
*stream
;
4173 IDWriteFontFileStream
*filestream
;
4174 HANDLE file
, mapping
;
4179 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
4180 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4182 /* search cache first */
4183 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4184 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4185 *ret
= stream
->stream
;
4186 IDWriteFontFileStream_AddRef(*ret
);
4193 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4194 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4195 if (file
== INVALID_HANDLE_VALUE
)
4198 GetFileSizeEx(file
, &size
);
4199 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4204 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4205 CloseHandle(mapping
);
4207 stream
= heap_alloc(sizeof(*stream
));
4209 UnmapViewOfFile(file_ptr
);
4210 return E_OUTOFMEMORY
;
4213 stream
->key
= heap_alloc(key_size
);
4215 UnmapViewOfFile(file_ptr
);
4217 return E_OUTOFMEMORY
;
4220 stream
->key_size
= key_size
;
4221 memcpy(stream
->key
, key
, key_size
);
4223 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4225 UnmapViewOfFile(file_ptr
);
4226 heap_free(stream
->key
);
4231 stream
->stream
= filestream
;
4232 list_add_head(&This
->streams
, &stream
->entry
);
4234 *ret
= stream
->stream
;
4239 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4241 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4242 const struct local_refkey
*refkey
= key
;
4244 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4246 *length
= strlenW(refkey
->name
);
4250 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4252 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4253 const struct local_refkey
*refkey
= key
;
4255 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4257 if (length
< strlenW(refkey
->name
))
4258 return E_INVALIDARG
;
4260 strcpyW(path
, refkey
->name
);
4264 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
4266 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4267 const struct local_refkey
*refkey
= key
;
4269 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
4271 *writetime
= refkey
->writetime
;
4275 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4276 localfontfileloader_QueryInterface
,
4277 localfontfileloader_AddRef
,
4278 localfontfileloader_Release
,
4279 localfontfileloader_CreateStreamFromKey
,
4280 localfontfileloader_GetFilePathLengthFromKey
,
4281 localfontfileloader_GetFilePathFromKey
,
4282 localfontfileloader_GetLastWriteTimeFromKey
4285 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
**ret
)
4287 struct dwrite_localfontfileloader
*This
;
4291 This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
4293 return E_OUTOFMEMORY
;
4295 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4297 list_init(&This
->streams
);
4299 *ret
= &This
->IDWriteLocalFontFileLoader_iface
;
4303 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4305 struct local_refkey
*refkey
;
4307 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4310 refkey
= heap_alloc(*size
);
4312 return E_OUTOFMEMORY
;
4315 refkey
->writetime
= *writetime
;
4317 WIN32_FILE_ATTRIBUTE_DATA info
;
4319 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4320 refkey
->writetime
= info
.ftLastWriteTime
;
4322 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4324 strcpyW(refkey
->name
, path
);
4331 /* IDWriteGlyphRunAnalysis */
4332 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4334 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4336 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4338 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4339 IsEqualIID(riid
, &IID_IUnknown
))
4342 IDWriteGlyphRunAnalysis_AddRef(iface
);
4347 return E_NOINTERFACE
;
4350 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4352 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4353 ULONG ref
= InterlockedIncrement(&This
->ref
);
4354 TRACE("(%p)->(%u)\n", This
, ref
);
4358 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4360 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4361 ULONG ref
= InterlockedDecrement(&This
->ref
);
4363 TRACE("(%p)->(%u)\n", This
, ref
);
4366 if (This
->run
.fontFace
)
4367 IDWriteFontFace_Release(This
->run
.fontFace
);
4368 heap_free(This
->glyphs
);
4369 heap_free(This
->advances
);
4370 heap_free(This
->advanceoffsets
);
4371 heap_free(This
->ascenderoffsets
);
4372 heap_free(This
->bitmap
);
4379 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4381 struct dwrite_glyphbitmap glyph_bitmap
;
4382 IDWriteFontFace3
*fontface3
;
4383 D2D_POINT_2F origin
;
4388 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4389 *bounds
= analysis
->bounds
;
4393 if (analysis
->run
.isSideways
)
4394 FIXME("sideways runs are not supported.\n");
4396 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
4398 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4400 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
4401 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
4402 for any non-zero glyph ascender */
4403 origin
.x
= origin
.y
= 0.0f
;
4404 is_rtl
= analysis
->run
.bidiLevel
& 1;
4406 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4407 glyph_bitmap
.fontface
= fontface3
;
4408 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4409 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4410 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4411 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4412 glyph_bitmap
.m
= &analysis
->m
;
4414 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4415 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4416 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4417 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4418 RECT
*bbox
= &glyph_bitmap
.bbox
;
4420 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4421 freetype_get_glyph_bbox(&glyph_bitmap
);
4424 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4426 OffsetRect(bbox
, origin
.x
, origin
.y
);
4429 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4431 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4432 origin
.x
+= advance
->x
;
4433 origin
.y
+= advance
->y
;
4436 IDWriteFontFace3_Release(fontface3
);
4438 /* translate to given run origin */
4439 OffsetRect(&analysis
->bounds
, analysis
->origin
.x
, analysis
->origin
.y
);
4440 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4441 OffsetRect(&analysis
->bounds
, analysis
->m
.dx
, analysis
->m
.dy
);
4443 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4444 *bounds
= analysis
->bounds
;
4447 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4449 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4451 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4453 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4454 memset(bounds
, 0, sizeof(*bounds
));
4455 return E_INVALIDARG
;
4458 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
4459 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
4460 memset(bounds
, 0, sizeof(*bounds
));
4464 glyphrunanalysis_get_texturebounds(This
, bounds
);
4468 static inline int get_dib_stride( int width
, int bpp
)
4470 return ((width
* bpp
+ 31) >> 3) & ~3;
4473 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4475 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4476 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4477 (runbounds
->left
- bounds
->left
) * 3;
4479 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4480 runbounds
->left
- bounds
->left
;
4483 static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
, DWRITE_TEXTURE_TYPE type
)
4485 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4486 struct dwrite_glyphbitmap glyph_bitmap
;
4487 IDWriteFontFace3
*fontface2
;
4488 D2D_POINT_2F origin
;
4494 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface2
);
4496 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4500 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4501 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4503 analysis
->bitmap
= heap_alloc_zero(size
);
4505 origin
.x
= origin
.y
= 0.0f
;
4506 is_rtl
= analysis
->run
.bidiLevel
& 1;
4508 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4509 glyph_bitmap
.fontface
= fontface2
;
4510 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4511 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4512 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4513 glyph_bitmap
.type
= type
;
4514 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4515 glyph_bitmap
.m
= &analysis
->m
;
4516 bbox
= &glyph_bitmap
.bbox
;
4518 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4519 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4520 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4521 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4522 int x
, y
, width
, height
;
4526 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4527 freetype_get_glyph_bbox(&glyph_bitmap
);
4529 if (IsRectEmpty(bbox
)) {
4530 origin
.x
+= advance
->x
;
4531 origin
.y
+= advance
->y
;
4535 width
= bbox
->right
- bbox
->left
;
4536 height
= bbox
->bottom
- bbox
->top
;
4538 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4539 glyph_bitmap
.pitch
= (width
+ 3) / 4 * 4;
4541 glyph_bitmap
.pitch
= ((width
+ 31) >> 5) << 2;
4543 glyph_bitmap
.buf
= src
= heap_alloc_zero(height
* glyph_bitmap
.pitch
);
4544 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4547 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4549 OffsetRect(bbox
, origin
.x
, origin
.y
);
4552 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4554 OffsetRect(bbox
, analysis
->origin
.x
, analysis
->origin
.y
);
4555 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4556 OffsetRect(bbox
, analysis
->m
.dx
, analysis
->m
.dy
);
4558 /* blit to analysis bitmap */
4559 dst
= get_pixel_ptr(analysis
->bitmap
, type
, bbox
, &analysis
->bounds
);
4562 /* convert 1bpp to 8bpp/24bpp */
4563 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4564 for (y
= 0; y
< height
; y
++) {
4565 for (x
= 0; x
< width
; x
++)
4566 if (src
[x
/ 8] & masks
[x
% 8])
4567 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4568 src
+= glyph_bitmap
.pitch
;
4569 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4573 for (y
= 0; y
< height
; y
++) {
4574 for (x
= 0; x
< width
; x
++)
4575 if (src
[x
/ 8] & masks
[x
% 8])
4576 dst
[x
] = DWRITE_ALPHA_MAX
;
4577 src
+= get_dib_stride(width
, 1);
4578 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
4583 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
4584 for (y
= 0; y
< height
; y
++) {
4585 for (x
= 0; x
< width
; x
++)
4586 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
4587 src
+= glyph_bitmap
.pitch
;
4588 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4592 heap_free(glyph_bitmap
.buf
);
4594 origin
.x
+= advance
->x
;
4595 origin
.y
+= advance
->y
;
4598 IDWriteFontFace3_Release(fontface2
);
4600 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
4602 /* we don't need this anymore */
4603 heap_free(analysis
->glyphs
);
4604 heap_free(analysis
->advances
);
4605 heap_free(analysis
->advanceoffsets
);
4606 heap_free(analysis
->ascenderoffsets
);
4607 IDWriteFontFace_Release(analysis
->run
.fontFace
);
4609 analysis
->glyphs
= NULL
;
4610 analysis
->advances
= NULL
;
4611 analysis
->advanceoffsets
= NULL
;
4612 analysis
->ascenderoffsets
= NULL
;
4613 analysis
->run
.glyphIndices
= NULL
;
4614 analysis
->run
.fontFace
= NULL
;
4617 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
4618 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
4620 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4624 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
4626 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
4627 return E_INVALIDARG
;
4629 /* make sure buffer is large enough for requested texture type */
4630 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
4631 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4634 if (size
< required
)
4635 return E_NOT_SUFFICIENT_BUFFER
;
4637 /* validate requested texture type with rendering mode */
4638 switch (This
->rendering_mode
)
4640 case DWRITE_RENDERING_MODE_ALIASED
:
4641 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
4642 return DWRITE_E_UNSUPPORTEDOPERATION
;
4644 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4645 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4646 case DWRITE_RENDERING_MODE_NATURAL
:
4647 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4648 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
4649 return DWRITE_E_UNSUPPORTEDOPERATION
;
4655 memset(bitmap
, 0, size
);
4656 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
4657 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
4658 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
4659 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
4660 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
4661 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
4665 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
))
4666 glyphrunanalysis_render(This
, type
);
4668 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
4669 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
4671 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
4672 memcpy(dst
, src
, draw_width
);
4681 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
4682 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
4684 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4686 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
4689 return E_INVALIDARG
;
4691 switch (This
->rendering_mode
)
4693 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4694 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4697 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
4698 *gamma
= (FLOAT
)value
/ 1000.0f
;
4700 *cleartypelevel
= 1.0f
;
4703 case DWRITE_RENDERING_MODE_ALIASED
:
4704 case DWRITE_RENDERING_MODE_NATURAL
:
4705 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4706 *gamma
= IDWriteRenderingParams_GetGamma(params
);
4707 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
4708 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
4717 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
4718 glyphrunanalysis_QueryInterface
,
4719 glyphrunanalysis_AddRef
,
4720 glyphrunanalysis_Release
,
4721 glyphrunanalysis_GetAlphaTextureBounds
,
4722 glyphrunanalysis_CreateAlphaTexture
,
4723 glyphrunanalysis_GetAlphaBlendParams
4726 static inline void init_2d_vec(D2D_POINT_2F
*vec
, FLOAT length
, BOOL is_vertical
)
4738 static inline void transform_2d_vec(D2D_POINT_2F
*vec
, const DWRITE_MATRIX
*m
)
4741 ret
.x
= vec
->x
* m
->m11
+ vec
->y
* m
->m21
;
4742 ret
.y
= vec
->x
* m
->m12
+ vec
->y
* m
->m22
;
4746 HRESULT
create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_GLYPH_RUN
const *run
,
4747 FLOAT ppdip
, const DWRITE_MATRIX
*transform
, DWRITE_GRID_FIT_MODE gridfit_mode
, DWRITE_TEXT_ANTIALIAS_MODE aa_mode
,
4748 FLOAT originX
, FLOAT originY
, IDWriteGlyphRunAnalysis
**ret
)
4750 struct dwrite_glyphrunanalysis
*analysis
;
4756 /* check for valid rendering mode */
4757 if ((UINT32
)rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
4758 return E_INVALIDARG
;
4760 analysis
= heap_alloc(sizeof(*analysis
));
4762 return E_OUTOFMEMORY
;
4764 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
4766 analysis
->rendering_mode
= rendering_mode
;
4767 analysis
->flags
= 0;
4768 analysis
->bitmap
= NULL
;
4769 analysis
->ppdip
= ppdip
;
4770 analysis
->origin
.x
= originX
* ppdip
;
4771 analysis
->origin
.y
= originY
* ppdip
;
4772 SetRectEmpty(&analysis
->bounds
);
4773 analysis
->run
= *run
;
4774 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
4775 analysis
->glyphs
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphIndices
));
4776 analysis
->advances
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advances
));
4777 if (run
->glyphOffsets
) {
4778 analysis
->advanceoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advanceoffsets
));
4779 analysis
->ascenderoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->ascenderoffsets
));
4782 analysis
->advanceoffsets
= NULL
;
4783 analysis
->ascenderoffsets
= NULL
;
4786 if (!analysis
->glyphs
|| !analysis
->advances
|| ((!analysis
->advanceoffsets
|| !analysis
->ascenderoffsets
) && run
->glyphOffsets
)) {
4787 heap_free(analysis
->glyphs
);
4788 heap_free(analysis
->advances
);
4789 heap_free(analysis
->advanceoffsets
);
4790 heap_free(analysis
->ascenderoffsets
);
4792 analysis
->glyphs
= NULL
;
4793 analysis
->advances
= NULL
;
4794 analysis
->advanceoffsets
= NULL
;
4795 analysis
->ascenderoffsets
= NULL
;
4797 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
4798 return E_OUTOFMEMORY
;
4801 /* check if transform is usable */
4802 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
))) {
4803 analysis
->m
= *transform
;
4804 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
4807 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
4809 analysis
->run
.glyphIndices
= analysis
->glyphs
;
4810 analysis
->run
.glyphAdvances
= NULL
;
4811 analysis
->run
.glyphOffsets
= NULL
;
4813 rtl_factor
= run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
4815 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4816 transform_2d_vec(&analysis
->origin
, &analysis
->m
);
4818 memcpy(analysis
->glyphs
, run
->glyphIndices
, run
->glyphCount
*sizeof(*run
->glyphIndices
));
4820 if (run
->glyphAdvances
) {
4821 for (i
= 0; i
< run
->glyphCount
; i
++) {
4822 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* run
->glyphAdvances
[i
] * ppdip
, run
->isSideways
);
4823 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4824 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4828 DWRITE_FONT_METRICS metrics
;
4829 IDWriteFontFace1
*fontface1
;
4831 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
4832 IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4834 for (i
= 0; i
< run
->glyphCount
; i
++) {
4838 switch (measuring_mode
)
4840 case DWRITE_MEASURING_MODE_NATURAL
:
4841 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
4844 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
) * ppdip
,
4847 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
4848 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
4849 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, run
->fontEmSize
, ppdip
, transform
,
4850 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
4852 init_2d_vec(analysis
->advances
+ i
, 0.0f
, FALSE
);
4854 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* floorf(a
* run
->fontEmSize
* ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
),
4861 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4862 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4865 IDWriteFontFace1_Release(fontface1
);
4868 if (run
->glyphOffsets
) {
4869 for (i
= 0; i
< run
->glyphCount
; i
++) {
4870 init_2d_vec(analysis
->advanceoffsets
+ i
, rtl_factor
* run
->glyphOffsets
[i
].advanceOffset
* ppdip
, run
->isSideways
);
4871 /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
4872 init_2d_vec(analysis
->ascenderoffsets
+ i
, -run
->glyphOffsets
[i
].ascenderOffset
* ppdip
, !run
->isSideways
);
4873 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
) {
4874 transform_2d_vec(analysis
->advanceoffsets
+ i
, &analysis
->m
);
4875 transform_2d_vec(analysis
->ascenderoffsets
+ i
, &analysis
->m
);
4880 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
4884 /* IDWriteColorGlyphRunEnumerator */
4885 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
4887 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4889 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4891 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
4892 IsEqualIID(riid
, &IID_IUnknown
))
4895 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
4900 return E_NOINTERFACE
;
4903 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
4905 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4906 ULONG ref
= InterlockedIncrement(&This
->ref
);
4907 TRACE("(%p)->(%u)\n", This
, ref
);
4911 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
4913 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4914 ULONG ref
= InterlockedDecrement(&This
->ref
);
4916 TRACE("(%p)->(%u)\n", This
, ref
);
4919 heap_free(This
->advances
);
4920 heap_free(This
->color_advances
);
4921 heap_free(This
->offsets
);
4922 heap_free(This
->color_offsets
);
4923 heap_free(This
->glyphindices
);
4924 heap_free(This
->glyphs
);
4925 if (This
->colr
.context
)
4926 IDWriteFontFace3_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
4927 IDWriteFontFace3_Release(This
->fontface
);
4934 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
4936 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
4937 FLOAT origin
= 0.0f
;
4943 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
4947 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
4949 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
4950 FLOAT advance_adj
= 0.0f
;
4951 BOOL got_palette_index
;
4954 /* start with regular glyphs */
4955 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
4956 UINT32 first_glyph
= 0;
4958 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
4959 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
4960 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
4961 first_glyph
= min(first_glyph
, g
);
4964 glyphenum
->glyphindices
[g
] = 1;
4965 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
4966 if (glyphenum
->color_offsets
)
4967 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
4970 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
4971 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
4972 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
4973 colorrun
->paletteIndex
= 0xffff;
4974 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
4975 glyphenum
->has_regular_glyphs
= FALSE
;
4979 colorrun
->glyphRun
.glyphCount
= 0;
4980 got_palette_index
= FALSE
;
4984 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
4986 glyphenum
->glyphindices
[g
] = 1;
4988 /* all glyph layers were returned */
4989 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
4990 advance_adj
+= glyphenum
->advances
[g
];
4994 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
4995 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
4996 if (!got_palette_index
) {
4997 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
4998 /* use foreground color or request one from the font */
4999 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5000 if (colorrun
->paletteIndex
!= 0xffff) {
5001 HRESULT hr
= IDWriteFontFace3_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5002 1, &colorrun
->runColor
);
5004 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5005 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5007 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5008 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5009 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5010 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5011 got_palette_index
= TRUE
;
5014 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5015 /* offsets are relative to glyph origin, nothing to fix up */
5016 if (glyphenum
->color_offsets
)
5017 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5018 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5020 glyphenum
->color_advances
[index
-1] += advance_adj
;
5021 colorrun
->glyphRun
.glyphCount
++;
5025 advance_adj
+= glyphenum
->advances
[g
];
5028 /* reset last advance */
5029 if (colorrun
->glyphRun
.glyphCount
)
5030 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5032 return colorrun
->glyphRun
.glyphCount
> 0;
5035 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5037 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5039 TRACE("(%p)->(%p)\n", This
, has_run
);
5043 This
->colorrun
.glyphRun
.glyphCount
= 0;
5044 while (This
->current_layer
< This
->max_layer_num
) {
5045 if (colorglyphenum_build_color_run(This
))
5048 This
->current_layer
++;
5051 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5056 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5058 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5060 TRACE("(%p)->(%p)\n", This
, run
);
5062 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5064 return E_NOT_VALID_STATE
;
5067 *run
= &This
->colorrun
;
5071 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5072 colorglyphenum_QueryInterface
,
5073 colorglyphenum_AddRef
,
5074 colorglyphenum_Release
,
5075 colorglyphenum_MoveNext
,
5076 colorglyphenum_GetCurrentRun
5079 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5080 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5082 struct dwrite_colorglyphenum
*colorglyphenum
;
5083 BOOL colorfont
, has_colored_glyph
;
5084 IDWriteFontFace3
*fontface3
;
5090 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
5092 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
5096 colorfont
= IDWriteFontFace3_IsColorFont(fontface3
) && IDWriteFontFace3_GetColorPaletteCount(fontface3
) > palette
;
5098 hr
= DWRITE_E_NOCOLOR
;
5102 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5103 if (!colorglyphenum
) {
5108 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5109 colorglyphenum
->ref
= 1;
5110 colorglyphenum
->origin_x
= originX
;
5111 colorglyphenum
->origin_y
= originY
;
5112 colorglyphenum
->fontface
= fontface3
;
5113 colorglyphenum
->glyphs
= NULL
;
5114 colorglyphenum
->run
= *run
;
5115 colorglyphenum
->run
.glyphIndices
= NULL
;
5116 colorglyphenum
->run
.glyphAdvances
= NULL
;
5117 colorglyphenum
->run
.glyphOffsets
= NULL
;
5118 colorglyphenum
->palette
= palette
;
5119 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5120 colorglyphenum
->colr
.exists
= TRUE
;
5121 get_fontface_table(fontface3
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5122 colorglyphenum
->current_layer
= 0;
5123 colorglyphenum
->max_layer_num
= 0;
5125 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5127 has_colored_glyph
= FALSE
;
5128 colorglyphenum
->has_regular_glyphs
= FALSE
;
5129 for (i
= 0; i
< run
->glyphCount
; i
++) {
5130 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5131 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5132 has_colored_glyph
= TRUE
;
5134 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5135 colorglyphenum
->has_regular_glyphs
= TRUE
;
5138 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5139 is supposed to proceed normally, like if font had no color info at all. */
5140 if (!has_colored_glyph
) {
5141 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5142 return DWRITE_E_NOCOLOR
;
5145 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5146 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5147 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5148 if (run
->glyphOffsets
) {
5149 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5150 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5151 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5154 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5155 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5156 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5157 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5159 if (run
->glyphAdvances
)
5160 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5162 DWRITE_FONT_METRICS metrics
;
5164 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5165 for (i
= 0; i
< run
->glyphCount
; i
++) {
5169 switch (measuring_mode
)
5171 case DWRITE_MEASURING_MODE_NATURAL
:
5172 hr
= IDWriteFontFace3_GetDesignGlyphAdvances(fontface3
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5175 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5177 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5178 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5179 hr
= IDWriteFontFace3_GetGdiCompatibleGlyphAdvances(fontface3
, run
->fontEmSize
, 1.0f
, transform
,
5180 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5182 colorglyphenum
->advances
[i
] = 0.0f
;
5184 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5192 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5196 IDWriteFontFace3_Release(fontface3
);