4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2016 Nikolay Sivov for CodeWeavers
6 * Copyright 2014 Aric Stewart for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/list.h"
27 #include "dwrite_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
30 WINE_DECLARE_DEBUG_CHANNEL(dwrite_file
);
32 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
33 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
34 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
35 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
36 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
37 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
38 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
39 #define MS_COLR_TAG DWRITE_MAKE_OPENTYPE_TAG('C','O','L','R')
41 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
43 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
44 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
45 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
47 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
48 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
49 static const WCHAR semiW
[] = {'s','e','m','i',0};
50 static const WCHAR extW
[] = {'e','x','t',0};
51 static const WCHAR thinW
[] = {'t','h','i','n',0};
52 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
53 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
54 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
55 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
56 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
57 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
58 static const WCHAR boldW
[] = {'B','o','l','d',0};
59 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
60 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
61 static const WCHAR demiW
[] = {'d','e','m','i',0};
62 static const WCHAR spaceW
[] = {' ',0};
63 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
65 struct dwrite_font_propvec
{
71 struct dwrite_font_data
{
74 DWRITE_FONT_STYLE style
;
75 DWRITE_FONT_STRETCH stretch
;
76 DWRITE_FONT_WEIGHT weight
;
78 struct dwrite_font_propvec propvec
;
80 DWRITE_FONT_METRICS1 metrics
;
81 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
82 IDWriteLocalizedStrings
*names
;
84 /* data needed to create fontface instance */
85 IDWriteFactory3
*factory
;
86 DWRITE_FONT_FACE_TYPE face_type
;
87 IDWriteFontFile
*file
;
94 /* used to mark font as tested when scanning for simulation candidate */
95 BOOL bold_sim_tested
: 1;
96 BOOL oblique_sim_tested
: 1;
99 struct dwrite_fontlist
{
100 IDWriteFontList1 IDWriteFontList1_iface
;
103 IDWriteFontFamily1
*family
;
104 struct dwrite_font_data
**fonts
;
108 struct dwrite_fontfamily_data
{
111 IDWriteLocalizedStrings
*familyname
;
113 struct dwrite_font_data
**fonts
;
116 BOOL has_normal_face
: 1;
117 BOOL has_oblique_face
: 1;
118 BOOL has_italic_face
: 1;
121 struct dwrite_fontcollection
{
122 IDWriteFontCollection1 IDWriteFontCollection1_iface
;
125 struct dwrite_fontfamily_data
**family_data
;
130 struct dwrite_fontfamily
{
131 IDWriteFontFamily1 IDWriteFontFamily1_iface
;
134 struct dwrite_fontfamily_data
*data
;
136 IDWriteFontCollection1
*collection
;
140 IDWriteFont3 IDWriteFont3_iface
;
143 IDWriteFontFamily1
*family
;
145 DWRITE_FONT_STYLE style
;
146 struct dwrite_font_data
*data
;
149 struct dwrite_fonttable
{
156 enum runanalysis_flags
{
157 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
158 RUNANALYSIS_BITMAP_READY
= 1 << 1,
159 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
162 struct dwrite_glyphrunanalysis
{
163 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
166 DWRITE_RENDERING_MODE rendering_mode
;
167 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
172 D2D_POINT_2F
*advances
;
173 D2D_POINT_2F
*advanceoffsets
;
174 D2D_POINT_2F
*ascenderoffsets
;
181 struct dwrite_colorglyphenum
{
182 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
185 FLOAT origin_x
; /* original run origin */
188 IDWriteFontFace3
*fontface
; /* for convenience */
189 DWRITE_COLOR_GLYPH_RUN colorrun
; /* returned with GetCurrentRun() */
190 DWRITE_GLYPH_RUN run
; /* base run */
191 UINT32 palette
; /* palette index to get layer color from */
192 FLOAT
*advances
; /* original or measured advances for base glyphs */
193 FLOAT
*color_advances
; /* returned color run points to this */
194 DWRITE_GLYPH_OFFSET
*offsets
; /* original offsets, or NULL */
195 DWRITE_GLYPH_OFFSET
*color_offsets
; /* returned color run offsets, or NULL */
196 UINT16
*glyphindices
; /* returned color run points to this */
197 struct dwrite_colorglyph
*glyphs
; /* current glyph color info */
198 BOOL has_regular_glyphs
; /* TRUE if there's any glyph without a color */
199 UINT16 current_layer
; /* enumerator position, updated with MoveNext */
200 UINT16 max_layer_num
; /* max number of layers for this run */
201 struct dwrite_fonttable colr
; /* used to access layers */
204 #define GLYPH_BLOCK_SHIFT 8
205 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
206 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
207 #define GLYPH_MAX 65536
209 struct dwrite_fontface
{
210 IDWriteFontFace3 IDWriteFontFace3_iface
;
213 IDWriteFontFileStream
**streams
;
214 IDWriteFontFile
**files
;
219 DWRITE_FONT_FACE_TYPE type
;
220 DWRITE_FONT_METRICS1 metrics
;
221 DWRITE_CARET_METRICS caret
;
224 BOOL has_kerning_pairs
: 1;
225 BOOL is_monospaced
: 1;
227 struct dwrite_fonttable cmap
;
228 struct dwrite_fonttable vdmx
;
229 struct dwrite_fonttable gasp
;
230 struct dwrite_fonttable cpal
;
231 struct dwrite_fonttable colr
;
232 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
235 struct dwrite_fontfile
{
236 IDWriteFontFile IDWriteFontFile_iface
;
239 IDWriteFontFileLoader
*loader
;
242 IDWriteFontFileStream
*stream
;
245 struct dwrite_fontfacereference
{
246 IDWriteFontFaceReference IDWriteFontFaceReference_iface
;
249 IDWriteFontFile
*file
;
252 IDWriteFactory3
*factory
;
255 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace3(IDWriteFontFace3
*iface
)
257 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace3_iface
);
260 static inline struct dwrite_font
*impl_from_IDWriteFont3(IDWriteFont3
*iface
)
262 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont3_iface
);
265 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
267 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
270 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily1(IDWriteFontFamily1
*iface
)
272 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily1_iface
);
275 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection1(IDWriteFontCollection1
*iface
)
277 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection1_iface
);
280 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
282 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
285 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
287 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
290 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList1(IDWriteFontList1
*iface
)
292 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList1_iface
);
295 static inline struct dwrite_fontfacereference
*impl_from_IDWriteFontFaceReference(IDWriteFontFaceReference
*iface
)
297 return CONTAINING_RECORD(iface
, struct dwrite_fontfacereference
, IDWriteFontFaceReference_iface
);
300 static inline const char *debugstr_tag(UINT32 tag
)
302 return debugstr_an((char*)&tag
, 4);
305 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
307 static const DWRITE_GLYPH_METRICS nil
;
308 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
310 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
311 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
315 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
317 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
320 /* start new block */
321 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
323 return E_OUTOFMEMORY
;
326 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
330 static void* get_fontface_table(IDWriteFontFace3
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
334 if (table
->data
|| !table
->exists
)
337 table
->exists
= FALSE
;
338 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, tag
, (const void**)&table
->data
, &table
->size
, &table
->context
,
340 if (FAILED(hr
) || !table
->exists
) {
341 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
348 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
349 struct dwrite_font_propvec
*vec
)
351 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
352 vec
->style
= style
* 7.0f
;
353 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
356 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
358 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
361 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
363 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
366 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
368 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CMAP_TAG
, &fontface
->cmap
);
371 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
373 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_VDMX_TAG
, &fontface
->vdmx
);
376 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
378 void *ptr
= get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_GASP_TAG
, &fontface
->gasp
);
379 *size
= fontface
->gasp
.size
;
383 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
385 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_CPAL_TAG
, &fontface
->cpal
);
388 static inline void* get_fontface_colr(struct dwrite_fontface
*fontface
)
390 return get_fontface_table(&fontface
->IDWriteFontFace3_iface
, MS_COLR_TAG
, &fontface
->colr
);
393 static void release_font_data(struct dwrite_font_data
*data
)
397 if (InterlockedDecrement(&data
->ref
) > 0)
400 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
401 if (data
->info_strings
[i
])
402 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
405 IDWriteLocalizedStrings_Release(data
->names
);
407 IDWriteFontFile_Release(data
->file
);
408 IDWriteFactory3_Release(data
->factory
);
409 heap_free(data
->facename
);
413 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
417 if (InterlockedDecrement(&data
->ref
) > 0)
420 for (i
= 0; i
< data
->font_count
; i
++)
421 release_font_data(data
->fonts
[i
]);
422 heap_free(data
->fonts
);
423 IDWriteLocalizedStrings_Release(data
->familyname
);
427 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace3
*iface
, REFIID riid
, void **obj
)
429 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
431 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
433 if (IsEqualIID(riid
, &IID_IDWriteFontFace3
) ||
434 IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
435 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
436 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
437 IsEqualIID(riid
, &IID_IUnknown
))
440 IDWriteFontFace3_AddRef(iface
);
445 return E_NOINTERFACE
;
448 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace3
*iface
)
450 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
451 ULONG ref
= InterlockedIncrement(&This
->ref
);
452 TRACE("(%p)->(%d)\n", This
, ref
);
456 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace3
*iface
)
458 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
459 ULONG ref
= InterlockedDecrement(&This
->ref
);
461 TRACE("(%p)->(%d)\n", This
, ref
);
466 if (This
->cmap
.context
)
467 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cmap
.context
);
468 if (This
->vdmx
.context
)
469 IDWriteFontFace3_ReleaseFontTable(iface
, This
->vdmx
.context
);
470 if (This
->gasp
.context
)
471 IDWriteFontFace3_ReleaseFontTable(iface
, This
->gasp
.context
);
472 if (This
->cpal
.context
)
473 IDWriteFontFace3_ReleaseFontTable(iface
, This
->cpal
.context
);
474 if (This
->colr
.context
)
475 IDWriteFontFace3_ReleaseFontTable(iface
, This
->colr
.context
);
476 for (i
= 0; i
< This
->file_count
; i
++) {
477 if (This
->streams
[i
])
478 IDWriteFontFileStream_Release(This
->streams
[i
]);
480 IDWriteFontFile_Release(This
->files
[i
]);
482 heap_free(This
->streams
);
483 heap_free(This
->files
);
485 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
486 heap_free(This
->glyphs
[i
]);
488 freetype_notify_cacheremove(iface
);
495 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace3
*iface
)
497 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
498 TRACE("(%p)\n", This
);
502 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace3
*iface
, UINT32
*number_of_files
,
503 IDWriteFontFile
**fontfiles
)
505 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
508 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
509 if (fontfiles
== NULL
)
511 *number_of_files
= This
->file_count
;
514 if (*number_of_files
< This
->file_count
)
517 for (i
= 0; i
< This
->file_count
; i
++)
519 IDWriteFontFile_AddRef(This
->files
[i
]);
520 fontfiles
[i
] = This
->files
[i
];
526 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace3
*iface
)
528 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
529 TRACE("(%p)\n", This
);
533 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace3
*iface
)
535 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
536 TRACE("(%p)\n", This
);
537 return This
->simulations
;
540 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace3
*iface
)
542 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
543 TRACE("(%p)\n", This
);
544 return This
->is_symbol
;
547 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS
*metrics
)
549 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
550 TRACE("(%p)->(%p)\n", This
, metrics
);
551 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
554 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace3
*iface
)
556 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
557 TRACE("(%p)\n", This
);
558 return freetype_get_glyphcount(iface
);
561 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace3
*iface
,
562 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
564 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
568 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
574 FIXME("sideways metrics are not supported.\n");
576 for (i
= 0; i
< glyph_count
; i
++) {
577 DWRITE_GLYPH_METRICS metrics
;
579 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
581 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
582 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
592 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace3
*iface
, UINT32
const *codepoints
,
593 UINT32 count
, UINT16
*glyph_indices
)
595 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
597 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
603 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
607 freetype_get_glyphs(iface
, This
->charmap
, codepoints
, count
, glyph_indices
);
611 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace3
*iface
, UINT32 table_tag
,
612 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
614 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
615 struct file_stream_desc stream_desc
;
617 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
619 stream_desc
.stream
= This
->streams
[0];
620 stream_desc
.face_type
= This
->type
;
621 stream_desc
.face_index
= This
->index
;
622 return opentype_get_font_table(&stream_desc
, table_tag
, table_data
, context
, table_size
, exists
);
625 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace3
*iface
, void *table_context
)
627 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
629 TRACE("(%p)->(%p)\n", This
, table_context
);
631 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
634 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace3
*iface
, FLOAT emSize
,
635 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
636 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
638 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
640 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
641 count
, is_sideways
, is_rtl
, sink
);
643 if (!glyphs
|| !sink
)
647 FIXME("sideways mode is not supported.\n");
649 return freetype_get_glyphrun_outline(iface
, emSize
, glyphs
, advances
, offsets
, count
, is_rtl
, sink
);
652 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
653 FLOAT ppem
, WORD gasp
)
655 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
659 case DWRITE_MEASURING_MODE_NATURAL
:
661 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
662 mode
= DWRITE_RENDERING_MODE_NATURAL
;
664 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
667 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
668 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
670 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
671 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
680 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
681 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
683 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
688 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
691 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
695 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
696 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
699 ppem
= emSize
* ppdip
;
701 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
702 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
706 ptr
= get_fontface_gasp(This
, &size
);
707 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
708 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
712 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
713 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
715 DWRITE_FONT_METRICS1 metrics1
;
716 HRESULT hr
= IDWriteFontFace3_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
717 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
721 static inline int round_metric(FLOAT metric
)
723 return (int)floorf(metric
+ 0.5f
);
726 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace3
*iface
, FLOAT emSize
, FLOAT ppdip
,
727 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
728 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
730 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
731 DWRITE_MEASURING_MODE mode
;
736 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
737 glyph_count
, metrics
, is_sideways
);
739 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
740 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
742 size
= emSize
* ppdip
;
743 scale
= size
/ This
->metrics
.designUnitsPerEm
;
744 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
746 for (i
= 0; i
< glyph_count
; i
++) {
747 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
748 DWRITE_GLYPH_METRICS design
;
750 hr
= IDWriteFontFace3_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
754 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
);
755 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
757 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
758 SCALE_METRIC(leftSideBearing
);
759 SCALE_METRIC(rightSideBearing
);
760 SCALE_METRIC(topSideBearing
);
761 SCALE_METRIC(advanceHeight
);
762 SCALE_METRIC(bottomSideBearing
);
763 SCALE_METRIC(verticalOriginY
);
770 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
772 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
773 TRACE("(%p)->(%p)\n", This
, metrics
);
774 *metrics
= This
->metrics
;
777 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace3
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
778 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
780 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
781 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
782 UINT16 ascent
, descent
;
785 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
787 if (em_size
<= 0.0f
|| pixels_per_dip
<= 0.0f
) {
788 memset(metrics
, 0, sizeof(*metrics
));
792 em_size
*= pixels_per_dip
;
793 if (m
&& m
->m22
!= 0.0f
)
794 em_size
*= fabs(m
->m22
);
796 scale
= em_size
/ design
->designUnitsPerEm
;
797 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
798 ascent
= round_metric(design
->ascent
* scale
);
799 descent
= round_metric(design
->descent
* scale
);
802 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
803 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
804 metrics
->ascent
= round_metric(ascent
/ scale
);
805 metrics
->descent
= round_metric(descent
/ scale
);
807 SCALE_METRIC(lineGap
);
808 SCALE_METRIC(capHeight
);
809 SCALE_METRIC(xHeight
);
810 SCALE_METRIC(underlinePosition
);
811 SCALE_METRIC(underlineThickness
);
812 SCALE_METRIC(strikethroughPosition
);
813 SCALE_METRIC(strikethroughThickness
);
814 SCALE_METRIC(glyphBoxLeft
);
815 SCALE_METRIC(glyphBoxTop
);
816 SCALE_METRIC(glyphBoxRight
);
817 SCALE_METRIC(glyphBoxBottom
);
818 SCALE_METRIC(subscriptPositionX
);
819 SCALE_METRIC(subscriptPositionY
);
820 SCALE_METRIC(subscriptSizeX
);
821 SCALE_METRIC(subscriptSizeY
);
822 SCALE_METRIC(superscriptPositionX
);
823 SCALE_METRIC(superscriptPositionY
);
824 SCALE_METRIC(superscriptSizeX
);
825 SCALE_METRIC(superscriptSizeY
);
827 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
833 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace3
*iface
, DWRITE_CARET_METRICS
*metrics
)
835 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
836 TRACE("(%p)->(%p)\n", This
, metrics
);
837 *metrics
= This
->caret
;
840 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace3
*iface
, UINT32 max_count
,
841 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
843 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
845 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
848 if (max_count
&& !ranges
)
851 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
854 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace3
*iface
)
856 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
857 TRACE("(%p)\n", This
);
858 return This
->is_monospaced
;
861 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace3
*iface
,
862 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
864 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
867 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
870 FIXME("sideways mode not supported\n");
872 for (i
= 0; i
< glyph_count
; i
++)
873 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], DWRITE_MEASURING_MODE_NATURAL
);
878 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace3
*iface
,
879 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
880 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
882 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
883 DWRITE_MEASURING_MODE mode
;
886 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
887 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
889 if (em_size
< 0.0f
|| ppdip
<= 0.0f
) {
890 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
895 if (em_size
== 0.0f
) {
896 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
900 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
901 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
903 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
904 for (i
= 0; i
< glyph_count
; i
++) {
905 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
);
906 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
912 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace3
*iface
, UINT32 count
,
913 const UINT16
*indices
, INT32
*adjustments
)
915 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
918 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
920 if (!(indices
|| adjustments
) || !count
)
923 if (!indices
|| count
== 1) {
924 memset(adjustments
, 0, count
*sizeof(INT32
));
928 if (!This
->has_kerning_pairs
) {
929 memset(adjustments
, 0, count
*sizeof(INT32
));
933 for (i
= 0; i
< count
-1; i
++)
934 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
935 adjustments
[count
-1] = 0;
940 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace3
*iface
)
942 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
943 TRACE("(%p)\n", This
);
944 return This
->has_kerning_pairs
;
947 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
,
948 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
949 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
951 DWRITE_GRID_FIT_MODE gridfitmode
;
952 return IDWriteFontFace2_GetRecommendedRenderingMode((IDWriteFontFace2
*)iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
953 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
956 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace3
*iface
, UINT32 glyph_count
,
957 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
959 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
960 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
964 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace3
*iface
)
966 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
967 FIXME("(%p): stub\n", This
);
971 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace3
*iface
)
973 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
974 TRACE("(%p)\n", This
);
975 return get_fontface_cpal(This
) && get_fontface_colr(This
);
978 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace3
*iface
)
980 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
981 TRACE("(%p)\n", This
);
982 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
985 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace3
*iface
)
987 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
988 TRACE("(%p)\n", This
);
989 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
992 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace3
*iface
, UINT32 palette_index
,
993 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
995 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
996 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
997 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
1000 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emSize
,
1001 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1002 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1003 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1005 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1010 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1011 measuringmode
, params
, renderingmode
, gridfitmode
);
1014 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1017 FIXME("sideways mode not supported\n");
1019 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1021 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1022 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1024 IDWriteRenderingParams2
*params2
;
1027 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1029 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1030 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1031 IDWriteRenderingParams2_Release(params2
);
1034 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1037 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1039 ptr
= get_fontface_gasp(This
, &size
);
1040 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1042 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1043 if (emSize
>= emthreshold
)
1044 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1046 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1049 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1050 if (emSize
>= emthreshold
)
1051 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1052 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1053 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1055 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1061 static HRESULT WINAPI
dwritefontface3_GetFontFaceReference(IDWriteFontFace3
*iface
, IDWriteFontFaceReference
**ref
)
1063 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1064 FIXME("(%p)->(%p): stub\n", This
, ref
);
1068 static void WINAPI
dwritefontface3_GetPanose(IDWriteFontFace3
*iface
, DWRITE_PANOSE
*panose
)
1070 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1071 FIXME("(%p)->(%p): stub\n", This
, panose
);
1074 static DWRITE_FONT_WEIGHT WINAPI
dwritefontface3_GetWeight(IDWriteFontFace3
*iface
)
1076 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1077 FIXME("(%p): stub\n", This
);
1078 return DWRITE_FONT_WEIGHT_NORMAL
;
1081 static DWRITE_FONT_STRETCH WINAPI
dwritefontface3_GetStretch(IDWriteFontFace3
*iface
)
1083 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1084 FIXME("(%p): stub\n", This
);
1085 return DWRITE_FONT_STRETCH_NORMAL
;
1088 static DWRITE_FONT_STYLE WINAPI
dwritefontface3_GetStyle(IDWriteFontFace3
*iface
)
1090 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1091 FIXME("(%p): stub\n", This
);
1092 return DWRITE_FONT_STYLE_NORMAL
;
1095 static HRESULT WINAPI
dwritefontface3_GetFamilyNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1097 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1098 FIXME("(%p)->(%p): stub\n", This
, names
);
1102 static HRESULT WINAPI
dwritefontface3_GetFaceNames(IDWriteFontFace3
*iface
, IDWriteLocalizedStrings
**names
)
1104 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1105 FIXME("(%p)->(%p): stub\n", This
, names
);
1109 static HRESULT WINAPI
dwritefontface3_GetInformationalStrings(IDWriteFontFace3
*iface
, DWRITE_INFORMATIONAL_STRING_ID stringid
,
1110 IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1112 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1113 FIXME("(%p)->(%u %p %p): stub\n", This
, stringid
, strings
, exists
);
1117 static BOOL WINAPI
dwritefontface3_HasCharacter(IDWriteFontFace3
*iface
, UINT32 ch
)
1119 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1123 TRACE("(%p)->(0x%08x)\n", This
, ch
);
1126 hr
= IDWriteFontFace3_GetGlyphIndices(iface
, &ch
, 1, &index
);
1133 static HRESULT WINAPI
dwritefontface3_GetRecommendedRenderingMode(IDWriteFontFace3
*iface
, FLOAT emsize
, FLOAT dpi_x
, FLOAT dpi_y
,
1134 DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
,
1135 IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE1
*rendering_mode
, DWRITE_GRID_FIT_MODE
*gridfit_mode
)
1137 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1138 FIXME("(%p)->(%f %f %f %p %d %u %u %p %p %p): stub\n", This
, emsize
, dpi_x
, dpi_y
, transform
, is_sideways
, threshold
,
1139 measuring_mode
, params
, rendering_mode
, gridfit_mode
);
1143 static BOOL WINAPI
dwritefontface3_IsCharacterLocal(IDWriteFontFace3
*iface
, UINT32 ch
)
1145 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1146 FIXME("(%p)->(0x%x): stub\n", This
, ch
);
1150 static BOOL WINAPI
dwritefontface3_IsGlyphLocal(IDWriteFontFace3
*iface
, UINT16 glyph
)
1152 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1153 FIXME("(%p)->(%u): stub\n", This
, glyph
);
1157 static HRESULT WINAPI
dwritefontface3_AreCharactersLocal(IDWriteFontFace3
*iface
, WCHAR
const *text
,
1158 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1160 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1161 FIXME("(%p)->(%s:%u %d %p): stub\n", This
, debugstr_wn(text
, count
), count
, enqueue_if_not
, are_local
);
1165 static HRESULT WINAPI
dwritefontface3_AreGlyphsLocal(IDWriteFontFace3
*iface
, UINT16
const *glyphs
,
1166 UINT32 count
, BOOL enqueue_if_not
, BOOL
*are_local
)
1168 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace3(iface
);
1169 FIXME("(%p)->(%p %u %d %p): stub\n", This
, glyphs
, count
, enqueue_if_not
, are_local
);
1173 static const IDWriteFontFace3Vtbl dwritefontfacevtbl
= {
1174 dwritefontface_QueryInterface
,
1175 dwritefontface_AddRef
,
1176 dwritefontface_Release
,
1177 dwritefontface_GetType
,
1178 dwritefontface_GetFiles
,
1179 dwritefontface_GetIndex
,
1180 dwritefontface_GetSimulations
,
1181 dwritefontface_IsSymbolFont
,
1182 dwritefontface_GetMetrics
,
1183 dwritefontface_GetGlyphCount
,
1184 dwritefontface_GetDesignGlyphMetrics
,
1185 dwritefontface_GetGlyphIndices
,
1186 dwritefontface_TryGetFontTable
,
1187 dwritefontface_ReleaseFontTable
,
1188 dwritefontface_GetGlyphRunOutline
,
1189 dwritefontface_GetRecommendedRenderingMode
,
1190 dwritefontface_GetGdiCompatibleMetrics
,
1191 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1192 dwritefontface1_GetMetrics
,
1193 dwritefontface1_GetGdiCompatibleMetrics
,
1194 dwritefontface1_GetCaretMetrics
,
1195 dwritefontface1_GetUnicodeRanges
,
1196 dwritefontface1_IsMonospacedFont
,
1197 dwritefontface1_GetDesignGlyphAdvances
,
1198 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1199 dwritefontface1_GetKerningPairAdjustments
,
1200 dwritefontface1_HasKerningPairs
,
1201 dwritefontface1_GetRecommendedRenderingMode
,
1202 dwritefontface1_GetVerticalGlyphVariants
,
1203 dwritefontface1_HasVerticalGlyphVariants
,
1204 dwritefontface2_IsColorFont
,
1205 dwritefontface2_GetColorPaletteCount
,
1206 dwritefontface2_GetPaletteEntryCount
,
1207 dwritefontface2_GetPaletteEntries
,
1208 dwritefontface2_GetRecommendedRenderingMode
,
1209 dwritefontface3_GetFontFaceReference
,
1210 dwritefontface3_GetPanose
,
1211 dwritefontface3_GetWeight
,
1212 dwritefontface3_GetStretch
,
1213 dwritefontface3_GetStyle
,
1214 dwritefontface3_GetFamilyNames
,
1215 dwritefontface3_GetFaceNames
,
1216 dwritefontface3_GetInformationalStrings
,
1217 dwritefontface3_HasCharacter
,
1218 dwritefontface3_GetRecommendedRenderingMode
,
1219 dwritefontface3_IsCharacterLocal
,
1220 dwritefontface3_IsGlyphLocal
,
1221 dwritefontface3_AreCharactersLocal
,
1222 dwritefontface3_AreGlyphsLocal
1225 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace3
**fontface
)
1227 struct dwrite_font_data
*data
= font
->data
;
1228 IDWriteFontFace
*face
;
1233 hr
= IDWriteFactory3_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
1234 data
->face_index
, font
->data
->simulations
, &face
);
1238 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace3
, (void**)fontface
);
1239 IDWriteFontFace_Release(face
);
1244 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont3
*iface
, REFIID riid
, void **obj
)
1246 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1248 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1250 if (IsEqualIID(riid
, &IID_IDWriteFont3
) ||
1251 IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1252 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1253 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1254 IsEqualIID(riid
, &IID_IUnknown
))
1257 IDWriteFont3_AddRef(iface
);
1262 return E_NOINTERFACE
;
1265 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont3
*iface
)
1267 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1268 ULONG ref
= InterlockedIncrement(&This
->ref
);
1269 TRACE("(%p)->(%d)\n", This
, ref
);
1273 static ULONG WINAPI
dwritefont_Release(IDWriteFont3
*iface
)
1275 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1276 ULONG ref
= InterlockedDecrement(&This
->ref
);
1278 TRACE("(%p)->(%d)\n", This
, ref
);
1281 IDWriteFontFamily1_Release(This
->family
);
1282 release_font_data(This
->data
);
1289 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont3
*iface
, IDWriteFontFamily
**family
)
1291 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1292 TRACE("(%p)->(%p)\n", This
, family
);
1294 *family
= (IDWriteFontFamily
*)This
->family
;
1295 IDWriteFontFamily_AddRef(*family
);
1299 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont3
*iface
)
1301 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1302 TRACE("(%p)\n", This
);
1303 return This
->data
->weight
;
1306 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont3
*iface
)
1308 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1309 TRACE("(%p)\n", This
);
1310 return This
->data
->stretch
;
1313 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont3
*iface
)
1315 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1316 TRACE("(%p)\n", This
);
1320 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont3
*iface
)
1322 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1323 IDWriteFontFace3
*fontface
;
1326 TRACE("(%p)\n", This
);
1328 hr
= get_fontface_from_font(This
, &fontface
);
1332 return IDWriteFontFace3_IsSymbolFont(fontface
);
1335 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont3
*iface
, IDWriteLocalizedStrings
**names
)
1337 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1338 TRACE("(%p)->(%p)\n", This
, names
);
1339 return clone_localizedstring(This
->data
->names
, names
);
1342 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont3
*iface
,
1343 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1345 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1346 struct dwrite_font_data
*data
= This
->data
;
1349 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1354 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1357 if (!data
->info_strings
[stringid
]) {
1358 IDWriteFontFace3
*fontface
;
1359 const void *table_data
;
1364 hr
= get_fontface_from_font(This
, &fontface
);
1368 table_exists
= FALSE
;
1369 hr
= IDWriteFontFace3_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1370 if (FAILED(hr
) || !table_exists
)
1371 WARN("no NAME table found.\n");
1374 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1375 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1377 IDWriteFontFace3_ReleaseFontTable(fontface
, context
);
1381 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1389 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont3
*iface
)
1391 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1392 TRACE("(%p)\n", This
);
1393 return This
->data
->simulations
;
1396 static void WINAPI
dwritefont_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS
*metrics
)
1398 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1400 TRACE("(%p)->(%p)\n", This
, metrics
);
1401 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1404 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont3
*iface
, UINT32 value
, BOOL
*exists
)
1406 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1407 IDWriteFontFace3
*fontface
;
1411 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1415 hr
= get_fontface_from_font(This
, &fontface
);
1420 hr
= IDWriteFontFace3_GetGlyphIndices(fontface
, &value
, 1, &index
);
1424 *exists
= index
!= 0;
1428 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace
**face
)
1430 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1433 TRACE("(%p)->(%p)\n", This
, face
);
1435 hr
= get_fontface_from_font(This
, (IDWriteFontFace3
**)face
);
1437 IDWriteFontFace_AddRef(*face
);
1442 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont3
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1444 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1445 TRACE("(%p)->(%p)\n", This
, metrics
);
1446 *metrics
= This
->data
->metrics
;
1449 static void WINAPI
dwritefont1_GetPanose(IDWriteFont3
*iface
, DWRITE_PANOSE
*panose
)
1451 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1452 TRACE("(%p)->(%p)\n", This
, panose
);
1453 *panose
= This
->data
->panose
;
1456 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont3
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1458 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1459 IDWriteFontFace3
*fontface
;
1462 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1464 hr
= get_fontface_from_font(This
, &fontface
);
1468 return IDWriteFontFace3_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1471 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont3
*iface
)
1473 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1474 IDWriteFontFace3
*fontface
;
1477 TRACE("(%p)\n", This
);
1479 hr
= get_fontface_from_font(This
, &fontface
);
1483 return IDWriteFontFace3_IsMonospacedFont(fontface
);
1486 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont3
*iface
)
1488 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1489 IDWriteFontFace3
*fontface
;
1492 TRACE("(%p)\n", This
);
1494 hr
= get_fontface_from_font(This
, &fontface
);
1498 return IDWriteFontFace3_IsColorFont(fontface
);
1501 static HRESULT WINAPI
dwritefont3_CreateFontFace(IDWriteFont3
*iface
, IDWriteFontFace3
**fontface
)
1503 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1504 FIXME("(%p)->(%p): stub\n", This
, fontface
);
1508 static BOOL WINAPI
dwritefont3_Equals(IDWriteFont3
*iface
, IDWriteFont
*font
)
1510 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1511 FIXME("(%p)->(%p): stub\n", This
, font
);
1515 static HRESULT WINAPI
dwritefont3_GetFontFaceReference(IDWriteFont3
*iface
, IDWriteFontFaceReference
**reference
)
1517 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1519 TRACE("(%p)->(%p)\n", This
, reference
);
1521 return IDWriteFactory3_CreateFontFaceReference_(This
->data
->factory
, This
->data
->file
, This
->data
->face_index
,
1522 This
->data
->simulations
, reference
);
1525 static BOOL WINAPI
dwritefont3_HasCharacter(IDWriteFont3
*iface
, UINT32 ch
)
1527 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1530 TRACE("(%p)->(0x%x)\n", This
, ch
);
1532 IDWriteFont_HasCharacter((IDWriteFont
*)iface
, ch
, &ret
);
1536 static DWRITE_LOCALITY WINAPI
dwritefont3_GetLocality(IDWriteFont3
*iface
)
1538 struct dwrite_font
*This
= impl_from_IDWriteFont3(iface
);
1539 FIXME("(%p): stub\n", This
);
1540 return DWRITE_LOCALITY_LOCAL
;
1543 static const IDWriteFont3Vtbl dwritefontvtbl
= {
1544 dwritefont_QueryInterface
,
1547 dwritefont_GetFontFamily
,
1548 dwritefont_GetWeight
,
1549 dwritefont_GetStretch
,
1550 dwritefont_GetStyle
,
1551 dwritefont_IsSymbolFont
,
1552 dwritefont_GetFaceNames
,
1553 dwritefont_GetInformationalStrings
,
1554 dwritefont_GetSimulations
,
1555 dwritefont_GetMetrics
,
1556 dwritefont_HasCharacter
,
1557 dwritefont_CreateFontFace
,
1558 dwritefont1_GetMetrics
,
1559 dwritefont1_GetPanose
,
1560 dwritefont1_GetUnicodeRanges
,
1561 dwritefont1_IsMonospacedFont
,
1562 dwritefont2_IsColorFont
,
1563 dwritefont3_CreateFontFace
,
1565 dwritefont3_GetFontFaceReference
,
1566 dwritefont3_HasCharacter
,
1567 dwritefont3_GetLocality
1570 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily1
*family
, IDWriteFont3
**font
)
1572 struct dwrite_font
*This
;
1575 This
= heap_alloc(sizeof(struct dwrite_font
));
1576 if (!This
) return E_OUTOFMEMORY
;
1578 This
->IDWriteFont3_iface
.lpVtbl
= &dwritefontvtbl
;
1580 This
->family
= family
;
1581 IDWriteFontFamily1_AddRef(family
);
1582 This
->style
= data
->style
;
1584 InterlockedIncrement(&This
->data
->ref
);
1586 *font
= &This
->IDWriteFont3_iface
;
1591 /* IDWriteFontList1 */
1592 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList1
*iface
, REFIID riid
, void **obj
)
1594 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1596 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1598 if (IsEqualIID(riid
, &IID_IDWriteFontList1
) ||
1599 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1600 IsEqualIID(riid
, &IID_IUnknown
))
1603 IDWriteFontList1_AddRef(iface
);
1608 return E_NOINTERFACE
;
1611 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList1
*iface
)
1613 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1614 ULONG ref
= InterlockedIncrement(&This
->ref
);
1615 TRACE("(%p)->(%d)\n", This
, ref
);
1619 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList1
*iface
)
1621 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1622 ULONG ref
= InterlockedDecrement(&This
->ref
);
1624 TRACE("(%p)->(%d)\n", This
, ref
);
1629 for (i
= 0; i
< This
->font_count
; i
++)
1630 release_font_data(This
->fonts
[i
]);
1631 IDWriteFontFamily1_Release(This
->family
);
1638 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList1
*iface
, IDWriteFontCollection
**collection
)
1640 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1641 return IDWriteFontFamily1_GetFontCollection(This
->family
, collection
);
1644 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList1
*iface
)
1646 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1647 TRACE("(%p)\n", This
);
1648 return This
->font_count
;
1651 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont
**font
)
1653 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1655 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1659 if (This
->font_count
== 0)
1662 if (index
>= This
->font_count
)
1663 return E_INVALIDARG
;
1665 return create_font(This
->fonts
[index
], This
->family
, (IDWriteFont3
**)font
);
1668 static DWRITE_LOCALITY WINAPI
dwritefontlist1_GetFontLocality(IDWriteFontList1
*iface
, UINT32 index
)
1670 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1672 FIXME("(%p)->(%u): stub\n", This
, index
);
1674 return DWRITE_LOCALITY_LOCAL
;
1677 static HRESULT WINAPI
dwritefontlist1_GetFont(IDWriteFontList1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1679 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1681 FIXME("(%p)->(%u %p): stub\n", This
, index
, font
);
1686 static HRESULT WINAPI
dwritefontlist1_GetFontFaceReference(IDWriteFontList1
*iface
, UINT32 index
,
1687 IDWriteFontFaceReference
**reference
)
1689 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList1(iface
);
1691 FIXME("(%p)->(%u %p): stub\n", This
, index
, reference
);
1696 static const IDWriteFontList1Vtbl dwritefontlistvtbl
= {
1697 dwritefontlist_QueryInterface
,
1698 dwritefontlist_AddRef
,
1699 dwritefontlist_Release
,
1700 dwritefontlist_GetFontCollection
,
1701 dwritefontlist_GetFontCount
,
1702 dwritefontlist_GetFont
,
1703 dwritefontlist1_GetFontLocality
,
1704 dwritefontlist1_GetFont
,
1705 dwritefontlist1_GetFontFaceReference
1708 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily1
*iface
, REFIID riid
, void **obj
)
1710 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1712 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1714 if (IsEqualIID(riid
, &IID_IDWriteFontFamily1
) ||
1715 IsEqualIID(riid
, &IID_IDWriteFontFamily
) ||
1716 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1717 IsEqualIID(riid
, &IID_IUnknown
))
1720 IDWriteFontFamily1_AddRef(iface
);
1725 return E_NOINTERFACE
;
1728 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily1
*iface
)
1730 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1731 ULONG ref
= InterlockedIncrement(&This
->ref
);
1732 TRACE("(%p)->(%d)\n", This
, ref
);
1736 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily1
*iface
)
1738 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1739 ULONG ref
= InterlockedDecrement(&This
->ref
);
1741 TRACE("(%p)->(%d)\n", This
, ref
);
1745 IDWriteFontCollection1_Release(This
->collection
);
1746 release_fontfamily_data(This
->data
);
1753 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily1
*iface
, IDWriteFontCollection
**collection
)
1755 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1757 TRACE("(%p)->(%p)\n", This
, collection
);
1759 *collection
= (IDWriteFontCollection
*)This
->collection
;
1760 IDWriteFontCollection_AddRef(*collection
);
1764 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily1
*iface
)
1766 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1767 TRACE("(%p)\n", This
);
1768 return This
->data
->font_count
;
1771 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont
**font
)
1773 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1775 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1779 if (This
->data
->font_count
== 0)
1782 if (index
>= This
->data
->font_count
)
1783 return E_INVALIDARG
;
1785 return create_font(This
->data
->fonts
[index
], iface
, (IDWriteFont3
**)font
);
1788 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily1
*iface
, IDWriteLocalizedStrings
**names
)
1790 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1791 return clone_localizedstring(This
->data
->familyname
, names
);
1794 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
1795 const struct dwrite_font_propvec
*req
)
1797 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
1798 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
1799 FLOAT cur_req_prod
, next_req_prod
;
1801 if (next_to_req
< cur_to_req
)
1804 if (next_to_req
> cur_to_req
)
1807 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
1808 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
1810 if (next_req_prod
> cur_req_prod
)
1813 if (next_req_prod
< cur_req_prod
)
1816 if (next
->stretch
> cur
->stretch
)
1818 if (next
->stretch
< cur
->stretch
)
1821 if (next
->style
> cur
->style
)
1823 if (next
->style
< cur
->style
)
1826 if (next
->weight
> cur
->weight
)
1828 if (next
->weight
< cur
->weight
)
1831 /* full match, no reason to prefer new variant */
1835 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1836 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1838 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1839 struct dwrite_font_propvec req
;
1840 struct dwrite_font_data
*match
;
1843 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1845 if (This
->data
->font_count
== 0) {
1847 return DWRITE_E_NOFONT
;
1850 init_font_prop_vec(weight
, stretch
, style
, &req
);
1851 match
= This
->data
->fonts
[0];
1853 for (i
= 1; i
< This
->data
->font_count
; i
++) {
1854 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &match
->propvec
, &req
))
1855 match
= This
->data
->fonts
[i
];
1858 return create_font(match
, iface
, (IDWriteFont3
**)font
);
1861 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
1863 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
1865 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1868 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
1870 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1873 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
1875 UINT32 b
= fonts
->font_count
- 1, j
, t
;
1880 for (j
= 0; j
< b
; j
++) {
1881 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
1882 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
1883 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
1884 fonts
->fonts
[j
+1] = s
;
1895 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1
*iface
, DWRITE_FONT_WEIGHT weight
,
1896 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
1898 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1899 matching_filter_func func
= NULL
;
1900 struct dwrite_font_propvec req
;
1901 struct dwrite_fontlist
*fonts
;
1904 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
1908 fonts
= heap_alloc(sizeof(*fonts
));
1910 return E_OUTOFMEMORY
;
1912 /* Allocate as many as family has, not all of them will be necessary used. */
1913 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
1914 if (!fonts
->fonts
) {
1916 return E_OUTOFMEMORY
;
1919 fonts
->IDWriteFontList1_iface
.lpVtbl
= &dwritefontlistvtbl
;
1921 fonts
->family
= iface
;
1922 IDWriteFontFamily1_AddRef(fonts
->family
);
1923 fonts
->font_count
= 0;
1925 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
1926 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
1927 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
1928 func
= is_font_acceptable_for_normal
;
1930 else /* requested oblique or italic */ {
1931 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
1932 func
= is_font_acceptable_for_oblique_italic
;
1935 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1936 if (!func
|| func(This
->data
->fonts
[i
])) {
1937 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
1938 InterlockedIncrement(&This
->data
->fonts
[i
]->ref
);
1939 fonts
->font_count
++;
1943 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
1944 init_font_prop_vec(weight
, stretch
, style
, &req
);
1945 matchingfonts_sort(fonts
, &req
);
1947 *ret
= (IDWriteFontList
*)&fonts
->IDWriteFontList1_iface
;
1951 static DWRITE_LOCALITY WINAPI
dwritefontfamily1_GetFontLocality(IDWriteFontFamily1
*iface
, UINT32 index
)
1953 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1955 FIXME("(%p)->(%u): stub\n", This
, index
);
1957 return DWRITE_LOCALITY_LOCAL
;
1960 static HRESULT WINAPI
dwritefontfamily1_GetFont(IDWriteFontFamily1
*iface
, UINT32 index
, IDWriteFont3
**font
)
1962 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1964 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1968 if (This
->data
->font_count
== 0)
1971 if (index
>= This
->data
->font_count
)
1974 return create_font(This
->data
->fonts
[index
], iface
, font
);
1977 static HRESULT WINAPI
dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1
*iface
, UINT32 index
,
1978 IDWriteFontFaceReference
**ref
)
1980 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily1(iface
);
1982 FIXME("(%p)->(%u %p): stub\n", This
, index
, ref
);
1987 static const IDWriteFontFamily1Vtbl fontfamilyvtbl
= {
1988 dwritefontfamily_QueryInterface
,
1989 dwritefontfamily_AddRef
,
1990 dwritefontfamily_Release
,
1991 dwritefontfamily_GetFontCollection
,
1992 dwritefontfamily_GetFontCount
,
1993 dwritefontfamily_GetFont
,
1994 dwritefontfamily_GetFamilyNames
,
1995 dwritefontfamily_GetFirstMatchingFont
,
1996 dwritefontfamily_GetMatchingFonts
,
1997 dwritefontfamily1_GetFontLocality
,
1998 dwritefontfamily1_GetFont
,
1999 dwritefontfamily1_GetFontFaceReference
2002 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection1
*collection
, IDWriteFontFamily1
**family
)
2004 struct dwrite_fontfamily
*This
;
2008 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
2009 if (!This
) return E_OUTOFMEMORY
;
2011 This
->IDWriteFontFamily1_iface
.lpVtbl
= &fontfamilyvtbl
;
2013 This
->collection
= collection
;
2014 IDWriteFontCollection1_AddRef(collection
);
2016 InterlockedIncrement(&This
->data
->ref
);
2018 *family
= &This
->IDWriteFontFamily1_iface
;
2023 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
2026 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
2029 static HRESULT WINAPI
dwritesystemfontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2031 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2032 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2034 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2035 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2036 IsEqualIID(riid
, &IID_IUnknown
))
2039 IDWriteFontCollection1_AddRef(iface
);
2045 if (IsEqualIID(riid
, &IID_issystemcollection
))
2048 return E_NOINTERFACE
;
2051 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection1
*iface
, REFIID riid
, void **obj
)
2053 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2054 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2056 if (IsEqualIID(riid
, &IID_IDWriteFontCollection1
) ||
2057 IsEqualIID(riid
, &IID_IDWriteFontCollection
) ||
2058 IsEqualIID(riid
, &IID_IUnknown
))
2061 IDWriteFontCollection1_AddRef(iface
);
2067 return E_NOINTERFACE
;
2070 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection1
*iface
)
2072 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2073 ULONG ref
= InterlockedIncrement(&This
->ref
);
2074 TRACE("(%p)->(%d)\n", This
, ref
);
2078 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection1
*iface
)
2081 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2082 ULONG ref
= InterlockedDecrement(&This
->ref
);
2083 TRACE("(%p)->(%d)\n", This
, ref
);
2086 for (i
= 0; i
< This
->family_count
; i
++)
2087 release_fontfamily_data(This
->family_data
[i
]);
2088 heap_free(This
->family_data
);
2095 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection1
*iface
)
2097 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2098 TRACE("(%p)\n", This
);
2099 return This
->family_count
;
2102 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
2104 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2106 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2108 if (index
>= This
->family_count
) {
2113 return create_fontfamily(This
->family_data
[index
], iface
, (IDWriteFontFamily1
**)family
);
2116 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
2120 for (i
= 0; i
< collection
->family_count
; i
++) {
2121 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
2122 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
2125 for (j
= 0; j
< count
; j
++) {
2127 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
2128 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
2136 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection1
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
2138 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2139 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
2140 *index
= collection_find_family(This
, name
);
2141 *exists
= *index
!= ~0u;
2145 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
2147 UINT32 left_key_size
, right_key_size
;
2148 const void *left_key
, *right_key
;
2154 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
2158 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
2162 if (left_key_size
!= right_key_size
)
2165 return !memcmp(left_key
, right_key
, left_key_size
);
2168 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection1
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
2170 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2171 struct dwrite_fontfamily_data
*found_family
= NULL
;
2172 struct dwrite_font_data
*found_font
= NULL
;
2173 IDWriteFontFamily1
*family
;
2174 UINT32 i
, j
, face_index
;
2175 IDWriteFontFile
*file
;
2178 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
2183 return E_INVALIDARG
;
2186 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
2189 face_index
= IDWriteFontFace_GetIndex(face
);
2191 for (i
= 0; i
< This
->family_count
; i
++) {
2192 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
2193 for (j
= 0; j
< family_data
->font_count
; j
++) {
2194 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
2196 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
2197 found_font
= font_data
;
2198 found_family
= family_data
;
2205 return DWRITE_E_NOFONT
;
2207 hr
= create_fontfamily(found_family
, iface
, &family
);
2211 hr
= create_font(found_font
, family
, (IDWriteFont3
**)font
);
2212 IDWriteFontFamily1_Release(family
);
2216 static HRESULT WINAPI
dwritefontcollection1_GetFontSet(IDWriteFontCollection1
*iface
, IDWriteFontSet
**fontset
)
2218 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2220 FIXME("(%p)->(%p): stub\n", This
, fontset
);
2225 static HRESULT WINAPI
dwritefontcollection1_GetFontFamily(IDWriteFontCollection1
*iface
, UINT32 index
, IDWriteFontFamily1
**family
)
2227 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection1(iface
);
2229 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
2231 if (index
>= This
->family_count
) {
2236 return create_fontfamily(This
->family_data
[index
], iface
, family
);
2239 static const IDWriteFontCollection1Vtbl fontcollectionvtbl
= {
2240 dwritefontcollection_QueryInterface
,
2241 dwritefontcollection_AddRef
,
2242 dwritefontcollection_Release
,
2243 dwritefontcollection_GetFontFamilyCount
,
2244 dwritefontcollection_GetFontFamily
,
2245 dwritefontcollection_FindFamilyName
,
2246 dwritefontcollection_GetFontFromFontFace
,
2247 dwritefontcollection1_GetFontSet
,
2248 dwritefontcollection1_GetFontFamily
2251 static const IDWriteFontCollection1Vtbl systemfontcollectionvtbl
= {
2252 dwritesystemfontcollection_QueryInterface
,
2253 dwritefontcollection_AddRef
,
2254 dwritefontcollection_Release
,
2255 dwritefontcollection_GetFontFamilyCount
,
2256 dwritefontcollection_GetFontFamily
,
2257 dwritefontcollection_FindFamilyName
,
2258 dwritefontcollection_GetFontFromFontFace
,
2259 dwritefontcollection1_GetFontSet
,
2260 dwritefontcollection1_GetFontFamily
2263 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2265 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2266 struct dwrite_font_data
**new_list
;
2269 new_alloc
= family_data
->font_alloc
* 2;
2270 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2272 return E_OUTOFMEMORY
;
2273 family_data
->fonts
= new_list
;
2274 family_data
->font_alloc
= new_alloc
;
2277 family_data
->fonts
[family_data
->font_count
] = font_data
;
2278 family_data
->font_count
++;
2279 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2280 family_data
->has_normal_face
= 1;
2281 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2282 family_data
->has_oblique_face
= 1;
2284 family_data
->has_italic_face
= 1;
2288 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2290 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2291 struct dwrite_fontfamily_data
**new_list
;
2294 new_alloc
= collection
->family_alloc
* 2;
2295 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2297 return E_OUTOFMEMORY
;
2299 collection
->family_alloc
= new_alloc
;
2300 collection
->family_data
= new_list
;
2303 collection
->family_data
[collection
->family_count
] = family
;
2304 collection
->family_count
++;
2309 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2311 collection
->IDWriteFontCollection1_iface
.lpVtbl
= is_system
? &systemfontcollectionvtbl
: &fontcollectionvtbl
;
2312 collection
->ref
= 1;
2313 collection
->family_count
= 0;
2314 collection
->family_alloc
= is_system
? 30 : 5;
2315 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2316 if (!collection
->family_data
)
2317 return E_OUTOFMEMORY
;
2322 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2324 IDWriteFontFileLoader
*loader
;
2331 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2335 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2339 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2340 IDWriteFontFileLoader_Release(loader
);
2347 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2349 BOOL exists
= FALSE
;
2354 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2355 if (FAILED(hr
) || !exists
)
2358 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2361 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2365 while (isspaceW(*in
))
2369 if (!(len
= strlenW(in
)))
2372 while (isspaceW(in
[len
-1]))
2375 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2384 INT len
; /* token length */
2385 INT fulllen
; /* full length including following separators */
2388 static inline BOOL
is_name_separator_char(WCHAR ch
)
2390 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2393 struct name_pattern
{
2394 const WCHAR
*part1
; /* NULL indicates end of list */
2395 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2398 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2400 const struct name_pattern
*pattern
;
2401 struct name_token
*token
;
2404 while ((pattern
= &patterns
[i
++])->part1
) {
2405 int len_part1
= strlenW(pattern
->part1
);
2406 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2408 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2409 if (len_part2
== 0) {
2410 /* simple case with single part pattern */
2411 if (token
->len
!= len_part1
)
2414 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2415 if (match
) *match
= *token
;
2416 list_remove(&token
->entry
);
2422 struct name_token
*next_token
;
2423 struct list
*next_entry
;
2425 /* pattern parts are stored in reading order, tokens list is reversed */
2426 if (token
->len
< len_part2
)
2429 /* it's possible to have combined string as a token, like ExtraCondensed */
2430 if (token
->len
== len_part1
+ len_part2
) {
2431 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2434 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2437 /* combined string match */
2438 if (match
) *match
= *token
;
2439 list_remove(&token
->entry
);
2444 /* now it's only possible to have two tokens matched to respective pattern parts */
2445 if (token
->len
!= len_part2
)
2448 next_entry
= list_next(tokens
, &token
->entry
);
2450 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2451 if (next_token
->len
!= len_part1
)
2454 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2457 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2460 /* both parts matched, remove tokens */
2462 match
->ptr
= next_token
->ptr
;
2463 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2465 list_remove(&token
->entry
);
2466 list_remove(&next_token
->entry
);
2467 heap_free(next_token
);
2482 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2484 static const WCHAR itaW
[] = {'i','t','a',0};
2485 static const WCHAR italW
[] = {'i','t','a','l',0};
2486 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2487 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2489 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2490 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2491 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2492 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2494 static const struct name_pattern italic_patterns
[] = {
2503 static const struct name_pattern oblique_patterns
[] = {
2512 /* italic patterns first */
2513 if (match_pattern_list(tokens
, italic_patterns
, match
))
2514 return DWRITE_FONT_STYLE_ITALIC
;
2516 /* oblique patterns */
2517 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2518 return DWRITE_FONT_STYLE_OBLIQUE
;
2523 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2524 struct name_token
*match
)
2526 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2527 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2528 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2529 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2530 static const WCHAR wideW
[] = {'w','i','d','e',0};
2531 static const WCHAR condW
[] = {'c','o','n','d',0};
2533 static const struct name_pattern ultracondensed_patterns
[] = {
2534 { extraW
, compressedW
},
2535 { extW
, compressedW
},
2536 { ultraW
, compressedW
},
2537 { ultraW
, condensedW
},
2542 static const struct name_pattern extracondensed_patterns
[] = {
2544 { extraW
, condensedW
},
2545 { extW
, condensedW
},
2551 static const struct name_pattern semicondensed_patterns
[] = {
2554 { semiW
, condensedW
},
2559 static const struct name_pattern semiexpanded_patterns
[] = {
2561 { semiW
, expandedW
},
2562 { semiW
, extendedW
},
2566 static const struct name_pattern extraexpanded_patterns
[] = {
2567 { extraW
, expandedW
},
2568 { extW
, expandedW
},
2569 { extraW
, extendedW
},
2570 { extW
, extendedW
},
2574 static const struct name_pattern ultraexpanded_patterns
[] = {
2575 { ultraW
, expandedW
},
2576 { ultraW
, extendedW
},
2580 static const struct name_pattern condensed_patterns
[] = {
2586 static const struct name_pattern expanded_patterns
[] = {
2592 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2593 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2595 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2596 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2598 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2599 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2601 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2602 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2604 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2605 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2607 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2608 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2610 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2611 return DWRITE_FONT_STRETCH_CONDENSED
;
2613 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2614 return DWRITE_FONT_STRETCH_EXPANDED
;
2619 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2620 struct name_token
*match
)
2622 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2623 static const WCHAR nordW
[] = {'n','o','r','d',0};
2625 static const struct name_pattern thin_patterns
[] = {
2632 static const struct name_pattern extralight_patterns
[] = {
2639 static const struct name_pattern semilight_patterns
[] = {
2644 static const struct name_pattern demibold_patterns
[] = {
2650 static const struct name_pattern extrabold_patterns
[] = {
2657 static const struct name_pattern extrablack_patterns
[] = {
2664 static const struct name_pattern bold_patterns
[] = {
2669 static const struct name_pattern thin2_patterns
[] = {
2674 static const struct name_pattern light_patterns
[] = {
2679 static const struct name_pattern medium_patterns
[] = {
2684 static const struct name_pattern black_patterns
[] = {
2691 static const struct name_pattern demibold2_patterns
[] = {
2696 static const struct name_pattern extrabold2_patterns
[] = {
2701 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2702 matching pattern. */
2704 if (match_pattern_list(tokens
, thin_patterns
, match
))
2705 return DWRITE_FONT_WEIGHT_THIN
;
2707 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2708 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2710 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2711 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2713 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2714 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2716 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2717 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2719 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2720 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2722 if (match_pattern_list(tokens
, bold_patterns
, match
))
2723 return DWRITE_FONT_WEIGHT_BOLD
;
2725 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2726 return DWRITE_FONT_WEIGHT_THIN
;
2728 if (match_pattern_list(tokens
, light_patterns
, match
))
2729 return DWRITE_FONT_WEIGHT_LIGHT
;
2731 if (match_pattern_list(tokens
, medium_patterns
, match
))
2732 return DWRITE_FONT_WEIGHT_MEDIUM
;
2734 if (match_pattern_list(tokens
, black_patterns
, match
))
2735 return DWRITE_FONT_WEIGHT_BLACK
;
2737 if (match_pattern_list(tokens
, black_patterns
, match
))
2738 return DWRITE_FONT_WEIGHT_BLACK
;
2740 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2741 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2743 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2744 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2746 /* FIXME: use abbreviated names to extract weight */
2751 struct knownweight_entry
{
2753 DWRITE_FONT_WEIGHT weight
;
2756 static int compare_knownweights(const void *a
, const void* b
)
2758 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2759 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2762 if (target
> entry
->weight
)
2764 else if (target
< entry
->weight
)
2770 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2772 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2773 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2774 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2775 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2776 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2777 const struct knownweight_entry
*ptr
;
2779 static const struct knownweight_entry knownweights
[] = {
2780 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
2781 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
2782 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
2783 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
2784 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
2785 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
2786 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
2787 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
2788 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
2789 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
2792 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
2793 compare_knownweights
);
2799 strcpyW(nameW
, ptr
->nameW
);
2803 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
2805 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
2806 strW
[name
->len
] = 0;
2809 /* Modifies facenameW string, and returns pointer to regular term that was removed */
2810 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
2812 static const WCHAR bookW
[] = {'B','o','o','k',0};
2813 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
2814 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
2815 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
2816 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
2818 static const WCHAR
*regular_patterns
[] = {
2827 const WCHAR
*regular_ptr
= NULL
, *ptr
;
2831 len
= strlenW(facenameW
);
2833 /* remove rightmost regular variant from face name */
2834 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
2835 int pattern_len
= strlenW(ptr
);
2838 if (pattern_len
> len
)
2841 src
= facenameW
+ len
- pattern_len
;
2842 while (src
>= facenameW
) {
2843 if (!strncmpiW(src
, ptr
, pattern_len
)) {
2844 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
2845 len
= strlenW(facenameW
);
2857 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
2865 struct name_token
*token
= heap_alloc(sizeof(*token
));
2870 while (*ptr
&& !is_name_separator_char(*ptr
)) {
2876 /* skip separators */
2877 while (is_name_separator_char(*ptr
)) {
2882 list_add_head(tokens
, &token
->entry
);
2886 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
2888 struct name_token
*token
, *token2
;
2889 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
2892 list_remove(&token
->entry
);
2894 /* don't include last separator */
2895 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
2896 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
2904 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
2906 struct name_token stretch_name
, weight_name
, style_name
;
2907 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
2908 WCHAR weightW
[32], stretchW
[32], styleW
[32];
2909 const WCHAR
*regular_ptr
= NULL
;
2910 DWRITE_FONT_STRETCH stretch
;
2911 DWRITE_FONT_WEIGHT weight
;
2915 /* remove leading and trailing spaces from family and face name */
2916 trim_spaces(familyW
, familynameW
);
2917 len
= trim_spaces(faceW
, facenameW
);
2919 /* remove rightmost regular variant from face name */
2920 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
2922 /* append face name to family name, FIXME check if face name is a substring of family name */
2924 strcatW(familynameW
, spaceW
);
2925 strcatW(familynameW
, facenameW
);
2928 /* tokenize with " .-_" */
2929 fontname_tokenize(&tokens
, familynameW
);
2931 /* extract and resolve style */
2932 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
2934 /* extract stretch */
2935 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
2937 /* extract weight */
2938 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
2940 /* resolve weight */
2941 if (weight
!= font
->weight
) {
2942 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
2943 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
2944 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
2945 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
2946 !(abs(weight
- font
->weight
) <= 150 &&
2947 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
2948 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
2949 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
2951 font
->weight
= weight
;
2955 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
2956 it's leaning in opposite direction from normal comparing to specified stretch or if specified
2957 stretch itself is normal (extracted stretch is never normal). */
2958 if (stretch
!= font
->stretch
) {
2959 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
2960 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
2961 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
2963 font
->stretch
= stretch
;
2967 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
2969 /* get final combined string from what's left in token list, list is released */
2970 fontname_tokens_to_str(&tokens
, finalW
);
2972 if (!strcmpW(familyW
, finalW
))
2975 /* construct face name */
2976 strcpyW(familyW
, finalW
);
2978 /* resolved weight name */
2979 if (weight_name
.ptr
)
2980 font_name_token_to_str(&weight_name
, weightW
);
2981 /* ignore normal weight */
2982 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
2984 /* for known weight values use appropriate names */
2985 else if (is_known_weight_value(font
->weight
, weightW
)) {
2987 /* use Wnnn format as a fallback in case weight is not one of known values */
2989 static const WCHAR fmtW
[] = {'W','%','d',0};
2990 sprintfW(weightW
, fmtW
, font
->weight
);
2993 /* resolved stretch name */
2994 if (stretch_name
.ptr
)
2995 font_name_token_to_str(&stretch_name
, stretchW
);
2996 /* ignore normal stretch */
2997 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
2999 /* use predefined stretch names */
3001 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3002 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
3003 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
3004 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
3005 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3006 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
3008 static const WCHAR
*stretchnamesW
[] = {
3013 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
3019 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
3022 /* resolved style name */
3024 font_name_token_to_str(&style_name
, styleW
);
3025 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
3027 /* use predefined names */
3029 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
3030 strcpyW(styleW
, italicW
);
3032 strcpyW(styleW
, obliqueW
);
3035 /* use Regular match if it was found initially */
3036 if (!*weightW
&& !*stretchW
&& !*styleW
)
3037 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
3041 strcpyW(faceW
, stretchW
);
3044 strcatW(faceW
, spaceW
);
3045 strcatW(faceW
, weightW
);
3049 strcatW(faceW
, spaceW
);
3050 strcatW(faceW
, styleW
);
3054 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
3058 static HRESULT
init_font_data(IDWriteFactory3
*factory
, IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
, UINT32 face_index
,
3059 IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
3061 struct file_stream_desc stream_desc
;
3062 struct dwrite_font_props props
;
3063 struct dwrite_font_data
*data
;
3064 IDWriteFontFileStream
*stream
;
3065 WCHAR familyW
[255], faceW
[255];
3069 data
= heap_alloc_zero(sizeof(*data
));
3071 return E_OUTOFMEMORY
;
3073 hr
= get_filestream_from_file(file
, &stream
);
3080 data
->factory
= factory
;
3082 data
->face_index
= face_index
;
3083 data
->face_type
= face_type
;
3084 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
3085 data
->bold_sim_tested
= 0;
3086 data
->oblique_sim_tested
= 0;
3087 IDWriteFontFile_AddRef(file
);
3088 IDWriteFactory3_AddRef(factory
);
3090 stream_desc
.stream
= stream
;
3091 stream_desc
.face_type
= face_type
;
3092 stream_desc
.face_index
= face_index
;
3093 opentype_get_font_properties(&stream_desc
, &props
);
3094 opentype_get_font_metrics(&stream_desc
, &data
->metrics
, NULL
);
3095 opentype_get_font_facename(&stream_desc
, &data
->names
);
3097 /* get family name from font file */
3098 hr
= opentype_get_font_familyname(&stream_desc
, family_name
);
3099 IDWriteFontFileStream_Release(stream
);
3101 WARN("unable to get family name from font\n");
3102 release_font_data(data
);
3106 data
->style
= props
.style
;
3107 data
->stretch
= props
.stretch
;
3108 data
->weight
= props
.weight
;
3109 data
->panose
= props
.panose
;
3111 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3112 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
3113 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
3114 set_en_localizedstring(*family_name
, familyW
);
3115 set_en_localizedstring(data
->names
, faceW
);
3118 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3124 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
, const WCHAR
*facenameW
,
3125 struct dwrite_font_data
**ret
)
3127 struct dwrite_font_data
*data
;
3130 data
= heap_alloc_zero(sizeof(*data
));
3132 return E_OUTOFMEMORY
;
3136 data
->simulations
|= sim
;
3137 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
3138 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
3139 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
3140 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
3141 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
3143 IDWriteFactory3_AddRef(data
->factory
);
3144 IDWriteFontFile_AddRef(data
->file
);
3146 create_localizedstrings(&data
->names
);
3147 add_localizedstring(data
->names
, enusW
, facenameW
);
3149 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
3155 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
3157 struct dwrite_fontfamily_data
*data
;
3159 data
= heap_alloc(sizeof(*data
));
3161 return E_OUTOFMEMORY
;
3164 data
->font_count
= 0;
3165 data
->font_alloc
= 2;
3166 data
->has_normal_face
= 0;
3167 data
->has_oblique_face
= 0;
3168 data
->has_italic_face
= 0;
3170 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
3173 return E_OUTOFMEMORY
;
3176 data
->familyname
= familyname
;
3177 IDWriteLocalizedStrings_AddRef(familyname
);
3183 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
3185 UINT32 i
, j
, heaviest
;
3187 for (i
= 0; i
< family
->font_count
; i
++) {
3188 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
3191 if (family
->fonts
[i
]->bold_sim_tested
)
3194 family
->fonts
[i
]->bold_sim_tested
= 1;
3195 for (j
= i
; j
< family
->font_count
; j
++) {
3196 if (family
->fonts
[j
]->bold_sim_tested
)
3199 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
3200 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3201 if (family
->fonts
[j
]->weight
> weight
) {
3202 weight
= family
->fonts
[j
]->weight
;
3205 family
->fonts
[j
]->bold_sim_tested
= 1;
3209 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
3210 static const struct name_pattern weightsim_patterns
[] = {
3225 WCHAR facenameW
[255], initialW
[255];
3226 struct dwrite_font_data
*boldface
;
3229 /* add Bold simulation based on heaviest face data */
3231 /* Simulated face name should only contain Bold as weight term,
3232 so remove existing regular and weight terms. */
3233 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
3234 facename_remove_regular_term(initialW
, -1);
3236 /* remove current weight pattern */
3237 fontname_tokenize(&tokens
, initialW
);
3238 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
3239 fontname_tokens_to_str(&tokens
, facenameW
);
3241 /* Bold suffix for new name */
3243 strcatW(facenameW
, spaceW
);
3244 strcatW(facenameW
, boldW
);
3246 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
3247 boldface
->bold_sim_tested
= 1;
3248 fontfamily_add_font(family
, boldface
);
3254 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3258 for (i
= 0; i
< family
->font_count
; i
++) {
3259 UINT32 regular
= ~0u, oblique
= ~0u;
3260 struct dwrite_font_data
*obliqueface
;
3261 WCHAR facenameW
[255];
3263 if (family
->fonts
[i
]->oblique_sim_tested
)
3266 family
->fonts
[i
]->oblique_sim_tested
= 1;
3267 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3269 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3272 /* find regular style with same weight/stretch values */
3273 for (j
= i
; j
< family
->font_count
; j
++) {
3274 if (family
->fonts
[j
]->oblique_sim_tested
)
3277 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3278 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3280 family
->fonts
[j
]->oblique_sim_tested
= 1;
3281 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3284 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3288 if (regular
!= ~0u && oblique
!= ~0u)
3292 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3296 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3300 /* add oblique simulation based on this regular face */
3302 /* remove regular term if any, append 'Oblique' */
3303 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3304 facename_remove_regular_term(facenameW
, -1);
3307 strcatW(facenameW
, spaceW
);
3308 strcatW(facenameW
, obliqueW
);
3310 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3311 obliqueface
->oblique_sim_tested
= 1;
3312 fontfamily_add_font(family
, obliqueface
);
3317 static BOOL
fontcollection_add_replacement(struct dwrite_fontcollection
*collection
, const WCHAR
*target_name
,
3318 const WCHAR
*replacement_name
)
3320 UINT32 i
= collection_find_family(collection
, replacement_name
);
3321 struct dwrite_fontfamily_data
*target
;
3322 IDWriteLocalizedStrings
*strings
;
3325 /* replacement does not exist */
3329 hr
= create_localizedstrings(&strings
);
3333 /* add a new family with target name, reuse font data from replacement */
3334 add_localizedstring(strings
, enusW
, target_name
);
3335 hr
= init_fontfamily_data(strings
, &target
);
3337 struct dwrite_fontfamily_data
*replacement
= collection
->family_data
[i
];
3340 for (i
= 0; i
< replacement
->font_count
; i
++)
3341 fontfamily_add_font(target
, replacement
->fonts
[i
]);
3343 fontcollection_add_family(collection
, target
);
3344 fontstrings_get_en_string(replacement
->familyname
, nameW
, sizeof(nameW
)/sizeof(WCHAR
));
3345 TRACE("replacement %s -> %s\n", debugstr_w(target_name
), debugstr_w(nameW
));
3347 IDWriteLocalizedStrings_Release(strings
);
3351 /* Add family mappings from HKCU\Software\Wine\Fonts\Replacements. This only affects
3352 system font collections. */
3353 static void fontcollection_add_replacements(struct dwrite_fontcollection
*collection
)
3355 DWORD max_namelen
, max_datalen
, i
= 0, type
, datalen
, namelen
;
3360 if (RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Fonts\\Replacements", &hkey
))
3363 if (RegQueryInfoKeyW(hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_namelen
, &max_datalen
, NULL
, NULL
)) {
3368 max_namelen
++; /* returned value doesn't include room for '\0' */
3369 name
= heap_alloc(max_namelen
* sizeof(WCHAR
));
3370 data
= heap_alloc(max_datalen
);
3372 datalen
= max_datalen
;
3373 namelen
= max_namelen
;
3374 while (RegEnumValueW(hkey
, i
++, name
, &namelen
, NULL
, &type
, data
, &datalen
) == ERROR_SUCCESS
) {
3375 if (collection_find_family(collection
, name
) == ~0u) {
3376 if (type
== REG_MULTI_SZ
) {
3377 WCHAR
*replacement
= data
;
3378 while (*replacement
) {
3379 if (fontcollection_add_replacement(collection
, name
, replacement
))
3381 replacement
+= strlenW(replacement
) + 1;
3384 else if (type
== REG_SZ
)
3385 fontcollection_add_replacement(collection
, name
, data
);
3388 TRACE("%s is available, won't be replaced.\n", debugstr_w(name
));
3390 datalen
= max_datalen
;
3391 namelen
= max_namelen
;
3399 HRESULT
create_font_collection(IDWriteFactory3
*factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
3401 struct fontfile_enum
{
3403 IDWriteFontFile
*file
;
3405 struct fontfile_enum
*fileenum
, *fileenum2
;
3406 struct dwrite_fontcollection
*collection
;
3407 struct list scannedfiles
;
3408 BOOL current
= FALSE
;
3414 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3415 if (!collection
) return E_OUTOFMEMORY
;
3417 hr
= init_font_collection(collection
, is_system
);
3419 heap_free(collection
);
3423 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3425 TRACE("building font collection:\n");
3427 list_init(&scannedfiles
);
3428 while (hr
== S_OK
) {
3429 DWRITE_FONT_FACE_TYPE face_type
;
3430 DWRITE_FONT_FILE_TYPE file_type
;
3431 BOOL supported
, same
= FALSE
;
3432 IDWriteFontFile
*file
;
3436 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3437 if (FAILED(hr
) || !current
)
3440 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3444 /* check if we've scanned this file already */
3445 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3446 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3451 IDWriteFontFile_Release(file
);
3455 /* failed font files are skipped */
3456 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3457 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3458 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3459 IDWriteFontFile_Release(file
);
3464 /* add to scanned list */
3465 fileenum
= heap_alloc(sizeof(*fileenum
));
3466 fileenum
->file
= file
;
3467 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3469 for (i
= 0; i
< face_count
; i
++) {
3470 IDWriteLocalizedStrings
*family_name
= NULL
;
3471 struct dwrite_font_data
*font_data
;
3475 /* alloc and init new font data structure */
3476 hr
= init_font_data(factory
, file
, face_type
, i
, &family_name
, &font_data
);
3478 /* move to next one */
3483 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3485 index
= collection_find_family(collection
, familyW
);
3487 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3489 struct dwrite_fontfamily_data
*family_data
;
3491 /* create and init new family */
3492 hr
= init_fontfamily_data(family_name
, &family_data
);
3494 /* add font to family, family - to collection */
3495 hr
= fontfamily_add_font(family_data
, font_data
);
3497 hr
= fontcollection_add_family(collection
, family_data
);
3500 release_fontfamily_data(family_data
);
3504 IDWriteLocalizedStrings_Release(family_name
);
3511 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3512 IDWriteFontFile_Release(fileenum
->file
);
3513 list_remove(&fileenum
->entry
);
3514 heap_free(fileenum
);
3517 for (i
= 0; i
< collection
->family_count
; i
++) {
3518 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3519 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3523 fontcollection_add_replacements(collection
);
3528 struct system_fontfile_enumerator
3530 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3533 IDWriteFactory3
*factory
;
3538 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3540 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3543 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3547 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3548 IDWriteFontFileEnumerator_AddRef(iface
);
3553 return E_NOINTERFACE
;
3556 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3558 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3559 return InterlockedIncrement(&enumerator
->ref
);
3562 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3564 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3565 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3568 IDWriteFactory3_Release(enumerator
->factory
);
3569 RegCloseKey(enumerator
->hkey
);
3570 heap_free(enumerator
);
3576 static HRESULT
create_local_file_reference(IDWriteFactory3
*factory
, const WCHAR
*filename
, IDWriteFontFile
**file
)
3580 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3581 if (!strchrW(filename
, '\\')) {
3582 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3583 WCHAR fullpathW
[MAX_PATH
];
3585 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3586 strcatW(fullpathW
, fontsW
);
3587 strcatW(fullpathW
, filename
);
3589 hr
= IDWriteFactory3_CreateFontFileReference(factory
, fullpathW
, NULL
, file
);
3592 hr
= IDWriteFactory3_CreateFontFileReference(factory
, filename
, NULL
, file
);
3597 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3599 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3600 DWORD ret
, type
, val_count
, count
;
3601 WCHAR
*value
, *filename
;
3606 if (enumerator
->index
< 0)
3609 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3610 if (ret
!= ERROR_SUCCESS
)
3614 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3615 filename
= heap_alloc(count
);
3616 if (!value
|| !filename
) {
3618 heap_free(filename
);
3619 return E_OUTOFMEMORY
;
3622 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3625 heap_free(filename
);
3629 hr
= create_local_file_reference(enumerator
->factory
, filename
, file
);
3632 heap_free(filename
);
3636 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3638 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3639 DWORD ret
, max_val_count
;
3643 enumerator
->index
++;
3645 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
3646 if (ret
!= ERROR_SUCCESS
)
3650 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
3651 return E_OUTOFMEMORY
;
3653 /* iterate until we find next string value */
3655 DWORD type
= 0, count
, val_count
;
3656 val_count
= max_val_count
;
3657 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
3659 if (type
== REG_SZ
) {
3663 enumerator
->index
++;
3666 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3671 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3673 systemfontfileenumerator_QueryInterface
,
3674 systemfontfileenumerator_AddRef
,
3675 systemfontfileenumerator_Release
,
3676 systemfontfileenumerator_MoveNext
,
3677 systemfontfileenumerator_GetCurrentFontFile
3680 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory3
*factory
, IDWriteFontFileEnumerator
**ret
)
3682 struct system_fontfile_enumerator
*enumerator
;
3683 static const WCHAR fontslistW
[] = {
3684 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3685 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3686 'F','o','n','t','s',0
3691 enumerator
= heap_alloc(sizeof(*enumerator
));
3693 return E_OUTOFMEMORY
;
3695 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3696 enumerator
->ref
= 1;
3697 enumerator
->factory
= factory
;
3698 enumerator
->index
= -1;
3699 IDWriteFactory3_AddRef(factory
);
3701 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3702 ERR("failed to open fonts list key\n");
3703 IDWriteFactory3_Release(factory
);
3704 heap_free(enumerator
);
3708 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3713 HRESULT
get_system_fontcollection(IDWriteFactory3
*factory
, IDWriteFontCollection
**collection
)
3715 IDWriteFontFileEnumerator
*enumerator
;
3720 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3724 TRACE("building system font collection for factory %p\n", factory
);
3725 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3726 IDWriteFontFileEnumerator_Release(enumerator
);
3730 static HRESULT
eudc_collection_add_family(IDWriteFactory3
*factory
, struct dwrite_fontcollection
*collection
,
3731 const WCHAR
*keynameW
, const WCHAR
*pathW
)
3733 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};
3734 static const WCHAR emptyW
[] = {0};
3735 IDWriteLocalizedStrings
*names
;
3736 DWRITE_FONT_FACE_TYPE face_type
;
3737 DWRITE_FONT_FILE_TYPE file_type
;
3739 UINT32 face_count
, i
;
3740 IDWriteFontFile
*file
;
3742 struct dwrite_fontfamily_data
*family_data
;
3744 /* create font file from this path */
3745 hr
= create_local_file_reference(factory
, pathW
, &file
);
3749 /* failed font files are skipped */
3750 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3751 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3752 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3753 IDWriteFontFile_Release(file
);
3757 /* create and init new family */
3759 /* Family names are added for non-specific locale, represented with empty string.
3760 Default family appears with empty family name. */
3761 create_localizedstrings(&names
);
3762 if (!strcmpiW(keynameW
, defaultfontW
))
3763 add_localizedstring(names
, emptyW
, emptyW
);
3765 add_localizedstring(names
, emptyW
, keynameW
);
3767 hr
= init_fontfamily_data(names
, &family_data
);
3768 IDWriteLocalizedStrings_Release(names
);
3770 IDWriteFontFile_Release(file
);
3774 /* fill with faces */
3775 for (i
= 0; i
< face_count
; i
++) {
3776 struct dwrite_font_data
*font_data
;
3778 /* alloc and init new font data structure */
3779 hr
= init_font_data(factory
, file
, face_type
, i
, &names
, &font_data
);
3783 IDWriteLocalizedStrings_Release(names
);
3785 /* add font to family */
3786 hr
= fontfamily_add_font(family_data
, font_data
);
3788 release_font_data(font_data
);
3791 /* add family to collection */
3792 hr
= fontcollection_add_family(collection
, family_data
);
3794 release_fontfamily_data(family_data
);
3795 IDWriteFontFile_Release(file
);
3800 HRESULT
get_eudc_fontcollection(IDWriteFactory3
*factory
, IDWriteFontCollection
**ret
)
3802 static const WCHAR eudckeyfmtW
[] = {'E','U','D','C','\\','%','u',0};
3803 struct dwrite_fontcollection
*collection
;
3804 static const WCHAR emptyW
[] = {0};
3805 WCHAR eudckeypathW
[16];
3813 TRACE("building EUDC font collection for factory %p, ACP %u\n", factory
, GetACP());
3817 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3818 if (!collection
) return E_OUTOFMEMORY
;
3820 hr
= init_font_collection(collection
, FALSE
);
3822 heap_free(collection
);
3826 *ret
= (IDWriteFontCollection
*)&collection
->IDWriteFontCollection1_iface
;
3828 /* return empty collection if EUDC fonts are not configured */
3829 sprintfW(eudckeypathW
, eudckeyfmtW
, GetACP());
3830 if (RegOpenKeyExW(HKEY_CURRENT_USER
, eudckeypathW
, 0, GENERIC_READ
, &eudckey
))
3833 retval
= ERROR_SUCCESS
;
3835 while (retval
!= ERROR_NO_MORE_ITEMS
) {
3836 WCHAR keynameW
[64], pathW
[MAX_PATH
];
3837 DWORD type
, path_len
, name_len
;
3839 path_len
= sizeof(pathW
)/sizeof(*pathW
);
3840 name_len
= sizeof(keynameW
)/sizeof(*keynameW
);
3841 retval
= RegEnumValueW(eudckey
, index
++, keynameW
, &name_len
, NULL
, &type
, (BYTE
*)pathW
, &path_len
);
3842 if (retval
|| type
!= REG_SZ
)
3845 hr
= eudc_collection_add_family(factory
, collection
, keynameW
, pathW
);
3847 WARN("failed to add family %s, path %s\n", debugstr_w(keynameW
), debugstr_w(pathW
));
3849 RegCloseKey(eudckey
);
3851 /* try to add global default if not defined for specific codepage */
3853 hr
= IDWriteFontCollection1_FindFamilyName(&collection
->IDWriteFontCollection1_iface
, emptyW
,
3855 if (FAILED(hr
) || !exists
) {
3856 const WCHAR globaldefaultW
[] = {'E','U','D','C','.','T','T','E',0};
3857 hr
= eudc_collection_add_family(factory
, collection
, emptyW
, globaldefaultW
);
3859 WARN("failed to add global default EUDC font, 0x%08x\n", hr
);
3862 /* EUDC collection offers simulated faces too */
3863 for (i
= 0; i
< collection
->family_count
; i
++) {
3864 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3865 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3871 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
3873 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3875 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3877 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
3880 IDWriteFontFile_AddRef(iface
);
3885 return E_NOINTERFACE
;
3888 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
3890 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3891 ULONG ref
= InterlockedIncrement(&This
->ref
);
3892 TRACE("(%p)->(%d)\n", This
, ref
);
3896 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
3898 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3899 ULONG ref
= InterlockedDecrement(&This
->ref
);
3901 TRACE("(%p)->(%d)\n", This
, ref
);
3905 IDWriteFontFileLoader_Release(This
->loader
);
3906 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
3907 heap_free(This
->reference_key
);
3914 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
3916 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3917 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
3918 *fontFileReferenceKey
= This
->reference_key
;
3919 *fontFileReferenceKeySize
= This
->key_size
;
3924 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
3926 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3927 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
3928 *fontFileLoader
= This
->loader
;
3929 IDWriteFontFileLoader_AddRef(This
->loader
);
3934 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
,
3935 DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
3937 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3938 IDWriteFontFileStream
*stream
;
3941 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
3943 *isSupportedFontType
= FALSE
;
3944 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3946 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3949 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
3953 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
3955 /* TODO: Further Analysis */
3956 IDWriteFontFileStream_Release(stream
);
3960 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
3961 dwritefontfile_QueryInterface
,
3962 dwritefontfile_AddRef
,
3963 dwritefontfile_Release
,
3964 dwritefontfile_GetReferenceKey
,
3965 dwritefontfile_GetLoader
,
3966 dwritefontfile_Analyze
,
3969 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
3971 struct dwrite_fontfile
*This
;
3973 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
3974 if (!This
) return E_OUTOFMEMORY
;
3976 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
3978 IDWriteFontFileLoader_AddRef(loader
);
3979 This
->loader
= loader
;
3980 This
->stream
= NULL
;
3981 This
->reference_key
= heap_alloc(key_size
);
3982 memcpy(This
->reference_key
, reference_key
, key_size
);
3983 This
->key_size
= key_size
;
3985 *font_file
= &This
->IDWriteFontFile_iface
;
3990 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3992 IDWriteFontFileLoader
*loader
;
3998 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
4002 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
4004 IDWriteFontFileLoader_Release(loader
);
4008 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
4009 IDWriteFontFileLoader_Release(loader
);
4014 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
4015 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
4017 struct file_stream_desc stream_desc
;
4018 struct dwrite_fontface
*fontface
;
4024 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
4026 return E_OUTOFMEMORY
;
4028 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
4029 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
4031 if (!fontface
->files
|| !fontface
->streams
) {
4032 heap_free(fontface
->files
);
4033 heap_free(fontface
->streams
);
4034 heap_free(fontface
);
4035 return E_OUTOFMEMORY
;
4038 fontface
->IDWriteFontFace3_iface
.lpVtbl
= &dwritefontfacevtbl
;
4040 fontface
->type
= facetype
;
4041 fontface
->file_count
= files_number
;
4042 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
4043 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
4044 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
4045 memset(&fontface
->cpal
, 0, sizeof(fontface
->cpal
));
4046 memset(&fontface
->colr
, 0, sizeof(fontface
->colr
));
4047 fontface
->cmap
.exists
= TRUE
;
4048 fontface
->vdmx
.exists
= TRUE
;
4049 fontface
->gasp
.exists
= TRUE
;
4050 fontface
->cpal
.exists
= TRUE
;
4051 fontface
->colr
.exists
= TRUE
;
4052 fontface
->index
= index
;
4053 fontface
->simulations
= simulations
;
4054 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
4056 for (i
= 0; i
< fontface
->file_count
; i
++) {
4057 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
4059 IDWriteFontFace3_Release(&fontface
->IDWriteFontFace3_iface
);
4063 fontface
->files
[i
] = font_files
[i
];
4064 IDWriteFontFile_AddRef(font_files
[i
]);
4067 stream_desc
.stream
= fontface
->streams
[0];
4068 stream_desc
.face_type
= facetype
;
4069 stream_desc
.face_index
= index
;
4070 opentype_get_font_metrics(&stream_desc
, &fontface
->metrics
, &fontface
->caret
);
4071 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
4072 /* TODO: test what happens if caret is already slanted */
4073 if (fontface
->caret
.slopeRise
== 1) {
4074 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
4075 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
4078 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace3_iface
, &fontface
->is_symbol
);
4079 fontface
->has_kerning_pairs
= freetype_has_kerning_pairs(&fontface
->IDWriteFontFace3_iface
);
4080 fontface
->is_monospaced
= freetype_is_monospaced(&fontface
->IDWriteFontFace3_iface
);
4082 *ret
= &fontface
->IDWriteFontFace3_iface
;
4086 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
4093 struct local_cached_stream
4096 IDWriteFontFileStream
*stream
;
4097 struct local_refkey
*key
;
4101 struct dwrite_localfontfilestream
4103 IDWriteFontFileStream IDWriteFontFileStream_iface
;
4106 struct local_cached_stream
*entry
;
4107 const void *file_ptr
;
4111 struct dwrite_localfontfileloader
{
4112 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
4115 struct list streams
;
4118 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
4120 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
4123 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
4125 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
4128 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
4130 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4131 TRACE_(dwrite_file
)("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4132 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
4135 IDWriteFontFileStream_AddRef(iface
);
4140 return E_NOINTERFACE
;
4143 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
4145 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4146 ULONG ref
= InterlockedIncrement(&This
->ref
);
4147 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4151 static inline void release_cached_stream(struct local_cached_stream
*stream
)
4153 list_remove(&stream
->entry
);
4154 heap_free(stream
->key
);
4158 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
4160 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4161 ULONG ref
= InterlockedDecrement(&This
->ref
);
4163 TRACE_(dwrite_file
)("(%p)->(%d)\n", This
, ref
);
4166 UnmapViewOfFile(This
->file_ptr
);
4167 release_cached_stream(This
->entry
);
4174 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
4176 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4178 TRACE_(dwrite_file
)("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
4179 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
4181 *fragment_context
= NULL
;
4183 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
4184 *fragment_start
= NULL
;
4188 *fragment_start
= (char*)This
->file_ptr
+ offset
;
4192 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
4194 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4195 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, fragment_context
);
4198 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
4200 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4201 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, size
);
4206 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
4208 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
4211 TRACE_(dwrite_file
)("(%p)->(%p)\n", This
, last_writetime
);
4213 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
4214 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
4215 *last_writetime
= li
.QuadPart
;
4220 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
4222 localfontfilestream_QueryInterface
,
4223 localfontfilestream_AddRef
,
4224 localfontfilestream_Release
,
4225 localfontfilestream_ReadFileFragment
,
4226 localfontfilestream_ReleaseFileFragment
,
4227 localfontfilestream_GetFileSize
,
4228 localfontfilestream_GetLastWriteTime
4231 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
**ret
)
4233 struct dwrite_localfontfilestream
*This
;
4237 This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
4239 return E_OUTOFMEMORY
;
4241 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
4244 This
->file_ptr
= file_ptr
;
4246 This
->entry
= entry
;
4248 *ret
= &This
->IDWriteFontFileStream_iface
;
4252 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
4254 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4256 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
4258 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
4261 IDWriteLocalFontFileLoader_AddRef(iface
);
4266 return E_NOINTERFACE
;
4269 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
4271 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4272 ULONG ref
= InterlockedIncrement(&This
->ref
);
4273 TRACE("(%p)->(%d)\n", This
, ref
);
4277 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
4279 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4280 ULONG ref
= InterlockedDecrement(&This
->ref
);
4282 TRACE("(%p)->(%d)\n", This
, ref
);
4285 struct local_cached_stream
*stream
, *stream2
;
4287 /* This will detach all entries from cache. Entries are released together with streams,
4288 so stream controls cache entry lifetime. */
4289 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
4290 list_init(&stream
->entry
);
4298 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
4300 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4301 const struct local_refkey
*refkey
= key
;
4302 struct local_cached_stream
*stream
;
4303 IDWriteFontFileStream
*filestream
;
4304 HANDLE file
, mapping
;
4309 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
4310 TRACE("name: %s\n", debugstr_w(refkey
->name
));
4312 /* search cache first */
4313 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
4314 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
4315 *ret
= stream
->stream
;
4316 IDWriteFontFileStream_AddRef(*ret
);
4323 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
4324 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
4325 if (file
== INVALID_HANDLE_VALUE
)
4328 GetFileSizeEx(file
, &size
);
4329 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
4334 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
4335 CloseHandle(mapping
);
4337 stream
= heap_alloc(sizeof(*stream
));
4339 UnmapViewOfFile(file_ptr
);
4340 return E_OUTOFMEMORY
;
4343 stream
->key
= heap_alloc(key_size
);
4345 UnmapViewOfFile(file_ptr
);
4347 return E_OUTOFMEMORY
;
4350 stream
->key_size
= key_size
;
4351 memcpy(stream
->key
, key
, key_size
);
4353 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
4355 UnmapViewOfFile(file_ptr
);
4356 heap_free(stream
->key
);
4361 stream
->stream
= filestream
;
4362 list_add_head(&This
->streams
, &stream
->entry
);
4364 *ret
= stream
->stream
;
4369 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
4371 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4372 const struct local_refkey
*refkey
= key
;
4374 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
4376 *length
= strlenW(refkey
->name
);
4380 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
4382 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4383 const struct local_refkey
*refkey
= key
;
4385 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
4387 if (length
< strlenW(refkey
->name
))
4388 return E_INVALIDARG
;
4390 strcpyW(path
, refkey
->name
);
4394 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
4396 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
4397 const struct local_refkey
*refkey
= key
;
4399 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
4401 *writetime
= refkey
->writetime
;
4405 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
4406 localfontfileloader_QueryInterface
,
4407 localfontfileloader_AddRef
,
4408 localfontfileloader_Release
,
4409 localfontfileloader_CreateStreamFromKey
,
4410 localfontfileloader_GetFilePathLengthFromKey
,
4411 localfontfileloader_GetFilePathFromKey
,
4412 localfontfileloader_GetLastWriteTimeFromKey
4415 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
**ret
)
4417 struct dwrite_localfontfileloader
*This
;
4421 This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
4423 return E_OUTOFMEMORY
;
4425 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
4427 list_init(&This
->streams
);
4429 *ret
= &This
->IDWriteLocalFontFileLoader_iface
;
4433 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
4435 struct local_refkey
*refkey
;
4438 return E_INVALIDARG
;
4440 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
4443 refkey
= heap_alloc(*size
);
4445 return E_OUTOFMEMORY
;
4448 refkey
->writetime
= *writetime
;
4450 WIN32_FILE_ATTRIBUTE_DATA info
;
4452 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
4453 refkey
->writetime
= info
.ftLastWriteTime
;
4455 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4457 strcpyW(refkey
->name
, path
);
4464 /* IDWriteGlyphRunAnalysis */
4465 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4467 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4469 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4471 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4472 IsEqualIID(riid
, &IID_IUnknown
))
4475 IDWriteGlyphRunAnalysis_AddRef(iface
);
4480 return E_NOINTERFACE
;
4483 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4485 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4486 ULONG ref
= InterlockedIncrement(&This
->ref
);
4487 TRACE("(%p)->(%u)\n", This
, ref
);
4491 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4493 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4494 ULONG ref
= InterlockedDecrement(&This
->ref
);
4496 TRACE("(%p)->(%u)\n", This
, ref
);
4499 if (This
->run
.fontFace
)
4500 IDWriteFontFace_Release(This
->run
.fontFace
);
4501 heap_free(This
->glyphs
);
4502 heap_free(This
->advances
);
4503 heap_free(This
->advanceoffsets
);
4504 heap_free(This
->ascenderoffsets
);
4505 heap_free(This
->bitmap
);
4512 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4514 struct dwrite_glyphbitmap glyph_bitmap
;
4515 IDWriteFontFace3
*fontface3
;
4516 D2D_POINT_2F origin
;
4521 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4522 *bounds
= analysis
->bounds
;
4526 if (analysis
->run
.isSideways
)
4527 FIXME("sideways runs are not supported.\n");
4529 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
4531 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4533 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
4534 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
4535 for any non-zero glyph ascender */
4536 origin
.x
= origin
.y
= 0.0f
;
4537 is_rtl
= analysis
->run
.bidiLevel
& 1;
4539 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4540 glyph_bitmap
.fontface
= fontface3
;
4541 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4542 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4543 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4544 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4545 glyph_bitmap
.m
= &analysis
->m
;
4547 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4548 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4549 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4550 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4551 RECT
*bbox
= &glyph_bitmap
.bbox
;
4553 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4554 freetype_get_glyph_bbox(&glyph_bitmap
);
4557 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4559 OffsetRect(bbox
, origin
.x
, origin
.y
);
4562 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4564 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4565 origin
.x
+= advance
->x
;
4566 origin
.y
+= advance
->y
;
4569 IDWriteFontFace3_Release(fontface3
);
4571 /* translate to given run origin */
4572 OffsetRect(&analysis
->bounds
, analysis
->origin
.x
, analysis
->origin
.y
);
4573 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4574 OffsetRect(&analysis
->bounds
, analysis
->m
.dx
, analysis
->m
.dy
);
4576 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4577 *bounds
= analysis
->bounds
;
4580 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4582 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4584 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4586 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4587 memset(bounds
, 0, sizeof(*bounds
));
4588 return E_INVALIDARG
;
4591 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
4592 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
4593 memset(bounds
, 0, sizeof(*bounds
));
4597 glyphrunanalysis_get_texturebounds(This
, bounds
);
4601 static inline int get_dib_stride( int width
, int bpp
)
4603 return ((width
* bpp
+ 31) >> 3) & ~3;
4606 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4608 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4609 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4610 (runbounds
->left
- bounds
->left
) * 3;
4612 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4613 runbounds
->left
- bounds
->left
;
4616 static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
, DWRITE_TEXTURE_TYPE type
)
4618 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4619 struct dwrite_glyphbitmap glyph_bitmap
;
4620 IDWriteFontFace3
*fontface2
;
4621 D2D_POINT_2F origin
;
4627 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface2
);
4629 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
4633 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4634 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4636 analysis
->bitmap
= heap_alloc_zero(size
);
4638 origin
.x
= origin
.y
= 0.0f
;
4639 is_rtl
= analysis
->run
.bidiLevel
& 1;
4641 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4642 glyph_bitmap
.fontface
= fontface2
;
4643 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4644 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4645 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4646 glyph_bitmap
.type
= type
;
4647 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4648 glyph_bitmap
.m
= &analysis
->m
;
4649 bbox
= &glyph_bitmap
.bbox
;
4651 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4652 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4653 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4654 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4655 int x
, y
, width
, height
;
4659 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4660 freetype_get_glyph_bbox(&glyph_bitmap
);
4662 if (IsRectEmpty(bbox
)) {
4663 origin
.x
+= advance
->x
;
4664 origin
.y
+= advance
->y
;
4668 width
= bbox
->right
- bbox
->left
;
4669 height
= bbox
->bottom
- bbox
->top
;
4671 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4672 glyph_bitmap
.pitch
= (width
+ 3) / 4 * 4;
4674 glyph_bitmap
.pitch
= ((width
+ 31) >> 5) << 2;
4676 glyph_bitmap
.buf
= src
= heap_alloc_zero(height
* glyph_bitmap
.pitch
);
4677 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4680 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4682 OffsetRect(bbox
, origin
.x
, origin
.y
);
4685 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4687 OffsetRect(bbox
, analysis
->origin
.x
, analysis
->origin
.y
);
4688 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4689 OffsetRect(bbox
, analysis
->m
.dx
, analysis
->m
.dy
);
4691 /* blit to analysis bitmap */
4692 dst
= get_pixel_ptr(analysis
->bitmap
, type
, bbox
, &analysis
->bounds
);
4695 /* convert 1bpp to 8bpp/24bpp */
4696 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4697 for (y
= 0; y
< height
; y
++) {
4698 for (x
= 0; x
< width
; x
++)
4699 if (src
[x
/ 8] & masks
[x
% 8])
4700 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4701 src
+= glyph_bitmap
.pitch
;
4702 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4706 for (y
= 0; y
< height
; y
++) {
4707 for (x
= 0; x
< width
; x
++)
4708 if (src
[x
/ 8] & masks
[x
% 8])
4709 dst
[x
] = DWRITE_ALPHA_MAX
;
4710 src
+= get_dib_stride(width
, 1);
4711 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
4716 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
4717 for (y
= 0; y
< height
; y
++) {
4718 for (x
= 0; x
< width
; x
++)
4719 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
4720 src
+= glyph_bitmap
.pitch
;
4721 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4725 heap_free(glyph_bitmap
.buf
);
4727 origin
.x
+= advance
->x
;
4728 origin
.y
+= advance
->y
;
4731 IDWriteFontFace3_Release(fontface2
);
4733 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
4735 /* we don't need this anymore */
4736 heap_free(analysis
->glyphs
);
4737 heap_free(analysis
->advances
);
4738 heap_free(analysis
->advanceoffsets
);
4739 heap_free(analysis
->ascenderoffsets
);
4740 IDWriteFontFace_Release(analysis
->run
.fontFace
);
4742 analysis
->glyphs
= NULL
;
4743 analysis
->advances
= NULL
;
4744 analysis
->advanceoffsets
= NULL
;
4745 analysis
->ascenderoffsets
= NULL
;
4746 analysis
->run
.glyphIndices
= NULL
;
4747 analysis
->run
.fontFace
= NULL
;
4750 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
4751 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
4753 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4757 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
4759 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
4760 return E_INVALIDARG
;
4762 /* make sure buffer is large enough for requested texture type */
4763 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
4764 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4767 if (size
< required
)
4768 return E_NOT_SUFFICIENT_BUFFER
;
4770 /* validate requested texture type with rendering mode */
4771 switch (This
->rendering_mode
)
4773 case DWRITE_RENDERING_MODE_ALIASED
:
4774 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
4775 return DWRITE_E_UNSUPPORTEDOPERATION
;
4777 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4778 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4779 case DWRITE_RENDERING_MODE_NATURAL
:
4780 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4781 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
4782 return DWRITE_E_UNSUPPORTEDOPERATION
;
4788 memset(bitmap
, 0, size
);
4789 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
4790 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
4791 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
4792 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
4793 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
4794 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
4798 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
))
4799 glyphrunanalysis_render(This
, type
);
4801 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
4802 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
4804 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
4805 memcpy(dst
, src
, draw_width
);
4814 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
4815 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
4817 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4819 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
4822 return E_INVALIDARG
;
4824 switch (This
->rendering_mode
)
4826 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4827 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4830 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
4831 *gamma
= (FLOAT
)value
/ 1000.0f
;
4833 *cleartypelevel
= 1.0f
;
4836 case DWRITE_RENDERING_MODE_ALIASED
:
4837 case DWRITE_RENDERING_MODE_NATURAL
:
4838 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4839 *gamma
= IDWriteRenderingParams_GetGamma(params
);
4840 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
4841 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
4850 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
4851 glyphrunanalysis_QueryInterface
,
4852 glyphrunanalysis_AddRef
,
4853 glyphrunanalysis_Release
,
4854 glyphrunanalysis_GetAlphaTextureBounds
,
4855 glyphrunanalysis_CreateAlphaTexture
,
4856 glyphrunanalysis_GetAlphaBlendParams
4859 static inline void init_2d_vec(D2D_POINT_2F
*vec
, FLOAT length
, BOOL is_vertical
)
4871 static inline void transform_2d_vec(D2D_POINT_2F
*vec
, const DWRITE_MATRIX
*m
)
4874 ret
.x
= vec
->x
* m
->m11
+ vec
->y
* m
->m21
;
4875 ret
.y
= vec
->x
* m
->m12
+ vec
->y
* m
->m22
;
4879 HRESULT
create_glyphrunanalysis(const struct glyphrunanalysis_desc
*desc
, IDWriteGlyphRunAnalysis
**ret
)
4881 struct dwrite_glyphrunanalysis
*analysis
;
4887 /* check for valid rendering mode */
4888 if ((UINT32
)desc
->rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| desc
->rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
4889 return E_INVALIDARG
;
4891 analysis
= heap_alloc(sizeof(*analysis
));
4893 return E_OUTOFMEMORY
;
4895 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
4897 analysis
->rendering_mode
= desc
->rendering_mode
;
4898 analysis
->flags
= 0;
4899 analysis
->bitmap
= NULL
;
4900 analysis
->ppdip
= desc
->ppdip
;
4901 analysis
->origin
.x
= desc
->origin_x
* desc
->ppdip
;
4902 analysis
->origin
.y
= desc
->origin_y
* desc
->ppdip
;
4903 SetRectEmpty(&analysis
->bounds
);
4904 analysis
->run
= *desc
->run
;
4905 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
4906 analysis
->glyphs
= heap_alloc(desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
4907 analysis
->advances
= heap_alloc(desc
->run
->glyphCount
*sizeof(*analysis
->advances
));
4908 if (desc
->run
->glyphOffsets
) {
4909 analysis
->advanceoffsets
= heap_alloc(desc
->run
->glyphCount
*sizeof(*analysis
->advanceoffsets
));
4910 analysis
->ascenderoffsets
= heap_alloc(desc
->run
->glyphCount
*sizeof(*analysis
->ascenderoffsets
));
4913 analysis
->advanceoffsets
= NULL
;
4914 analysis
->ascenderoffsets
= NULL
;
4917 if (!analysis
->glyphs
|| !analysis
->advances
|| ((!analysis
->advanceoffsets
|| !analysis
->ascenderoffsets
) && desc
->run
->glyphOffsets
)) {
4918 heap_free(analysis
->glyphs
);
4919 heap_free(analysis
->advances
);
4920 heap_free(analysis
->advanceoffsets
);
4921 heap_free(analysis
->ascenderoffsets
);
4923 analysis
->glyphs
= NULL
;
4924 analysis
->advances
= NULL
;
4925 analysis
->advanceoffsets
= NULL
;
4926 analysis
->ascenderoffsets
= NULL
;
4928 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
4929 return E_OUTOFMEMORY
;
4932 /* check if transform is usable */
4933 if (desc
->transform
&& memcmp(desc
->transform
, &identity
, sizeof(*desc
->transform
))) {
4934 analysis
->m
= *desc
->transform
;
4935 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
4938 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
4940 analysis
->run
.glyphIndices
= analysis
->glyphs
;
4941 analysis
->run
.glyphAdvances
= NULL
;
4942 analysis
->run
.glyphOffsets
= NULL
;
4944 rtl_factor
= desc
->run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
4946 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4947 transform_2d_vec(&analysis
->origin
, &analysis
->m
);
4949 memcpy(analysis
->glyphs
, desc
->run
->glyphIndices
, desc
->run
->glyphCount
*sizeof(*desc
->run
->glyphIndices
));
4951 if (desc
->run
->glyphAdvances
) {
4952 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
4953 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* desc
->run
->glyphAdvances
[i
] * desc
->ppdip
, desc
->run
->isSideways
);
4954 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4955 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4959 DWRITE_FONT_METRICS metrics
;
4960 IDWriteFontFace1
*fontface1
;
4962 IDWriteFontFace_GetMetrics(desc
->run
->fontFace
, &metrics
);
4963 IDWriteFontFace_QueryInterface(desc
->run
->fontFace
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4965 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
4969 switch (desc
->measuring_mode
)
4971 case DWRITE_MEASURING_MODE_NATURAL
:
4972 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, desc
->run
->glyphIndices
+ i
, &a
, desc
->run
->isSideways
);
4975 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* get_scaled_advance_width(a
, desc
->run
->fontEmSize
, &metrics
) * desc
->ppdip
,
4976 desc
->run
->isSideways
);
4978 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
4979 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
4980 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, desc
->run
->fontEmSize
, desc
->ppdip
, desc
->transform
,
4981 desc
->measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, desc
->run
->isSideways
, 1, desc
->run
->glyphIndices
+ i
, &a
);
4983 init_2d_vec(analysis
->advances
+ i
, 0.0f
, FALSE
);
4985 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* floorf(a
* desc
->run
->fontEmSize
* desc
->ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
),
4986 desc
->run
->isSideways
);
4992 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4993 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4996 IDWriteFontFace1_Release(fontface1
);
4999 if (desc
->run
->glyphOffsets
) {
5000 for (i
= 0; i
< desc
->run
->glyphCount
; i
++) {
5001 init_2d_vec(analysis
->advanceoffsets
+ i
, rtl_factor
* desc
->run
->glyphOffsets
[i
].advanceOffset
* desc
->ppdip
, desc
->run
->isSideways
);
5002 /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
5003 init_2d_vec(analysis
->ascenderoffsets
+ i
, -desc
->run
->glyphOffsets
[i
].ascenderOffset
* desc
->ppdip
, !desc
->run
->isSideways
);
5004 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
) {
5005 transform_2d_vec(analysis
->advanceoffsets
+ i
, &analysis
->m
);
5006 transform_2d_vec(analysis
->ascenderoffsets
+ i
, &analysis
->m
);
5011 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
5015 /* IDWriteColorGlyphRunEnumerator */
5016 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
5018 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5020 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
5022 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
5023 IsEqualIID(riid
, &IID_IUnknown
))
5026 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
5031 return E_NOINTERFACE
;
5034 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
5036 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5037 ULONG ref
= InterlockedIncrement(&This
->ref
);
5038 TRACE("(%p)->(%u)\n", This
, ref
);
5042 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
5044 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5045 ULONG ref
= InterlockedDecrement(&This
->ref
);
5047 TRACE("(%p)->(%u)\n", This
, ref
);
5050 heap_free(This
->advances
);
5051 heap_free(This
->color_advances
);
5052 heap_free(This
->offsets
);
5053 heap_free(This
->color_offsets
);
5054 heap_free(This
->glyphindices
);
5055 heap_free(This
->glyphs
);
5056 if (This
->colr
.context
)
5057 IDWriteFontFace3_ReleaseFontTable(This
->fontface
, This
->colr
.context
);
5058 IDWriteFontFace3_Release(This
->fontface
);
5065 static FLOAT
get_glyph_origin(const struct dwrite_colorglyphenum
*glyphenum
, UINT32 g
)
5067 BOOL is_rtl
= glyphenum
->run
.bidiLevel
& 1;
5068 FLOAT origin
= 0.0f
;
5074 origin
+= is_rtl
? -glyphenum
->advances
[g
] : glyphenum
->advances
[g
];
5078 static BOOL
colorglyphenum_build_color_run(struct dwrite_colorglyphenum
*glyphenum
)
5080 DWRITE_COLOR_GLYPH_RUN
*colorrun
= &glyphenum
->colorrun
;
5081 FLOAT advance_adj
= 0.0f
;
5082 BOOL got_palette_index
;
5085 /* start with regular glyphs */
5086 if (glyphenum
->current_layer
== 0 && glyphenum
->has_regular_glyphs
) {
5087 UINT32 first_glyph
= 0;
5089 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5090 if (glyphenum
->glyphs
[g
].num_layers
== 0) {
5091 glyphenum
->glyphindices
[g
] = glyphenum
->glyphs
[g
].glyph
;
5092 first_glyph
= min(first_glyph
, g
);
5095 glyphenum
->glyphindices
[g
] = 1;
5096 glyphenum
->color_advances
[g
] = glyphenum
->advances
[g
];
5097 if (glyphenum
->color_offsets
)
5098 glyphenum
->color_offsets
[g
] = glyphenum
->offsets
[g
];
5101 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, first_glyph
);
5102 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5103 colorrun
->glyphRun
.glyphCount
= glyphenum
->run
.glyphCount
;
5104 colorrun
->paletteIndex
= 0xffff;
5105 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5106 glyphenum
->has_regular_glyphs
= FALSE
;
5110 colorrun
->glyphRun
.glyphCount
= 0;
5111 got_palette_index
= FALSE
;
5115 for (g
= 0; g
< glyphenum
->run
.glyphCount
; g
++) {
5117 glyphenum
->glyphindices
[g
] = 1;
5119 /* all glyph layers were returned */
5120 if (glyphenum
->glyphs
[g
].layer
== glyphenum
->glyphs
[g
].num_layers
) {
5121 advance_adj
+= glyphenum
->advances
[g
];
5125 if (glyphenum
->current_layer
== glyphenum
->glyphs
[g
].layer
&& (!got_palette_index
|| colorrun
->paletteIndex
== glyphenum
->glyphs
[g
].palette_index
)) {
5126 UINT32 index
= colorrun
->glyphRun
.glyphCount
;
5127 if (!got_palette_index
) {
5128 colorrun
->paletteIndex
= glyphenum
->glyphs
[g
].palette_index
;
5129 /* use foreground color or request one from the font */
5130 memset(&colorrun
->runColor
, 0, sizeof(colorrun
->runColor
));
5131 if (colorrun
->paletteIndex
!= 0xffff) {
5132 HRESULT hr
= IDWriteFontFace3_GetPaletteEntries(glyphenum
->fontface
, glyphenum
->palette
, colorrun
->paletteIndex
,
5133 1, &colorrun
->runColor
);
5135 WARN("failed to get palette entry, fontface %p, palette %u, index %u, 0x%08x\n", glyphenum
->fontface
,
5136 glyphenum
->palette
, colorrun
->paletteIndex
, hr
);
5138 /* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
5139 colorrun
->baselineOriginX
= glyphenum
->origin_x
+ get_glyph_origin(glyphenum
, g
);
5140 colorrun
->baselineOriginY
= glyphenum
->origin_y
;
5141 glyphenum
->color_advances
[index
] = glyphenum
->advances
[g
];
5142 got_palette_index
= TRUE
;
5145 glyphenum
->glyphindices
[index
] = glyphenum
->glyphs
[g
].glyph
;
5146 /* offsets are relative to glyph origin, nothing to fix up */
5147 if (glyphenum
->color_offsets
)
5148 glyphenum
->color_offsets
[index
] = glyphenum
->offsets
[g
];
5149 opentype_colr_next_glyph(glyphenum
->colr
.data
, glyphenum
->glyphs
+ g
);
5151 glyphenum
->color_advances
[index
-1] += advance_adj
;
5152 colorrun
->glyphRun
.glyphCount
++;
5156 advance_adj
+= glyphenum
->advances
[g
];
5159 /* reset last advance */
5160 if (colorrun
->glyphRun
.glyphCount
)
5161 glyphenum
->color_advances
[colorrun
->glyphRun
.glyphCount
-1] = 0.0f
;
5163 return colorrun
->glyphRun
.glyphCount
> 0;
5166 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
5168 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5170 TRACE("(%p)->(%p)\n", This
, has_run
);
5174 This
->colorrun
.glyphRun
.glyphCount
= 0;
5175 while (This
->current_layer
< This
->max_layer_num
) {
5176 if (colorglyphenum_build_color_run(This
))
5179 This
->current_layer
++;
5182 *has_run
= This
->colorrun
.glyphRun
.glyphCount
> 0;
5187 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
5189 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
5191 TRACE("(%p)->(%p)\n", This
, run
);
5193 if (This
->colorrun
.glyphRun
.glyphCount
== 0) {
5195 return E_NOT_VALID_STATE
;
5198 *run
= &This
->colorrun
;
5202 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
5203 colorglyphenum_QueryInterface
,
5204 colorglyphenum_AddRef
,
5205 colorglyphenum_Release
,
5206 colorglyphenum_MoveNext
,
5207 colorglyphenum_GetCurrentRun
5210 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
5211 DWRITE_MEASURING_MODE measuring_mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
5213 struct dwrite_colorglyphenum
*colorglyphenum
;
5214 BOOL colorfont
, has_colored_glyph
;
5215 IDWriteFontFace3
*fontface3
;
5221 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace3
, (void**)&fontface3
);
5223 WARN("failed to get IDWriteFontFace3, 0x%08x\n", hr
);
5227 colorfont
= IDWriteFontFace3_IsColorFont(fontface3
) && IDWriteFontFace3_GetColorPaletteCount(fontface3
) > palette
;
5229 hr
= DWRITE_E_NOCOLOR
;
5233 colorglyphenum
= heap_alloc_zero(sizeof(*colorglyphenum
));
5234 if (!colorglyphenum
) {
5239 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
5240 colorglyphenum
->ref
= 1;
5241 colorglyphenum
->origin_x
= originX
;
5242 colorglyphenum
->origin_y
= originY
;
5243 colorglyphenum
->fontface
= fontface3
;
5244 colorglyphenum
->glyphs
= NULL
;
5245 colorglyphenum
->run
= *run
;
5246 colorglyphenum
->run
.glyphIndices
= NULL
;
5247 colorglyphenum
->run
.glyphAdvances
= NULL
;
5248 colorglyphenum
->run
.glyphOffsets
= NULL
;
5249 colorglyphenum
->palette
= palette
;
5250 memset(&colorglyphenum
->colr
, 0, sizeof(colorglyphenum
->colr
));
5251 colorglyphenum
->colr
.exists
= TRUE
;
5252 get_fontface_table(fontface3
, MS_COLR_TAG
, &colorglyphenum
->colr
);
5253 colorglyphenum
->current_layer
= 0;
5254 colorglyphenum
->max_layer_num
= 0;
5256 colorglyphenum
->glyphs
= heap_alloc_zero(run
->glyphCount
* sizeof(*colorglyphenum
->glyphs
));
5258 has_colored_glyph
= FALSE
;
5259 colorglyphenum
->has_regular_glyphs
= FALSE
;
5260 for (i
= 0; i
< run
->glyphCount
; i
++) {
5261 if (opentype_get_colr_glyph(colorglyphenum
->colr
.data
, run
->glyphIndices
[i
], colorglyphenum
->glyphs
+ i
) == S_OK
) {
5262 colorglyphenum
->max_layer_num
= max(colorglyphenum
->max_layer_num
, colorglyphenum
->glyphs
[i
].num_layers
);
5263 has_colored_glyph
= TRUE
;
5265 if (colorglyphenum
->glyphs
[i
].num_layers
== 0)
5266 colorglyphenum
->has_regular_glyphs
= TRUE
;
5269 /* It's acceptable to have a subset of glyphs mapped to color layers, for regular runs client
5270 is supposed to proceed normally, like if font had no color info at all. */
5271 if (!has_colored_glyph
) {
5272 IDWriteColorGlyphRunEnumerator_Release(&colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
);
5273 return DWRITE_E_NOCOLOR
;
5276 colorglyphenum
->advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5277 colorglyphenum
->color_advances
= heap_alloc(run
->glyphCount
* sizeof(FLOAT
));
5278 colorglyphenum
->glyphindices
= heap_alloc(run
->glyphCount
* sizeof(UINT16
));
5279 if (run
->glyphOffsets
) {
5280 colorglyphenum
->offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->offsets
));
5281 colorglyphenum
->color_offsets
= heap_alloc(run
->glyphCount
* sizeof(*colorglyphenum
->color_offsets
));
5282 memcpy(colorglyphenum
->offsets
, run
->glyphOffsets
, run
->glyphCount
* sizeof(*run
->glyphOffsets
));
5285 colorglyphenum
->colorrun
.glyphRun
.glyphIndices
= colorglyphenum
->glyphindices
;
5286 colorglyphenum
->colorrun
.glyphRun
.glyphAdvances
= colorglyphenum
->color_advances
;
5287 colorglyphenum
->colorrun
.glyphRun
.glyphOffsets
= colorglyphenum
->color_offsets
;
5288 colorglyphenum
->colorrun
.glyphRunDescription
= NULL
; /* FIXME */
5290 if (run
->glyphAdvances
)
5291 memcpy(colorglyphenum
->advances
, run
->glyphAdvances
, run
->glyphCount
* sizeof(FLOAT
));
5293 DWRITE_FONT_METRICS metrics
;
5295 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
5296 for (i
= 0; i
< run
->glyphCount
; i
++) {
5300 switch (measuring_mode
)
5302 case DWRITE_MEASURING_MODE_NATURAL
:
5303 hr
= IDWriteFontFace3_GetDesignGlyphAdvances(fontface3
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
5306 colorglyphenum
->advances
[i
] = get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
);
5308 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
5309 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
5310 hr
= IDWriteFontFace3_GetGdiCompatibleGlyphAdvances(fontface3
, run
->fontEmSize
, 1.0f
, transform
,
5311 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
5313 colorglyphenum
->advances
[i
] = 0.0f
;
5315 colorglyphenum
->advances
[i
] = floorf(a
* run
->fontEmSize
/ metrics
.designUnitsPerEm
+ 0.5f
);
5323 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;
5327 IDWriteFontFace3_Release(fontface3
);
5331 /* IDWriteFontFaceReference */
5332 static HRESULT WINAPI
fontfacereference_QueryInterface(IDWriteFontFaceReference
*iface
, REFIID riid
, void **obj
)
5334 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5336 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
5338 if (IsEqualIID(riid
, &IID_IDWriteFontFaceReference
) || IsEqualIID(riid
, &IID_IUnknown
)) {
5340 IDWriteFontFaceReference_AddRef(iface
);
5346 return E_NOINTERFACE
;
5349 static ULONG WINAPI
fontfacereference_AddRef(IDWriteFontFaceReference
*iface
)
5351 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5352 ULONG ref
= InterlockedIncrement(&This
->ref
);
5353 TRACE("(%p)->(%u)\n", This
, ref
);
5357 static ULONG WINAPI
fontfacereference_Release(IDWriteFontFaceReference
*iface
)
5359 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5360 ULONG ref
= InterlockedDecrement(&This
->ref
);
5362 TRACE("(%p)->(%u)\n", This
, ref
);
5365 IDWriteFontFile_Release(This
->file
);
5366 IDWriteFactory3_Release(This
->factory
);
5373 static HRESULT WINAPI
fontfacereference_CreateFontFace(IDWriteFontFaceReference
*iface
, IDWriteFontFace3
**fontface
)
5375 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5377 TRACE("(%p)->(%p)\n", This
, fontface
);
5379 return IDWriteFontFaceReference_CreateFontFaceWithSimulations(iface
, This
->simulations
, fontface
);
5382 static HRESULT WINAPI
fontfacereference_CreateFontFaceWithSimulations(IDWriteFontFaceReference
*iface
,
5383 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace3
**ret
)
5385 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5386 DWRITE_FONT_FILE_TYPE file_type
;
5387 DWRITE_FONT_FACE_TYPE face_type
;
5388 IDWriteFontFace
*fontface
;
5393 TRACE("(%p)->(%d %p)\n", This
, simulations
, ret
);
5395 hr
= IDWriteFontFile_Analyze(This
->file
, &is_supported
, &file_type
, &face_type
, &face_num
);
5399 hr
= IDWriteFactory3_CreateFontFace(This
->factory
, face_type
, 1, &This
->file
, This
->index
, simulations
, &fontface
);
5400 if (SUCCEEDED(hr
)) {
5401 hr
= IDWriteFontFace_QueryInterface(fontface
, &IID_IDWriteFontFace3
, (void**)ret
);
5402 IDWriteFontFace_Release(fontface
);
5408 static BOOL WINAPI
fontfacereference_Equals(IDWriteFontFaceReference
*iface
, IDWriteFontFaceReference
*ref
)
5410 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5411 IDWriteFontFile
*file
;
5414 TRACE("(%p)->(%p)\n", This
, ref
);
5416 if (FAILED(IDWriteFontFaceReference_GetFontFile(ref
, &file
)))
5419 ret
= is_same_fontfile(This
->file
, file
);
5420 IDWriteFontFile_Release(file
);
5425 static UINT32 WINAPI
fontfacereference_GetFontFaceIndex(IDWriteFontFaceReference
*iface
)
5427 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5429 TRACE("(%p)\n", This
);
5434 static DWRITE_FONT_SIMULATIONS WINAPI
fontfacereference_GetSimulations(IDWriteFontFaceReference
*iface
)
5436 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5438 TRACE("(%p)\n", This
);
5440 return This
->simulations
;
5443 static HRESULT WINAPI
fontfacereference_GetFontFile(IDWriteFontFaceReference
*iface
, IDWriteFontFile
**file
)
5445 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5446 IDWriteFontFileLoader
*loader
;
5451 TRACE("(%p)->(%p)\n", This
, file
);
5453 hr
= IDWriteFontFile_GetReferenceKey(This
->file
, &key
, &key_size
);
5457 hr
= IDWriteFontFile_GetLoader(This
->file
, &loader
);
5461 hr
= IDWriteFactory3_CreateCustomFontFileReference(This
->factory
, key
, key_size
, loader
, file
);
5462 IDWriteFontFileLoader_Release(loader
);
5467 static UINT64 WINAPI
fontfacereference_GetLocalFileSize(IDWriteFontFaceReference
*iface
)
5469 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5471 FIXME("(%p): stub\n", This
);
5476 static UINT64 WINAPI
fontfacereference_GetFileSize(IDWriteFontFaceReference
*iface
)
5478 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5480 FIXME("(%p): stub\n", This
);
5485 static HRESULT WINAPI
fontfacereference_GetFileTime(IDWriteFontFaceReference
*iface
, FILETIME
*writetime
)
5487 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5489 FIXME("(%p)->(%p): stub\n", This
, writetime
);
5494 static DWRITE_LOCALITY WINAPI
fontfacereference_GetLocality(IDWriteFontFaceReference
*iface
)
5496 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5498 FIXME("(%p): stub\n", This
);
5500 return DWRITE_LOCALITY_LOCAL
;
5503 static HRESULT WINAPI
fontfacereference_EnqueueFontDownloadRequest(IDWriteFontFaceReference
*iface
)
5505 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5507 FIXME("(%p): stub\n", This
);
5512 static HRESULT WINAPI
fontfacereference_EnqueueCharacterDownloadRequest(IDWriteFontFaceReference
*iface
, WCHAR
const *chars
,
5515 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5517 FIXME("(%p)->(%s:%u): stub\n", This
, debugstr_wn(chars
, count
), count
);
5522 static HRESULT WINAPI
fontfacereference_EnqueueGlyphDownloadRequest(IDWriteFontFaceReference
*iface
, UINT16
const *glyphs
,
5525 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5527 FIXME("(%p)->(%p %u): stub\n", This
, glyphs
, count
);
5532 static HRESULT WINAPI
fontfacereference_EnqueueFileFragmentDownloadRequest(IDWriteFontFaceReference
*iface
,
5533 UINT64 offset
, UINT64 size
)
5535 struct dwrite_fontfacereference
*This
= impl_from_IDWriteFontFaceReference(iface
);
5537 FIXME("(%p)->(%s %s): stub\n", This
, wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(size
));
5542 static const IDWriteFontFaceReferenceVtbl fontfacereferencevtbl
= {
5543 fontfacereference_QueryInterface
,
5544 fontfacereference_AddRef
,
5545 fontfacereference_Release
,
5546 fontfacereference_CreateFontFace
,
5547 fontfacereference_CreateFontFaceWithSimulations
,
5548 fontfacereference_Equals
,
5549 fontfacereference_GetFontFaceIndex
,
5550 fontfacereference_GetSimulations
,
5551 fontfacereference_GetFontFile
,
5552 fontfacereference_GetLocalFileSize
,
5553 fontfacereference_GetFileSize
,
5554 fontfacereference_GetFileTime
,
5555 fontfacereference_GetLocality
,
5556 fontfacereference_EnqueueFontDownloadRequest
,
5557 fontfacereference_EnqueueCharacterDownloadRequest
,
5558 fontfacereference_EnqueueGlyphDownloadRequest
,
5559 fontfacereference_EnqueueFileFragmentDownloadRequest
5562 HRESULT
create_fontfacereference(IDWriteFactory3
*factory
, IDWriteFontFile
*file
, UINT32 index
,
5563 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFaceReference
**ret
)
5565 struct dwrite_fontfacereference
*ref
;
5569 ref
= heap_alloc(sizeof(*ref
));
5571 return E_OUTOFMEMORY
;
5573 ref
->IDWriteFontFaceReference_iface
.lpVtbl
= &fontfacereferencevtbl
;
5576 ref
->factory
= factory
;
5577 IDWriteFactory3_AddRef(ref
->factory
);
5579 IDWriteFontFile_AddRef(ref
->file
);
5581 ref
->simulations
= simulations
;
5582 *ret
= &ref
->IDWriteFontFaceReference_iface
;