4 * Copyright 2011 Huw Davies
5 * Copyright 2012, 2014-2015 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
);
31 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
32 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
33 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
34 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
35 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
36 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
37 #define MS_CPAL_TAG DWRITE_MAKE_OPENTYPE_TAG('C','P','A','L')
39 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
41 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
42 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
43 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
45 static const WCHAR extraW
[] = {'e','x','t','r','a',0};
46 static const WCHAR ultraW
[] = {'u','l','t','r','a',0};
47 static const WCHAR semiW
[] = {'s','e','m','i',0};
48 static const WCHAR extW
[] = {'e','x','t',0};
49 static const WCHAR thinW
[] = {'t','h','i','n',0};
50 static const WCHAR lightW
[] = {'l','i','g','h','t',0};
51 static const WCHAR mediumW
[] = {'m','e','d','i','u','m',0};
52 static const WCHAR blackW
[] = {'b','l','a','c','k',0};
53 static const WCHAR condensedW
[] = {'c','o','n','d','e','n','s','e','d',0};
54 static const WCHAR expandedW
[] = {'e','x','p','a','n','d','e','d',0};
55 static const WCHAR italicW
[] = {'i','t','a','l','i','c',0};
56 static const WCHAR boldW
[] = {'B','o','l','d',0};
57 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
58 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
59 static const WCHAR demiW
[] = {'d','e','m','i',0};
60 static const WCHAR spaceW
[] = {' ',0};
61 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
63 struct dwrite_font_propvec
{
69 struct dwrite_font_data
{
72 DWRITE_FONT_STYLE style
;
73 DWRITE_FONT_STRETCH stretch
;
74 DWRITE_FONT_WEIGHT weight
;
76 struct dwrite_font_propvec propvec
;
78 DWRITE_FONT_METRICS1 metrics
;
79 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
80 IDWriteLocalizedStrings
*names
;
82 /* data needed to create fontface instance */
83 IDWriteFactory2
*factory
;
84 DWRITE_FONT_FACE_TYPE face_type
;
85 IDWriteFontFile
*file
;
92 /* used to mark font as tested when scanning for simulation candidate */
93 BOOL bold_sim_tested
: 1;
94 BOOL oblique_sim_tested
: 1;
97 struct dwrite_fontlist
{
98 IDWriteFontList IDWriteFontList_iface
;
101 IDWriteFontFamily
*family
;
102 struct dwrite_font_data
**fonts
;
106 struct dwrite_fontfamily_data
{
109 IDWriteLocalizedStrings
*familyname
;
111 struct dwrite_font_data
**fonts
;
114 BOOL has_normal_face
: 1;
115 BOOL has_oblique_face
: 1;
116 BOOL has_italic_face
: 1;
119 struct dwrite_fontcollection
{
120 IDWriteFontCollection IDWriteFontCollection_iface
;
123 struct dwrite_fontfamily_data
**family_data
;
129 struct dwrite_fontfamily
{
130 IDWriteFontFamily IDWriteFontFamily_iface
;
133 struct dwrite_fontfamily_data
*data
;
135 IDWriteFontCollection
* collection
;
139 IDWriteFont2 IDWriteFont2_iface
;
142 IDWriteFontFamily
*family
;
144 DWRITE_FONT_STYLE style
;
145 struct dwrite_font_data
*data
;
148 struct dwrite_fonttable
{
155 enum runanalysis_flags
{
156 RUNANALYSIS_BOUNDS_READY
= 1 << 0,
157 RUNANALYSIS_BITMAP_READY
= 1 << 1,
158 RUNANALYSIS_USE_TRANSFORM
= 1 << 2
161 struct dwrite_glyphrunanalysis
{
162 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
165 DWRITE_RENDERING_MODE rendering_mode
;
166 DWRITE_GLYPH_RUN run
; /* glyphAdvances and glyphOffsets are not used */
171 D2D_POINT_2F
*advances
;
172 D2D_POINT_2F
*advanceoffsets
;
173 D2D_POINT_2F
*ascenderoffsets
;
180 struct dwrite_colorglyphenum
{
181 IDWriteColorGlyphRunEnumerator IDWriteColorGlyphRunEnumerator_iface
;
185 #define GLYPH_BLOCK_SHIFT 8
186 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
187 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
188 #define GLYPH_MAX 65536
190 struct dwrite_fontface
{
191 IDWriteFontFace2 IDWriteFontFace2_iface
;
194 IDWriteFontFileStream
**streams
;
195 IDWriteFontFile
**files
;
200 DWRITE_FONT_FACE_TYPE type
;
201 DWRITE_FONT_METRICS1 metrics
;
202 DWRITE_CARET_METRICS caret
;
206 struct dwrite_fonttable cmap
;
207 struct dwrite_fonttable vdmx
;
208 struct dwrite_fonttable gasp
;
209 struct dwrite_fonttable cpal
;
210 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
213 struct dwrite_fontfile
{
214 IDWriteFontFile IDWriteFontFile_iface
;
217 IDWriteFontFileLoader
*loader
;
220 IDWriteFontFileStream
*stream
;
223 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace2(IDWriteFontFace2
*iface
)
225 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace2_iface
);
228 static inline struct dwrite_font
*impl_from_IDWriteFont2(IDWriteFont2
*iface
)
230 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont2_iface
);
233 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
235 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
238 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily(IDWriteFontFamily
*iface
)
240 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily_iface
);
243 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
245 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
248 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
250 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
253 static inline struct dwrite_colorglyphenum
*impl_from_IDWriteColorGlyphRunEnumerator(IDWriteColorGlyphRunEnumerator
*iface
)
255 return CONTAINING_RECORD(iface
, struct dwrite_colorglyphenum
, IDWriteColorGlyphRunEnumerator_iface
);
258 static inline struct dwrite_fontlist
*impl_from_IDWriteFontList(IDWriteFontList
*iface
)
260 return CONTAINING_RECORD(iface
, struct dwrite_fontlist
, IDWriteFontList_iface
);
263 static inline const char *debugstr_tag(UINT32 tag
)
265 return debugstr_an((char*)&tag
, 4);
268 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
270 static const DWRITE_GLYPH_METRICS nil
;
271 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
273 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
274 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
278 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
280 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
283 /* start new block */
284 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
286 return E_OUTOFMEMORY
;
289 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
293 static void* get_fontface_table(struct dwrite_fontface
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
297 if (table
->data
|| !table
->exists
)
300 table
->exists
= FALSE
;
301 hr
= IDWriteFontFace2_TryGetFontTable(&fontface
->IDWriteFontFace2_iface
, tag
, (const void**)&table
->data
,
302 &table
->size
, &table
->context
, &table
->exists
);
303 if (FAILED(hr
) || !table
->exists
) {
304 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
311 static void init_font_prop_vec(DWRITE_FONT_WEIGHT weight
, DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
,
312 struct dwrite_font_propvec
*vec
)
314 vec
->stretch
= ((INT32
)stretch
- DWRITE_FONT_STRETCH_NORMAL
) * 11.0f
;
315 vec
->style
= style
* 7.0f
;
316 vec
->weight
= ((INT32
)weight
- DWRITE_FONT_WEIGHT_NORMAL
) / 100.0f
* 5.0f
;
319 static FLOAT
get_font_prop_vec_distance(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
321 return powf(left
->stretch
- right
->stretch
, 2) + powf(left
->style
- right
->style
, 2) + powf(left
->weight
- right
->weight
, 2);
324 static FLOAT
get_font_prop_vec_dotproduct(const struct dwrite_font_propvec
*left
, const struct dwrite_font_propvec
*right
)
326 return left
->stretch
* right
->stretch
+ left
->style
* right
->style
+ left
->weight
* right
->weight
;
329 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
331 return get_fontface_table(fontface
, MS_CMAP_TAG
, &fontface
->cmap
);
334 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
336 return get_fontface_table(fontface
, MS_VDMX_TAG
, &fontface
->vdmx
);
339 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
341 void *ptr
= get_fontface_table(fontface
, MS_GASP_TAG
, &fontface
->gasp
);
342 *size
= fontface
->gasp
.size
;
346 static inline void* get_fontface_cpal(struct dwrite_fontface
*fontface
)
348 return get_fontface_table(fontface
, MS_CPAL_TAG
, &fontface
->cpal
);
351 static void release_font_data(struct dwrite_font_data
*data
)
355 if (InterlockedDecrement(&data
->ref
) > 0)
358 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
359 if (data
->info_strings
[i
])
360 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
362 IDWriteLocalizedStrings_Release(data
->names
);
364 IDWriteFontFile_Release(data
->file
);
365 IDWriteFactory2_Release(data
->factory
);
366 heap_free(data
->facename
);
370 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
374 if (InterlockedDecrement(&data
->ref
) > 0)
377 for (i
= 0; i
< data
->font_count
; i
++)
378 release_font_data(data
->fonts
[i
]);
379 heap_free(data
->fonts
);
380 IDWriteLocalizedStrings_Release(data
->familyname
);
384 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace2
*iface
, REFIID riid
, void **obj
)
386 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
388 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
390 if (IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
391 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
392 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
393 IsEqualIID(riid
, &IID_IUnknown
))
396 IDWriteFontFace2_AddRef(iface
);
401 return E_NOINTERFACE
;
404 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace2
*iface
)
406 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
407 ULONG ref
= InterlockedIncrement(&This
->ref
);
408 TRACE("(%p)->(%d)\n", This
, ref
);
412 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace2
*iface
)
414 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
415 ULONG ref
= InterlockedDecrement(&This
->ref
);
417 TRACE("(%p)->(%d)\n", This
, ref
);
422 if (This
->cmap
.context
)
423 IDWriteFontFace2_ReleaseFontTable(iface
, This
->cmap
.context
);
424 if (This
->vdmx
.context
)
425 IDWriteFontFace2_ReleaseFontTable(iface
, This
->vdmx
.context
);
426 if (This
->gasp
.context
)
427 IDWriteFontFace2_ReleaseFontTable(iface
, This
->gasp
.context
);
428 if (This
->cpal
.context
)
429 IDWriteFontFace2_ReleaseFontTable(iface
, This
->cpal
.context
);
430 for (i
= 0; i
< This
->file_count
; i
++) {
431 if (This
->streams
[i
])
432 IDWriteFontFileStream_Release(This
->streams
[i
]);
434 IDWriteFontFile_Release(This
->files
[i
]);
436 heap_free(This
->streams
);
437 heap_free(This
->files
);
439 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
440 heap_free(This
->glyphs
[i
]);
442 freetype_notify_cacheremove(iface
);
449 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace2
*iface
)
451 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
452 TRACE("(%p)\n", This
);
456 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace2
*iface
, UINT32
*number_of_files
,
457 IDWriteFontFile
**fontfiles
)
459 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
462 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
463 if (fontfiles
== NULL
)
465 *number_of_files
= This
->file_count
;
468 if (*number_of_files
< This
->file_count
)
471 for (i
= 0; i
< This
->file_count
; i
++)
473 IDWriteFontFile_AddRef(This
->files
[i
]);
474 fontfiles
[i
] = This
->files
[i
];
480 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace2
*iface
)
482 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
483 TRACE("(%p)\n", This
);
487 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace2
*iface
)
489 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
490 TRACE("(%p)\n", This
);
491 return This
->simulations
;
494 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace2
*iface
)
496 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
497 TRACE("(%p)\n", This
);
498 return This
->is_symbol
;
501 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS
*metrics
)
503 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
504 TRACE("(%p)->(%p)\n", This
, metrics
);
505 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
508 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace2
*iface
)
510 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
511 TRACE("(%p)\n", This
);
512 return freetype_get_glyphcount(iface
);
515 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2
*iface
,
516 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
518 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
522 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
528 FIXME("sideways metrics are not supported.\n");
530 for (i
= 0; i
< glyph_count
; i
++) {
531 DWRITE_GLYPH_METRICS metrics
;
533 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
535 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
536 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
546 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace2
*iface
, UINT32
const *codepoints
,
547 UINT32 count
, UINT16
*glyph_indices
)
549 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
552 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
558 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
562 for (i
= 0; i
< count
; i
++)
563 glyph_indices
[i
] = freetype_get_glyphindex(iface
, codepoints
[i
], This
->charmap
);
568 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace2
*iface
, UINT32 table_tag
,
569 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
571 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
573 TRACE("(%p)->(%s %p %p %p %p)\n", This
, debugstr_tag(table_tag
), table_data
, table_size
, context
, exists
);
575 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
578 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace2
*iface
, void *table_context
)
580 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
582 TRACE("(%p)->(%p)\n", This
, table_context
);
584 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
587 HRESULT
new_glyph_outline(UINT32 count
, struct glyph_outline
**ret
)
589 struct glyph_outline
*outline
;
590 D2D1_POINT_2F
*points
;
595 outline
= heap_alloc(sizeof(*outline
));
597 return E_OUTOFMEMORY
;
599 points
= heap_alloc(count
*sizeof(D2D1_POINT_2F
));
600 tags
= heap_alloc_zero(count
*sizeof(UINT8
));
601 if (!points
|| !tags
) {
605 return E_OUTOFMEMORY
;
608 outline
->points
= points
;
609 outline
->tags
= tags
;
610 outline
->count
= count
;
611 outline
->advance
= 0.0;
617 static void free_glyph_outline(struct glyph_outline
*outline
)
619 heap_free(outline
->points
);
620 heap_free(outline
->tags
);
624 static void report_glyph_outline(const struct glyph_outline
*outline
, IDWriteGeometrySink
*sink
)
628 for (p
= 0; p
< outline
->count
; p
++) {
629 if (outline
->tags
[p
] & OUTLINE_POINT_START
) {
630 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, outline
->points
[p
], D2D1_FIGURE_BEGIN_FILLED
);
634 if (outline
->tags
[p
] & OUTLINE_POINT_LINE
)
635 ID2D1SimplifiedGeometrySink_AddLines(sink
, outline
->points
+p
, 1);
636 else if (outline
->tags
[p
] & OUTLINE_POINT_BEZIER
) {
637 static const UINT16 segment_length
= 3;
638 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, (D2D1_BEZIER_SEGMENT
*)&outline
->points
[p
], 1);
639 p
+= segment_length
- 1;
642 if (outline
->tags
[p
] & OUTLINE_POINT_END
)
643 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
647 static inline void translate_glyph_outline(struct glyph_outline
*outline
, FLOAT xoffset
, FLOAT yoffset
)
651 for (p
= 0; p
< outline
->count
; p
++) {
652 outline
->points
[p
].x
+= xoffset
;
653 outline
->points
[p
].y
+= yoffset
;
657 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace2
*iface
, FLOAT emSize
,
658 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
659 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
661 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
666 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
667 count
, is_sideways
, is_rtl
, sink
);
669 if (!glyphs
|| !sink
)
673 FIXME("sideways mode is not supported.\n");
676 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
678 for (g
= 0; g
< count
; g
++) {
679 FLOAT xoffset
= 0.0, yoffset
= 0.0;
680 struct glyph_outline
*outline
;
682 /* FIXME: cache outlines */
684 hr
= freetype_get_glyph_outline(iface
, emSize
, glyphs
[g
], This
->simulations
, &outline
);
688 /* glyph offsets act as current glyph adjustment */
690 xoffset
+= is_rtl
? -offsets
[g
].advanceOffset
: offsets
[g
].advanceOffset
;
691 yoffset
-= offsets
[g
].ascenderOffset
;
695 advance
= is_rtl
? -outline
->advance
: 0.0;
698 translate_glyph_outline(outline
, xoffset
, yoffset
);
700 /* update advance to next glyph */
702 advance
+= is_rtl
? -advances
[g
] : advances
[g
];
704 advance
+= is_rtl
? -outline
->advance
: outline
->advance
;
706 report_glyph_outline(outline
, sink
);
707 free_glyph_outline(outline
);
713 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
714 FLOAT ppem
, WORD gasp
)
716 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
720 case DWRITE_MEASURING_MODE_NATURAL
:
722 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
723 mode
= DWRITE_RENDERING_MODE_NATURAL
;
725 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
728 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
729 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
731 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
732 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
741 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
742 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
744 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
749 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
752 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
756 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
757 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
760 ppem
= emSize
* ppdip
;
762 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
763 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
767 ptr
= get_fontface_gasp(This
, &size
);
768 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
769 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
773 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
774 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
776 DWRITE_FONT_METRICS1 metrics1
;
777 HRESULT hr
= IDWriteFontFace2_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
778 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
782 static inline int round_metric(FLOAT metric
)
784 return (int)floorf(metric
+ 0.5f
);
787 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT ppdip
,
788 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
789 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
791 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
792 DWRITE_MEASURING_MODE mode
;
797 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
798 glyph_count
, metrics
, is_sideways
);
800 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
801 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
803 size
= emSize
* ppdip
;
804 scale
= size
/ This
->metrics
.designUnitsPerEm
;
805 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
807 for (i
= 0; i
< glyph_count
; i
++) {
808 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
809 DWRITE_GLYPH_METRICS design
;
811 hr
= IDWriteFontFace2_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
815 ret
->advanceWidth
= freetype_get_glyph_advance(iface
, size
, glyphs
[i
], mode
);
816 ret
->advanceWidth
= round_metric(ret
->advanceWidth
* This
->metrics
.designUnitsPerEm
/ size
);
818 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
819 SCALE_METRIC(leftSideBearing
);
820 SCALE_METRIC(rightSideBearing
);
821 SCALE_METRIC(topSideBearing
);
822 SCALE_METRIC(advanceHeight
);
823 SCALE_METRIC(bottomSideBearing
);
824 SCALE_METRIC(verticalOriginY
);
831 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
833 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
834 TRACE("(%p)->(%p)\n", This
, metrics
);
835 *metrics
= This
->metrics
;
838 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
839 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
841 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
842 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
843 UINT16 ascent
, descent
;
846 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
848 if (em_size
<= 0.0 || pixels_per_dip
<= 0.0) {
849 memset(metrics
, 0, sizeof(*metrics
));
853 em_size
*= pixels_per_dip
;
854 if (m
&& m
->m22
!= 0.0)
855 em_size
*= fabs(m
->m22
);
857 scale
= em_size
/ design
->designUnitsPerEm
;
858 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
859 ascent
= round_metric(design
->ascent
* scale
);
860 descent
= round_metric(design
->descent
* scale
);
863 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
864 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
865 metrics
->ascent
= round_metric(ascent
/ scale
);
866 metrics
->descent
= round_metric(descent
/ scale
);
868 SCALE_METRIC(lineGap
);
869 SCALE_METRIC(capHeight
);
870 SCALE_METRIC(xHeight
);
871 SCALE_METRIC(underlinePosition
);
872 SCALE_METRIC(underlineThickness
);
873 SCALE_METRIC(strikethroughPosition
);
874 SCALE_METRIC(strikethroughThickness
);
875 SCALE_METRIC(glyphBoxLeft
);
876 SCALE_METRIC(glyphBoxTop
);
877 SCALE_METRIC(glyphBoxRight
);
878 SCALE_METRIC(glyphBoxBottom
);
879 SCALE_METRIC(subscriptPositionX
);
880 SCALE_METRIC(subscriptPositionY
);
881 SCALE_METRIC(subscriptSizeX
);
882 SCALE_METRIC(subscriptSizeY
);
883 SCALE_METRIC(superscriptPositionX
);
884 SCALE_METRIC(superscriptPositionY
);
885 SCALE_METRIC(superscriptSizeX
);
886 SCALE_METRIC(superscriptSizeY
);
888 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
894 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace2
*iface
, DWRITE_CARET_METRICS
*metrics
)
896 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
897 TRACE("(%p)->(%p)\n", This
, metrics
);
898 *metrics
= This
->caret
;
901 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace2
*iface
, UINT32 max_count
,
902 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
904 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
906 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
909 if (max_count
&& !ranges
)
912 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
915 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace2
*iface
)
917 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
918 TRACE("(%p)\n", This
);
919 return freetype_is_monospaced(iface
);
922 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2
*iface
,
923 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
925 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
928 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
931 FIXME("sideways mode not supported\n");
933 for (i
= 0; i
< glyph_count
; i
++)
934 advances
[i
] = freetype_get_glyph_advance(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], DWRITE_MEASURING_MODE_NATURAL
);
939 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2
*iface
,
940 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
941 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
943 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
944 DWRITE_MEASURING_MODE mode
;
947 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
948 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
950 if (em_size
< 0.0 || ppdip
<= 0.0) {
951 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
956 if (em_size
== 0.0) {
957 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
961 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
962 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
964 mode
= use_gdi_natural
? DWRITE_MEASURING_MODE_GDI_NATURAL
: DWRITE_MEASURING_MODE_GDI_CLASSIC
;
965 for (i
= 0; i
< glyph_count
; i
++) {
966 advances
[i
] = freetype_get_glyph_advance(iface
, em_size
, glyphs
[i
], mode
);
967 advances
[i
] = round_metric(advances
[i
] * This
->metrics
.designUnitsPerEm
/ em_size
);
973 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2
*iface
, UINT32 count
,
974 const UINT16
*indices
, INT32
*adjustments
)
976 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
979 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
981 if (!(indices
|| adjustments
) || !count
)
984 if (!indices
|| count
== 1) {
985 memset(adjustments
, 0, count
*sizeof(INT32
));
989 for (i
= 0; i
< count
-1; i
++)
990 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
991 adjustments
[count
-1] = 0;
996 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace2
*iface
)
998 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
999 TRACE("(%p)\n", This
);
1000 return freetype_has_kerning_pairs(iface
);
1003 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
,
1004 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
1005 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
1007 DWRITE_GRID_FIT_MODE gridfitmode
;
1008 return IDWriteFontFace2_GetRecommendedRenderingMode(iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
1009 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
1012 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2
*iface
, UINT32 glyph_count
,
1013 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
1015 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1016 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
1020 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2
*iface
)
1022 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1023 FIXME("(%p): stub\n", This
);
1027 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace2
*iface
)
1029 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1030 FIXME("(%p): stub\n", This
);
1034 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace2
*iface
)
1036 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1037 TRACE("(%p)\n", This
);
1038 return opentype_get_cpal_palettecount(get_fontface_cpal(This
));
1041 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2
*iface
)
1043 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1044 TRACE("(%p)\n", This
);
1045 return opentype_get_cpal_paletteentrycount(get_fontface_cpal(This
));
1048 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace2
*iface
, UINT32 palette_index
,
1049 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
1051 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1052 TRACE("(%p)->(%u %u %u %p)\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
1053 return opentype_get_cpal_entries(get_fontface_cpal(This
), palette_index
, first_entry_index
, entry_count
, entries
);
1056 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
1057 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
1058 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
1059 DWRITE_GRID_FIT_MODE
*gridfitmode
)
1061 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
1066 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
1067 measuringmode
, params
, renderingmode
, gridfitmode
);
1070 FIXME("transform not supported %s\n", debugstr_matrix(m
));
1073 FIXME("sideways mode not supported\n");
1075 emSize
*= max(dpiX
, dpiY
) / 96.0f
;
1077 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
1078 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
1080 IDWriteRenderingParams2
*params2
;
1083 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
1085 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
1086 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
1087 IDWriteRenderingParams2_Release(params2
);
1090 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
1093 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1095 ptr
= get_fontface_gasp(This
, &size
);
1096 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1098 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1099 if (emSize
>= emthreshold
)
1100 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1102 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1105 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1106 if (emSize
>= emthreshold
)
1107 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1108 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1109 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1111 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1117 static const IDWriteFontFace2Vtbl dwritefontfacevtbl
= {
1118 dwritefontface_QueryInterface
,
1119 dwritefontface_AddRef
,
1120 dwritefontface_Release
,
1121 dwritefontface_GetType
,
1122 dwritefontface_GetFiles
,
1123 dwritefontface_GetIndex
,
1124 dwritefontface_GetSimulations
,
1125 dwritefontface_IsSymbolFont
,
1126 dwritefontface_GetMetrics
,
1127 dwritefontface_GetGlyphCount
,
1128 dwritefontface_GetDesignGlyphMetrics
,
1129 dwritefontface_GetGlyphIndices
,
1130 dwritefontface_TryGetFontTable
,
1131 dwritefontface_ReleaseFontTable
,
1132 dwritefontface_GetGlyphRunOutline
,
1133 dwritefontface_GetRecommendedRenderingMode
,
1134 dwritefontface_GetGdiCompatibleMetrics
,
1135 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1136 dwritefontface1_GetMetrics
,
1137 dwritefontface1_GetGdiCompatibleMetrics
,
1138 dwritefontface1_GetCaretMetrics
,
1139 dwritefontface1_GetUnicodeRanges
,
1140 dwritefontface1_IsMonospacedFont
,
1141 dwritefontface1_GetDesignGlyphAdvances
,
1142 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1143 dwritefontface1_GetKerningPairAdjustments
,
1144 dwritefontface1_HasKerningPairs
,
1145 dwritefontface1_GetRecommendedRenderingMode
,
1146 dwritefontface1_GetVerticalGlyphVariants
,
1147 dwritefontface1_HasVerticalGlyphVariants
,
1148 dwritefontface2_IsColorFont
,
1149 dwritefontface2_GetColorPaletteCount
,
1150 dwritefontface2_GetPaletteEntryCount
,
1151 dwritefontface2_GetPaletteEntries
,
1152 dwritefontface2_GetRecommendedRenderingMode
1155 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace2
**fontface
)
1157 struct dwrite_font_data
*data
= font
->data
;
1158 IDWriteFontFace
*face
;
1163 hr
= IDWriteFactory2_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
1164 data
->face_index
, font
->data
->simulations
, &face
);
1168 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace2
, (void**)fontface
);
1169 IDWriteFontFace_Release(face
);
1174 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont2
*iface
, REFIID riid
, void **obj
)
1176 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1178 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1180 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1181 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1182 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1183 IsEqualIID(riid
, &IID_IUnknown
))
1186 IDWriteFont2_AddRef(iface
);
1191 return E_NOINTERFACE
;
1194 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont2
*iface
)
1196 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1197 ULONG ref
= InterlockedIncrement(&This
->ref
);
1198 TRACE("(%p)->(%d)\n", This
, ref
);
1202 static ULONG WINAPI
dwritefont_Release(IDWriteFont2
*iface
)
1204 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1205 ULONG ref
= InterlockedDecrement(&This
->ref
);
1207 TRACE("(%p)->(%d)\n", This
, ref
);
1210 IDWriteFontFamily_Release(This
->family
);
1211 release_font_data(This
->data
);
1218 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont2
*iface
, IDWriteFontFamily
**family
)
1220 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1221 TRACE("(%p)->(%p)\n", This
, family
);
1223 *family
= This
->family
;
1224 IDWriteFontFamily_AddRef(*family
);
1228 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont2
*iface
)
1230 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1231 TRACE("(%p)\n", This
);
1232 return This
->data
->weight
;
1235 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont2
*iface
)
1237 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1238 TRACE("(%p)\n", This
);
1239 return This
->data
->stretch
;
1242 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont2
*iface
)
1244 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1245 TRACE("(%p)\n", This
);
1249 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont2
*iface
)
1251 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1252 IDWriteFontFace2
*fontface
;
1255 TRACE("(%p)\n", This
);
1257 hr
= get_fontface_from_font(This
, &fontface
);
1261 return IDWriteFontFace2_IsSymbolFont(fontface
);
1264 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont2
*iface
, IDWriteLocalizedStrings
**names
)
1266 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1267 TRACE("(%p)->(%p)\n", This
, names
);
1268 return clone_localizedstring(This
->data
->names
, names
);
1271 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont2
*iface
,
1272 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1274 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1275 struct dwrite_font_data
*data
= This
->data
;
1278 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1283 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1286 if (!data
->info_strings
[stringid
]) {
1287 IDWriteFontFace2
*fontface
;
1288 const void *table_data
;
1293 hr
= get_fontface_from_font(This
, &fontface
);
1297 table_exists
= FALSE
;
1298 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1299 if (FAILED(hr
) || !table_exists
)
1300 WARN("no NAME table found.\n");
1303 hr
= opentype_get_font_info_strings(table_data
, stringid
, &data
->info_strings
[stringid
]);
1304 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1306 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
1310 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1318 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont2
*iface
)
1320 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1321 TRACE("(%p)\n", This
);
1322 return This
->data
->simulations
;
1325 static void WINAPI
dwritefont_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS
*metrics
)
1327 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1329 TRACE("(%p)->(%p)\n", This
, metrics
);
1330 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1333 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont2
*iface
, UINT32 value
, BOOL
*exists
)
1335 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1336 IDWriteFontFace2
*fontface
;
1340 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1344 hr
= get_fontface_from_font(This
, &fontface
);
1349 hr
= IDWriteFontFace2_GetGlyphIndices(fontface
, &value
, 1, &index
);
1353 *exists
= index
!= 0;
1357 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont2
*iface
, IDWriteFontFace
**face
)
1359 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1362 TRACE("(%p)->(%p)\n", This
, face
);
1364 hr
= get_fontface_from_font(This
, (IDWriteFontFace2
**)face
);
1366 IDWriteFontFace_AddRef(*face
);
1371 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1373 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1374 TRACE("(%p)->(%p)\n", This
, metrics
);
1375 *metrics
= This
->data
->metrics
;
1378 static void WINAPI
dwritefont1_GetPanose(IDWriteFont2
*iface
, DWRITE_PANOSE
*panose
)
1380 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1381 TRACE("(%p)->(%p)\n", This
, panose
);
1382 *panose
= This
->data
->panose
;
1385 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont2
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1387 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1388 IDWriteFontFace2
*fontface
;
1391 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1393 hr
= get_fontface_from_font(This
, &fontface
);
1397 return IDWriteFontFace2_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1400 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont2
*iface
)
1402 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1403 IDWriteFontFace2
*fontface
;
1406 TRACE("(%p)\n", This
);
1408 hr
= get_fontface_from_font(This
, &fontface
);
1412 return IDWriteFontFace2_IsMonospacedFont(fontface
);
1415 static BOOL WINAPI
dwritefont2_IsColorFont(IDWriteFont2
*iface
)
1417 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1418 IDWriteFontFace2
*fontface
;
1421 TRACE("(%p)\n", This
);
1423 hr
= get_fontface_from_font(This
, &fontface
);
1427 return IDWriteFontFace2_IsColorFont(fontface
);
1430 static const IDWriteFont2Vtbl dwritefontvtbl
= {
1431 dwritefont_QueryInterface
,
1434 dwritefont_GetFontFamily
,
1435 dwritefont_GetWeight
,
1436 dwritefont_GetStretch
,
1437 dwritefont_GetStyle
,
1438 dwritefont_IsSymbolFont
,
1439 dwritefont_GetFaceNames
,
1440 dwritefont_GetInformationalStrings
,
1441 dwritefont_GetSimulations
,
1442 dwritefont_GetMetrics
,
1443 dwritefont_HasCharacter
,
1444 dwritefont_CreateFontFace
,
1445 dwritefont1_GetMetrics
,
1446 dwritefont1_GetPanose
,
1447 dwritefont1_GetUnicodeRanges
,
1448 dwritefont1_IsMonospacedFont
,
1449 dwritefont2_IsColorFont
1452 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily
*family
, IDWriteFont
**font
)
1454 struct dwrite_font
*This
;
1457 This
= heap_alloc(sizeof(struct dwrite_font
));
1458 if (!This
) return E_OUTOFMEMORY
;
1460 This
->IDWriteFont2_iface
.lpVtbl
= &dwritefontvtbl
;
1462 This
->family
= family
;
1463 IDWriteFontFamily_AddRef(family
);
1464 This
->style
= data
->style
;
1466 InterlockedIncrement(&This
->data
->ref
);
1468 *font
= (IDWriteFont
*)&This
->IDWriteFont2_iface
;
1473 /* IDWriteFontList */
1474 static HRESULT WINAPI
dwritefontlist_QueryInterface(IDWriteFontList
*iface
, REFIID riid
, void **obj
)
1476 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1478 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1480 if (IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1481 IsEqualIID(riid
, &IID_IUnknown
))
1484 IDWriteFontList_AddRef(iface
);
1489 return E_NOINTERFACE
;
1492 static ULONG WINAPI
dwritefontlist_AddRef(IDWriteFontList
*iface
)
1494 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1495 ULONG ref
= InterlockedIncrement(&This
->ref
);
1496 TRACE("(%p)->(%d)\n", This
, ref
);
1500 static ULONG WINAPI
dwritefontlist_Release(IDWriteFontList
*iface
)
1502 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1503 ULONG ref
= InterlockedDecrement(&This
->ref
);
1505 TRACE("(%p)->(%d)\n", This
, ref
);
1510 for (i
= 0; i
< This
->font_count
; i
++)
1511 release_font_data(This
->fonts
[i
]);
1512 IDWriteFontFamily_Release(This
->family
);
1519 static HRESULT WINAPI
dwritefontlist_GetFontCollection(IDWriteFontList
*iface
, IDWriteFontCollection
**collection
)
1521 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1522 return IDWriteFontFamily_GetFontCollection(This
->family
, collection
);
1525 static UINT32 WINAPI
dwritefontlist_GetFontCount(IDWriteFontList
*iface
)
1527 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1528 TRACE("(%p)\n", This
);
1529 return This
->font_count
;
1532 static HRESULT WINAPI
dwritefontlist_GetFont(IDWriteFontList
*iface
, UINT32 index
, IDWriteFont
**font
)
1534 struct dwrite_fontlist
*This
= impl_from_IDWriteFontList(iface
);
1536 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1540 if (This
->font_count
== 0)
1543 if (index
>= This
->font_count
)
1544 return E_INVALIDARG
;
1546 return create_font(This
->fonts
[index
], This
->family
, font
);
1549 static const IDWriteFontListVtbl dwritefontlistvtbl
= {
1550 dwritefontlist_QueryInterface
,
1551 dwritefontlist_AddRef
,
1552 dwritefontlist_Release
,
1553 dwritefontlist_GetFontCollection
,
1554 dwritefontlist_GetFontCount
,
1555 dwritefontlist_GetFont
1558 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily
*iface
, REFIID riid
, void **obj
)
1560 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1561 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1563 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1564 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1565 IsEqualIID(riid
, &IID_IDWriteFontFamily
))
1568 IDWriteFontFamily_AddRef(iface
);
1573 return E_NOINTERFACE
;
1576 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily
*iface
)
1578 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1579 ULONG ref
= InterlockedIncrement(&This
->ref
);
1580 TRACE("(%p)->(%d)\n", This
, ref
);
1584 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily
*iface
)
1586 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1587 ULONG ref
= InterlockedDecrement(&This
->ref
);
1589 TRACE("(%p)->(%d)\n", This
, ref
);
1593 IDWriteFontCollection_Release(This
->collection
);
1594 release_fontfamily_data(This
->data
);
1601 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily
*iface
, IDWriteFontCollection
**collection
)
1603 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1604 TRACE("(%p)->(%p)\n", This
, collection
);
1606 *collection
= This
->collection
;
1607 IDWriteFontCollection_AddRef(This
->collection
);
1611 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily
*iface
)
1613 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1614 TRACE("(%p)\n", This
);
1615 return This
->data
->font_count
;
1618 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily
*iface
, UINT32 index
, IDWriteFont
**font
)
1620 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1622 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1626 if (This
->data
->font_count
== 0)
1629 if (index
>= This
->data
->font_count
)
1630 return E_INVALIDARG
;
1632 return create_font(This
->data
->fonts
[index
], iface
, font
);
1635 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily
*iface
, IDWriteLocalizedStrings
**names
)
1637 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1638 return clone_localizedstring(This
->data
->familyname
, names
);
1641 static BOOL
is_better_font_match(const struct dwrite_font_propvec
*next
, const struct dwrite_font_propvec
*cur
,
1642 const struct dwrite_font_propvec
*req
)
1644 FLOAT cur_to_req
= get_font_prop_vec_distance(cur
, req
);
1645 FLOAT next_to_req
= get_font_prop_vec_distance(next
, req
);
1646 FLOAT cur_req_prod
, next_req_prod
;
1648 if (next_to_req
< cur_to_req
)
1651 if (next_to_req
> cur_to_req
)
1654 cur_req_prod
= get_font_prop_vec_dotproduct(cur
, req
);
1655 next_req_prod
= get_font_prop_vec_dotproduct(next
, req
);
1657 if (next_req_prod
> cur_req_prod
)
1660 if (next_req_prod
< cur_req_prod
)
1663 if (next
->stretch
> cur
->stretch
)
1665 if (next
->stretch
< cur
->stretch
)
1668 if (next
->style
> cur
->style
)
1670 if (next
->style
< cur
->style
)
1673 if (next
->weight
> cur
->weight
)
1675 if (next
->weight
< cur
->weight
)
1678 /* full match, no reason to prefer new variant */
1682 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1683 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1685 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1686 struct dwrite_font_propvec req
;
1687 struct dwrite_font_data
*match
;
1690 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1692 if (This
->data
->font_count
== 0) {
1694 return DWRITE_E_NOFONT
;
1697 init_font_prop_vec(weight
, stretch
, style
, &req
);
1698 match
= This
->data
->fonts
[0];
1700 for (i
= 1; i
< This
->data
->font_count
; i
++) {
1701 if (is_better_font_match(&This
->data
->fonts
[i
]->propvec
, &match
->propvec
, &req
))
1702 match
= This
->data
->fonts
[i
];
1705 return create_font(match
, iface
, font
);
1708 typedef BOOL (*matching_filter_func
)(const struct dwrite_font_data
*);
1710 static BOOL
is_font_acceptable_for_normal(const struct dwrite_font_data
*font
)
1712 return font
->style
== DWRITE_FONT_STYLE_NORMAL
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1715 static BOOL
is_font_acceptable_for_oblique_italic(const struct dwrite_font_data
*font
)
1717 return font
->style
== DWRITE_FONT_STYLE_OBLIQUE
|| font
->style
== DWRITE_FONT_STYLE_ITALIC
;
1720 static void matchingfonts_sort(struct dwrite_fontlist
*fonts
, const struct dwrite_font_propvec
*req
)
1722 UINT32 b
= fonts
->font_count
- 1, j
, t
;
1727 for (j
= 0; j
< b
; j
++) {
1728 if (is_better_font_match(&fonts
->fonts
[j
+1]->propvec
, &fonts
->fonts
[j
]->propvec
, req
)) {
1729 struct dwrite_font_data
*s
= fonts
->fonts
[j
];
1730 fonts
->fonts
[j
] = fonts
->fonts
[j
+1];
1731 fonts
->fonts
[j
+1] = s
;
1742 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1743 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**ret
)
1745 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1746 matching_filter_func func
= NULL
;
1747 struct dwrite_font_propvec req
;
1748 struct dwrite_fontlist
*fonts
;
1751 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, ret
);
1755 fonts
= heap_alloc(sizeof(*fonts
));
1757 return E_OUTOFMEMORY
;
1759 /* Allocate as many as family has, not all of them will be necessary used. */
1760 fonts
->fonts
= heap_alloc(sizeof(*fonts
->fonts
) * This
->data
->font_count
);
1761 if (!fonts
->fonts
) {
1763 return E_OUTOFMEMORY
;
1766 fonts
->IDWriteFontList_iface
.lpVtbl
= &dwritefontlistvtbl
;
1768 fonts
->family
= iface
;
1769 IDWriteFontFamily_AddRef(fonts
->family
);
1770 fonts
->font_count
= 0;
1772 /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */
1773 if (style
== DWRITE_FONT_STYLE_NORMAL
) {
1774 if (This
->data
->has_normal_face
|| This
->data
->has_italic_face
)
1775 func
= is_font_acceptable_for_normal
;
1777 else /* requested oblique or italic */ {
1778 if (This
->data
->has_oblique_face
|| This
->data
->has_italic_face
)
1779 func
= is_font_acceptable_for_oblique_italic
;
1782 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1783 if (!func
|| func(This
->data
->fonts
[i
])) {
1784 fonts
->fonts
[fonts
->font_count
] = This
->data
->fonts
[i
];
1785 InterlockedIncrement(&This
->data
->fonts
[i
]->ref
);
1786 fonts
->font_count
++;
1790 /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */
1791 init_font_prop_vec(weight
, stretch
, style
, &req
);
1792 matchingfonts_sort(fonts
, &req
);
1794 *ret
= &fonts
->IDWriteFontList_iface
;
1798 static const IDWriteFontFamilyVtbl fontfamilyvtbl
= {
1799 dwritefontfamily_QueryInterface
,
1800 dwritefontfamily_AddRef
,
1801 dwritefontfamily_Release
,
1802 dwritefontfamily_GetFontCollection
,
1803 dwritefontfamily_GetFontCount
,
1804 dwritefontfamily_GetFont
,
1805 dwritefontfamily_GetFamilyNames
,
1806 dwritefontfamily_GetFirstMatchingFont
,
1807 dwritefontfamily_GetMatchingFonts
1810 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily
**family
)
1812 struct dwrite_fontfamily
*This
;
1816 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1817 if (!This
) return E_OUTOFMEMORY
;
1819 This
->IDWriteFontFamily_iface
.lpVtbl
= &fontfamilyvtbl
;
1821 This
->collection
= collection
;
1822 IDWriteFontCollection_AddRef(collection
);
1824 InterlockedIncrement(&This
->data
->ref
);
1826 *family
= &This
->IDWriteFontFamily_iface
;
1831 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1834 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1837 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
1839 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1840 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1842 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1843 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
1846 IDWriteFontCollection_AddRef(iface
);
1852 if (This
->is_system
&& IsEqualIID(riid
, &IID_issystemcollection
))
1855 return E_NOINTERFACE
;
1858 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection
*iface
)
1860 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1861 ULONG ref
= InterlockedIncrement(&This
->ref
);
1862 TRACE("(%p)->(%d)\n", This
, ref
);
1866 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection
*iface
)
1869 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1870 ULONG ref
= InterlockedDecrement(&This
->ref
);
1871 TRACE("(%p)->(%d)\n", This
, ref
);
1874 for (i
= 0; i
< This
->family_count
; i
++)
1875 release_fontfamily_data(This
->family_data
[i
]);
1876 heap_free(This
->family_data
);
1883 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
1885 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1886 TRACE("(%p)\n", This
);
1887 return This
->family_count
;
1890 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
1892 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1894 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
1896 if (index
>= This
->family_count
) {
1901 return create_fontfamily(This
->family_data
[index
], iface
, family
);
1904 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
1908 for (i
= 0; i
< collection
->family_count
; i
++) {
1909 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
1910 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
1913 for (j
= 0; j
< count
; j
++) {
1915 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
1916 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
1924 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
1926 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1927 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
1928 *index
= collection_find_family(This
, name
);
1929 *exists
= *index
!= ~0u;
1933 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
1935 UINT32 left_key_size
, right_key_size
;
1936 const void *left_key
, *right_key
;
1942 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
1946 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
1950 if (left_key_size
!= right_key_size
)
1953 return !memcmp(left_key
, right_key
, left_key_size
);
1956 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
1958 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1959 struct dwrite_fontfamily_data
*found_family
= NULL
;
1960 struct dwrite_font_data
*found_font
= NULL
;
1961 IDWriteFontFamily
*family
;
1962 UINT32 i
, j
, face_index
;
1963 IDWriteFontFile
*file
;
1966 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
1971 return E_INVALIDARG
;
1974 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
1977 face_index
= IDWriteFontFace_GetIndex(face
);
1979 for (i
= 0; i
< This
->family_count
; i
++) {
1980 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
1981 for (j
= 0; j
< family_data
->font_count
; j
++) {
1982 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
1984 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
1985 found_font
= font_data
;
1986 found_family
= family_data
;
1993 return DWRITE_E_NOFONT
;
1995 hr
= create_fontfamily(found_family
, iface
, &family
);
1999 hr
= create_font(found_font
, family
, font
);
2000 IDWriteFontFamily_Release(family
);
2004 static const IDWriteFontCollectionVtbl fontcollectionvtbl
= {
2005 dwritefontcollection_QueryInterface
,
2006 dwritefontcollection_AddRef
,
2007 dwritefontcollection_Release
,
2008 dwritefontcollection_GetFontFamilyCount
,
2009 dwritefontcollection_GetFontFamily
,
2010 dwritefontcollection_FindFamilyName
,
2011 dwritefontcollection_GetFontFromFontFace
2014 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
2016 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
2017 struct dwrite_font_data
**new_list
;
2020 new_alloc
= family_data
->font_alloc
* 2;
2021 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
2023 return E_OUTOFMEMORY
;
2024 family_data
->fonts
= new_list
;
2025 family_data
->font_alloc
= new_alloc
;
2028 family_data
->fonts
[family_data
->font_count
] = font_data
;
2029 family_data
->font_count
++;
2030 if (font_data
->style
== DWRITE_FONT_STYLE_NORMAL
)
2031 family_data
->has_normal_face
= TRUE
;
2032 else if (font_data
->style
== DWRITE_FONT_STYLE_OBLIQUE
)
2033 family_data
->has_oblique_face
= TRUE
;
2035 family_data
->has_italic_face
= TRUE
;
2039 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
2041 if (collection
->family_alloc
< collection
->family_count
+ 1) {
2042 struct dwrite_fontfamily_data
**new_list
;
2045 new_alloc
= collection
->family_alloc
* 2;
2046 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
2048 return E_OUTOFMEMORY
;
2050 collection
->family_alloc
= new_alloc
;
2051 collection
->family_data
= new_list
;
2054 collection
->family_data
[collection
->family_count
] = family
;
2055 collection
->family_count
++;
2060 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
2062 collection
->IDWriteFontCollection_iface
.lpVtbl
= &fontcollectionvtbl
;
2063 collection
->ref
= 1;
2064 collection
->family_count
= 0;
2065 collection
->family_alloc
= is_system
? 30 : 5;
2066 collection
->is_system
= is_system
;
2068 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
) * collection
->family_alloc
);
2069 if (!collection
->family_data
)
2070 return E_OUTOFMEMORY
;
2075 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2077 IDWriteFontFileLoader
*loader
;
2084 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2088 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2092 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2093 IDWriteFontFileLoader_Release(loader
);
2100 static void fontstrings_get_en_string(IDWriteLocalizedStrings
*strings
, WCHAR
*buffer
, UINT32 size
)
2102 BOOL exists
= FALSE
;
2107 hr
= IDWriteLocalizedStrings_FindLocaleName(strings
, enusW
, &index
, &exists
);
2108 if (FAILED(hr
) || !exists
)
2111 IDWriteLocalizedStrings_GetString(strings
, index
, buffer
, size
);
2114 static int trim_spaces(WCHAR
*in
, WCHAR
*ret
)
2118 while (isspaceW(*in
))
2122 if (!(len
= strlenW(in
)))
2125 while (isspaceW(in
[len
-1]))
2128 memcpy(ret
, in
, len
*sizeof(WCHAR
));
2137 INT len
; /* token length */
2138 INT fulllen
; /* full length including following separators */
2141 static inline BOOL
is_name_separator_char(WCHAR ch
)
2143 return ch
== ' ' || ch
== '.' || ch
== '-' || ch
== '_';
2146 struct name_pattern
{
2147 const WCHAR
*part1
; /* NULL indicates end of list */
2148 const WCHAR
*part2
; /* optional, if not NULL should point to non-empty string */
2151 static BOOL
match_pattern_list(struct list
*tokens
, const struct name_pattern
*patterns
, struct name_token
*match
)
2153 const struct name_pattern
*pattern
;
2154 struct name_token
*token
;
2157 while ((pattern
= &patterns
[i
++])->part1
) {
2158 int len_part1
= strlenW(pattern
->part1
);
2159 int len_part2
= pattern
->part2
? strlenW(pattern
->part2
) : 0;
2161 LIST_FOR_EACH_ENTRY(token
, tokens
, struct name_token
, entry
) {
2162 if (len_part2
== 0) {
2163 /* simple case with single part pattern */
2164 if (token
->len
!= len_part1
)
2167 if (!strncmpiW(token
->ptr
, pattern
->part1
, len_part1
)) {
2168 if (match
) *match
= *token
;
2169 list_remove(&token
->entry
);
2175 struct name_token
*next_token
;
2176 struct list
*next_entry
;
2178 /* pattern parts are stored in reading order, tokens list is reversed */
2179 if (token
->len
< len_part2
)
2182 /* it's possible to have combined string as a token, like ExtraCondensed */
2183 if (token
->len
== len_part1
+ len_part2
) {
2184 if (strncmpiW(token
->ptr
, pattern
->part1
, len_part1
))
2187 if (strncmpiW(&token
->ptr
[len_part1
], pattern
->part2
, len_part2
))
2190 /* combined string match */
2191 if (match
) *match
= *token
;
2192 list_remove(&token
->entry
);
2197 /* now it's only possible to have two tokens matched to respective pattern parts */
2198 if (token
->len
!= len_part2
)
2201 next_entry
= list_next(tokens
, &token
->entry
);
2203 next_token
= LIST_ENTRY(next_entry
, struct name_token
, entry
);
2204 if (next_token
->len
!= len_part1
)
2207 if (strncmpiW(token
->ptr
, pattern
->part2
, len_part2
))
2210 if (strncmpiW(next_token
->ptr
, pattern
->part1
, len_part1
))
2213 /* both parts matched, remove tokens */
2215 match
->ptr
= next_token
->ptr
;
2216 match
->len
= (token
->ptr
- next_token
->ptr
) + token
->len
;
2218 list_remove(&token
->entry
);
2219 list_remove(&next_token
->entry
);
2220 heap_free(next_token
);
2235 static DWRITE_FONT_STYLE
font_extract_style(struct list
*tokens
, DWRITE_FONT_STYLE style
, struct name_token
*match
)
2237 static const WCHAR itaW
[] = {'i','t','a',0};
2238 static const WCHAR italW
[] = {'i','t','a','l',0};
2239 static const WCHAR cursiveW
[] = {'c','u','r','s','i','v','e',0};
2240 static const WCHAR kursivW
[] = {'k','u','r','s','i','v',0};
2242 static const WCHAR inclinedW
[] = {'i','n','c','l','i','n','e','d',0};
2243 static const WCHAR backslantedW
[] = {'b','a','c','k','s','l','a','n','t','e','d',0};
2244 static const WCHAR backslantW
[] = {'b','a','c','k','s','l','a','n','t',0};
2245 static const WCHAR slantedW
[] = {'s','l','a','n','t','e','d',0};
2247 static const struct name_pattern italic_patterns
[] = {
2256 static const struct name_pattern oblique_patterns
[] = {
2265 /* italic patterns first */
2266 if (match_pattern_list(tokens
, italic_patterns
, match
))
2267 return DWRITE_FONT_STYLE_ITALIC
;
2269 /* oblique patterns */
2270 if (match_pattern_list(tokens
, oblique_patterns
, match
))
2271 return DWRITE_FONT_STYLE_OBLIQUE
;
2276 static DWRITE_FONT_STRETCH
font_extract_stretch(struct list
*tokens
, DWRITE_FONT_STRETCH stretch
,
2277 struct name_token
*match
)
2279 static const WCHAR compressedW
[] = {'c','o','m','p','r','e','s','s','e','d',0};
2280 static const WCHAR extendedW
[] = {'e','x','t','e','n','d','e','d',0};
2281 static const WCHAR compactW
[] = {'c','o','m','p','a','c','t',0};
2282 static const WCHAR narrowW
[] = {'n','a','r','r','o','w',0};
2283 static const WCHAR wideW
[] = {'w','i','d','e',0};
2284 static const WCHAR condW
[] = {'c','o','n','d',0};
2286 static const struct name_pattern ultracondensed_patterns
[] = {
2287 { extraW
, compressedW
},
2288 { extW
, compressedW
},
2289 { ultraW
, compressedW
},
2290 { ultraW
, condensedW
},
2295 static const struct name_pattern extracondensed_patterns
[] = {
2297 { extraW
, condensedW
},
2298 { extW
, condensedW
},
2304 static const struct name_pattern semicondensed_patterns
[] = {
2307 { semiW
, condensedW
},
2312 static const struct name_pattern semiexpanded_patterns
[] = {
2314 { semiW
, expandedW
},
2315 { semiW
, extendedW
},
2319 static const struct name_pattern extraexpanded_patterns
[] = {
2320 { extraW
, expandedW
},
2321 { extW
, expandedW
},
2322 { extraW
, extendedW
},
2323 { extW
, extendedW
},
2327 static const struct name_pattern ultraexpanded_patterns
[] = {
2328 { ultraW
, expandedW
},
2329 { ultraW
, extendedW
},
2333 static const struct name_pattern condensed_patterns
[] = {
2339 static const struct name_pattern expanded_patterns
[] = {
2345 if (match_pattern_list(tokens
, ultracondensed_patterns
, match
))
2346 return DWRITE_FONT_STRETCH_ULTRA_CONDENSED
;
2348 if (match_pattern_list(tokens
, extracondensed_patterns
, match
))
2349 return DWRITE_FONT_STRETCH_EXTRA_CONDENSED
;
2351 if (match_pattern_list(tokens
, semicondensed_patterns
, match
))
2352 return DWRITE_FONT_STRETCH_SEMI_CONDENSED
;
2354 if (match_pattern_list(tokens
, semiexpanded_patterns
, match
))
2355 return DWRITE_FONT_STRETCH_SEMI_EXPANDED
;
2357 if (match_pattern_list(tokens
, extraexpanded_patterns
, match
))
2358 return DWRITE_FONT_STRETCH_EXTRA_EXPANDED
;
2360 if (match_pattern_list(tokens
, ultraexpanded_patterns
, match
))
2361 return DWRITE_FONT_STRETCH_ULTRA_EXPANDED
;
2363 if (match_pattern_list(tokens
, condensed_patterns
, match
))
2364 return DWRITE_FONT_STRETCH_CONDENSED
;
2366 if (match_pattern_list(tokens
, expanded_patterns
, match
))
2367 return DWRITE_FONT_STRETCH_EXPANDED
;
2372 static DWRITE_FONT_WEIGHT
font_extract_weight(struct list
*tokens
, DWRITE_FONT_WEIGHT weight
,
2373 struct name_token
*match
)
2375 static const WCHAR heavyW
[] = {'h','e','a','v','y',0};
2376 static const WCHAR nordW
[] = {'n','o','r','d',0};
2378 static const struct name_pattern thin_patterns
[] = {
2385 static const struct name_pattern extralight_patterns
[] = {
2392 static const struct name_pattern semilight_patterns
[] = {
2397 static const struct name_pattern demibold_patterns
[] = {
2403 static const struct name_pattern extrabold_patterns
[] = {
2410 static const struct name_pattern extrablack_patterns
[] = {
2417 static const struct name_pattern bold_patterns
[] = {
2422 static const struct name_pattern thin2_patterns
[] = {
2427 static const struct name_pattern light_patterns
[] = {
2432 static const struct name_pattern medium_patterns
[] = {
2437 static const struct name_pattern black_patterns
[] = {
2444 static const struct name_pattern demibold2_patterns
[] = {
2449 static const struct name_pattern extrabold2_patterns
[] = {
2454 /* FIXME: allow optional 'face' suffix, separated or not. It's removed together with
2455 matching pattern. */
2457 if (match_pattern_list(tokens
, thin_patterns
, match
))
2458 return DWRITE_FONT_WEIGHT_THIN
;
2460 if (match_pattern_list(tokens
, extralight_patterns
, match
))
2461 return DWRITE_FONT_WEIGHT_EXTRA_LIGHT
;
2463 if (match_pattern_list(tokens
, semilight_patterns
, match
))
2464 return DWRITE_FONT_WEIGHT_SEMI_LIGHT
;
2466 if (match_pattern_list(tokens
, demibold_patterns
, match
))
2467 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2469 if (match_pattern_list(tokens
, extrabold_patterns
, match
))
2470 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2472 if (match_pattern_list(tokens
, extrablack_patterns
, match
))
2473 return DWRITE_FONT_WEIGHT_EXTRA_BLACK
;
2475 if (match_pattern_list(tokens
, bold_patterns
, match
))
2476 return DWRITE_FONT_WEIGHT_BOLD
;
2478 if (match_pattern_list(tokens
, thin2_patterns
, match
))
2479 return DWRITE_FONT_WEIGHT_THIN
;
2481 if (match_pattern_list(tokens
, light_patterns
, match
))
2482 return DWRITE_FONT_WEIGHT_LIGHT
;
2484 if (match_pattern_list(tokens
, medium_patterns
, match
))
2485 return DWRITE_FONT_WEIGHT_MEDIUM
;
2487 if (match_pattern_list(tokens
, black_patterns
, match
))
2488 return DWRITE_FONT_WEIGHT_BLACK
;
2490 if (match_pattern_list(tokens
, black_patterns
, match
))
2491 return DWRITE_FONT_WEIGHT_BLACK
;
2493 if (match_pattern_list(tokens
, demibold2_patterns
, match
))
2494 return DWRITE_FONT_WEIGHT_DEMI_BOLD
;
2496 if (match_pattern_list(tokens
, extrabold2_patterns
, match
))
2497 return DWRITE_FONT_WEIGHT_EXTRA_BOLD
;
2499 /* FIXME: use abbreviated names to extract weight */
2504 struct knownweight_entry
{
2506 DWRITE_FONT_WEIGHT weight
;
2509 static int compare_knownweights(const void *a
, const void* b
)
2511 DWRITE_FONT_WEIGHT target
= *(DWRITE_FONT_WEIGHT
*)a
;
2512 const struct knownweight_entry
*entry
= (struct knownweight_entry
*)b
;
2515 if (target
> entry
->weight
)
2517 else if (target
< entry
->weight
)
2523 static BOOL
is_known_weight_value(DWRITE_FONT_WEIGHT weight
, WCHAR
*nameW
)
2525 static const WCHAR extralightW
[] = {'E','x','t','r','a',' ','L','i','g','h','t',0};
2526 static const WCHAR semilightW
[] = {'S','e','m','i',' ','L','i','g','h','t',0};
2527 static const WCHAR extrablackW
[] = {'E','x','t','r','a',' ','B','l','a','c','k',0};
2528 static const WCHAR extraboldW
[] = {'E','x','t','r','a',' ','B','o','l','d',0};
2529 static const WCHAR demiboldW
[] = {'D','e','m','i',' ','B','o','l','d',0};
2530 const struct knownweight_entry
*ptr
;
2532 static const struct knownweight_entry knownweights
[] = {
2533 { thinW
, DWRITE_FONT_WEIGHT_THIN
},
2534 { extralightW
, DWRITE_FONT_WEIGHT_EXTRA_LIGHT
},
2535 { lightW
, DWRITE_FONT_WEIGHT_LIGHT
},
2536 { semilightW
, DWRITE_FONT_WEIGHT_SEMI_LIGHT
},
2537 { mediumW
, DWRITE_FONT_WEIGHT_MEDIUM
},
2538 { demiboldW
, DWRITE_FONT_WEIGHT_DEMI_BOLD
},
2539 { boldW
, DWRITE_FONT_WEIGHT_BOLD
},
2540 { extraboldW
, DWRITE_FONT_WEIGHT_EXTRA_BOLD
},
2541 { blackW
, DWRITE_FONT_WEIGHT_BLACK
},
2542 { extrablackW
, DWRITE_FONT_WEIGHT_EXTRA_BLACK
}
2545 ptr
= bsearch(&weight
, knownweights
, sizeof(knownweights
)/sizeof(knownweights
[0]), sizeof(knownweights
[0]),
2546 compare_knownweights
);
2552 strcpyW(nameW
, ptr
->nameW
);
2556 static inline void font_name_token_to_str(const struct name_token
*name
, WCHAR
*strW
)
2558 memcpy(strW
, name
->ptr
, name
->len
* sizeof(WCHAR
));
2559 strW
[name
->len
] = 0;
2562 /* Modifies facenameW string, and returns pointer to regular term that was removed */
2563 static const WCHAR
*facename_remove_regular_term(WCHAR
*facenameW
, INT len
)
2565 static const WCHAR bookW
[] = {'B','o','o','k',0};
2566 static const WCHAR normalW
[] = {'N','o','r','m','a','l',0};
2567 static const WCHAR regularW
[] = {'R','e','g','u','l','a','r',0};
2568 static const WCHAR romanW
[] = {'R','o','m','a','n',0};
2569 static const WCHAR uprightW
[] = {'U','p','r','i','g','h','t',0};
2571 static const WCHAR
*regular_patterns
[] = {
2580 const WCHAR
*regular_ptr
= NULL
, *ptr
;
2584 len
= strlenW(facenameW
);
2586 /* remove rightmost regular variant from face name */
2587 while (!regular_ptr
&& (ptr
= regular_patterns
[i
++])) {
2588 int pattern_len
= strlenW(ptr
);
2591 if (pattern_len
> len
)
2594 src
= facenameW
+ len
- pattern_len
;
2595 while (src
>= facenameW
) {
2596 if (!strncmpiW(src
, ptr
, pattern_len
)) {
2597 memmove(src
, src
+ pattern_len
, (len
- pattern_len
- (src
- facenameW
) + 1)*sizeof(WCHAR
));
2598 len
= strlenW(facenameW
);
2610 static void fontname_tokenize(struct list
*tokens
, const WCHAR
*nameW
)
2618 struct name_token
*token
= heap_alloc(sizeof(*token
));
2623 while (*ptr
&& !is_name_separator_char(*ptr
)) {
2629 /* skip separators */
2630 while (is_name_separator_char(*ptr
)) {
2635 list_add_head(tokens
, &token
->entry
);
2639 static void fontname_tokens_to_str(struct list
*tokens
, WCHAR
*nameW
)
2641 struct name_token
*token
, *token2
;
2642 LIST_FOR_EACH_ENTRY_SAFE_REV(token
, token2
, tokens
, struct name_token
, entry
) {
2645 list_remove(&token
->entry
);
2647 /* don't include last separator */
2648 len
= list_empty(tokens
) ? token
->len
: token
->fulllen
;
2649 memcpy(nameW
, token
->ptr
, len
* sizeof(WCHAR
));
2657 static BOOL
font_apply_differentiation_rules(struct dwrite_font_data
*font
, WCHAR
*familyW
, WCHAR
*faceW
)
2659 struct name_token stretch_name
, weight_name
, style_name
;
2660 WCHAR familynameW
[255], facenameW
[255], finalW
[255];
2661 WCHAR weightW
[32], stretchW
[32], styleW
[32];
2662 const WCHAR
*regular_ptr
= NULL
;
2663 DWRITE_FONT_STRETCH stretch
;
2664 DWRITE_FONT_WEIGHT weight
;
2668 /* remove leading and trailing spaces from family and face name */
2669 trim_spaces(familyW
, familynameW
);
2670 len
= trim_spaces(faceW
, facenameW
);
2672 /* remove rightmost regular variant from face name */
2673 regular_ptr
= facename_remove_regular_term(facenameW
, len
);
2675 /* append face name to family name, FIXME check if face name is a substring of family name */
2677 strcatW(familynameW
, spaceW
);
2678 strcatW(familynameW
, facenameW
);
2681 /* tokenize with " .-_" */
2682 fontname_tokenize(&tokens
, familynameW
);
2684 /* extract and resolve style */
2685 font
->style
= font_extract_style(&tokens
, font
->style
, &style_name
);
2687 /* extract stretch */
2688 stretch
= font_extract_stretch(&tokens
, font
->stretch
, &stretch_name
);
2690 /* extract weight */
2691 weight
= font_extract_weight(&tokens
, font
->weight
, &weight_name
);
2693 /* resolve weight */
2694 if (weight
!= font
->weight
) {
2695 if (!(weight
< DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
< DWRITE_FONT_WEIGHT_NORMAL
) &&
2696 !(weight
> DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
> DWRITE_FONT_WEIGHT_MEDIUM
) &&
2697 !((weight
== DWRITE_FONT_WEIGHT_NORMAL
&& font
->weight
== DWRITE_FONT_WEIGHT_MEDIUM
) ||
2698 (weight
== DWRITE_FONT_WEIGHT_MEDIUM
&& font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)) &&
2699 !(abs(weight
- font
->weight
) <= 150 &&
2700 font
->weight
!= DWRITE_FONT_WEIGHT_NORMAL
&&
2701 font
->weight
!= DWRITE_FONT_WEIGHT_MEDIUM
&&
2702 font
->weight
!= DWRITE_FONT_WEIGHT_BOLD
)) {
2704 font
->weight
= weight
;
2708 /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
2709 it's leaning in opposite direction from normal comparing to specified stretch or if specified
2710 stretch itself is normal (extracted stretch is never normal). */
2711 if (stretch
!= font
->stretch
) {
2712 if ((font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
) ||
2713 (font
->stretch
< DWRITE_FONT_STRETCH_NORMAL
&& stretch
> DWRITE_FONT_STRETCH_NORMAL
) ||
2714 (font
->stretch
> DWRITE_FONT_STRETCH_NORMAL
&& stretch
< DWRITE_FONT_STRETCH_NORMAL
)) {
2716 font
->stretch
= stretch
;
2720 /* FIXME: cleanup face name from possible 2-3 digit prefixes */
2722 /* get final combined string from what's left in token list, list is released */
2723 fontname_tokens_to_str(&tokens
, finalW
);
2725 if (!strcmpW(familyW
, finalW
))
2728 /* construct face name */
2729 strcpyW(familyW
, finalW
);
2731 /* resolved weight name */
2732 if (weight_name
.ptr
)
2733 font_name_token_to_str(&weight_name
, weightW
);
2734 /* ignore normal weight */
2735 else if (font
->weight
== DWRITE_FONT_WEIGHT_NORMAL
)
2737 /* for known weight values use appropriate names */
2738 else if (is_known_weight_value(font
->weight
, weightW
)) {
2740 /* use Wnnn format as a fallback in case weight is not one of defined values */
2742 static const WCHAR fmtW
[] = {'W','%','d',0};
2743 sprintfW(weightW
, fmtW
, font
->weight
);
2746 /* resolved stretch name */
2747 if (stretch_name
.ptr
)
2748 font_name_token_to_str(&stretch_name
, stretchW
);
2749 /* ignore normal stretch */
2750 else if (font
->stretch
== DWRITE_FONT_STRETCH_NORMAL
)
2752 /* use predefined stretch names */
2754 static const WCHAR ultracondensedW
[] = {'U','l','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2755 static const WCHAR extracondensedW
[] = {'E','x','t','r','a',' ','C','o','n','d','e','n','s','e','d',0};
2756 static const WCHAR semicondensedW
[] = {'S','e','m','i',' ','C','o','n','d','e','n','s','e','d',0};
2757 static const WCHAR semiexpandedW
[] = {'S','e','m','i',' ','E','x','p','a','n','d','e','d',0};
2758 static const WCHAR extraexpandedW
[] = {'E','x','t','r','a',' ','E','x','p','a','n','d','e','d',0};
2759 static const WCHAR ultraexpandedW
[] = {'U','l','t','r','a',' ','E','x','p','a','n','d','e','d',0};
2761 static const WCHAR
*stretchnamesW
[] = {
2766 NULL
, /* DWRITE_FONT_STRETCH_NORMAL */
2772 strcpyW(stretchW
, stretchnamesW
[font
->stretch
]);
2775 /* resolved style name */
2777 font_name_token_to_str(&style_name
, styleW
);
2778 else if (font
->style
== DWRITE_FONT_STYLE_NORMAL
)
2780 /* use predefined names */
2782 if (font
->style
== DWRITE_FONT_STYLE_ITALIC
)
2783 strcpyW(styleW
, italicW
);
2785 strcpyW(styleW
, obliqueW
);
2788 /* use Regular match if it was found initially */
2789 if (!*weightW
&& !*stretchW
&& !*styleW
)
2790 strcpyW(faceW
, regular_ptr
? regular_ptr
: regularW
);
2794 strcpyW(faceW
, stretchW
);
2797 strcatW(faceW
, spaceW
);
2798 strcatW(faceW
, weightW
);
2802 strcatW(faceW
, spaceW
);
2803 strcatW(faceW
, styleW
);
2807 TRACE("resolved family %s, face %s\n", debugstr_w(familyW
), debugstr_w(faceW
));
2811 static HRESULT
init_font_data(IDWriteFactory2
*factory
, IDWriteFontFile
*file
, DWRITE_FONT_FACE_TYPE face_type
, UINT32 face_index
,
2812 IDWriteLocalizedStrings
**family_name
, struct dwrite_font_data
**ret
)
2814 struct dwrite_font_props props
;
2815 struct dwrite_font_data
*data
;
2816 IDWriteFontFileStream
*stream
;
2817 WCHAR familyW
[255], faceW
[255];
2821 data
= heap_alloc_zero(sizeof(*data
));
2823 return E_OUTOFMEMORY
;
2825 hr
= get_filestream_from_file(file
, &stream
);
2832 data
->factory
= factory
;
2834 data
->face_index
= face_index
;
2835 data
->face_type
= face_type
;
2836 data
->simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
2837 data
->bold_sim_tested
= FALSE
;
2838 data
->oblique_sim_tested
= FALSE
;
2839 IDWriteFontFile_AddRef(file
);
2840 IDWriteFactory2_AddRef(factory
);
2842 opentype_get_font_properties(stream
, face_type
, face_index
, &props
);
2843 opentype_get_font_metrics(stream
, face_type
, face_index
, &data
->metrics
, NULL
);
2844 opentype_get_font_facename(stream
, face_type
, face_index
, &data
->names
);
2846 /* get family name from font file */
2847 hr
= opentype_get_font_familyname(stream
, face_type
, face_index
, family_name
);
2848 IDWriteFontFileStream_Release(stream
);
2850 WARN("unable to get family name from font\n");
2851 release_font_data(data
);
2855 data
->style
= props
.style
;
2856 data
->stretch
= props
.stretch
;
2857 data
->weight
= props
.weight
;
2858 data
->panose
= props
.panose
;
2860 fontstrings_get_en_string(*family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
2861 fontstrings_get_en_string(data
->names
, faceW
, sizeof(faceW
)/sizeof(WCHAR
));
2862 if (font_apply_differentiation_rules(data
, familyW
, faceW
)) {
2863 set_en_localizedstring(*family_name
, familyW
);
2864 set_en_localizedstring(data
->names
, faceW
);
2867 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
2873 static HRESULT
init_font_data_from_font(const struct dwrite_font_data
*src
, DWRITE_FONT_SIMULATIONS sim
, const WCHAR
*facenameW
,
2874 struct dwrite_font_data
**ret
)
2876 struct dwrite_font_data
*data
;
2879 data
= heap_alloc_zero(sizeof(*data
));
2881 return E_OUTOFMEMORY
;
2885 data
->simulations
|= sim
;
2886 if (sim
== DWRITE_FONT_SIMULATIONS_BOLD
)
2887 data
->weight
= DWRITE_FONT_WEIGHT_BOLD
;
2888 else if (sim
== DWRITE_FONT_SIMULATIONS_OBLIQUE
)
2889 data
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
2890 memset(data
->info_strings
, 0, sizeof(data
->info_strings
));
2892 IDWriteFactory2_AddRef(data
->factory
);
2893 IDWriteFontFile_AddRef(data
->file
);
2895 create_localizedstrings(&data
->names
);
2896 add_localizedstring(data
->names
, enusW
, facenameW
);
2898 init_font_prop_vec(data
->weight
, data
->stretch
, data
->style
, &data
->propvec
);
2904 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
2906 struct dwrite_fontfamily_data
*data
;
2908 data
= heap_alloc(sizeof(*data
));
2910 return E_OUTOFMEMORY
;
2913 data
->font_count
= 0;
2914 data
->font_alloc
= 2;
2915 data
->has_normal_face
= FALSE
;
2916 data
->has_oblique_face
= FALSE
;
2917 data
->has_italic_face
= FALSE
;
2919 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
2922 return E_OUTOFMEMORY
;
2925 data
->familyname
= familyname
;
2926 IDWriteLocalizedStrings_AddRef(familyname
);
2932 static void fontfamily_add_bold_simulated_face(struct dwrite_fontfamily_data
*family
)
2934 UINT32 i
, j
, heaviest
;
2936 for (i
= 0; i
< family
->font_count
; i
++) {
2937 DWRITE_FONT_WEIGHT weight
= family
->fonts
[i
]->weight
;
2940 if (family
->fonts
[i
]->bold_sim_tested
)
2943 family
->fonts
[i
]->bold_sim_tested
= TRUE
;
2944 for (j
= i
; j
< family
->font_count
; j
++) {
2945 if (family
->fonts
[j
]->bold_sim_tested
)
2948 if ((family
->fonts
[i
]->style
== family
->fonts
[j
]->style
) &&
2949 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
2950 if (family
->fonts
[j
]->weight
> weight
) {
2951 weight
= family
->fonts
[j
]->weight
;
2954 family
->fonts
[j
]->bold_sim_tested
= TRUE
;
2958 if (weight
>= DWRITE_FONT_WEIGHT_SEMI_LIGHT
&& weight
<= 550) {
2959 static const struct name_pattern weightsim_patterns
[] = {
2974 WCHAR facenameW
[255], initialW
[255];
2975 struct dwrite_font_data
*boldface
;
2978 /* add Bold simulation based on heaviest face data */
2980 /* Simulated face name should only contain Bold as weight term,
2981 so remove existing regular and weight terms. */
2982 fontstrings_get_en_string(family
->fonts
[heaviest
]->names
, initialW
, sizeof(initialW
)/sizeof(WCHAR
));
2983 facename_remove_regular_term(initialW
, -1);
2985 /* remove current weight pattern */
2986 fontname_tokenize(&tokens
, initialW
);
2987 match_pattern_list(&tokens
, weightsim_patterns
, NULL
);
2988 fontname_tokens_to_str(&tokens
, facenameW
);
2990 /* Bold suffix for new name */
2992 strcatW(facenameW
, spaceW
);
2993 strcatW(facenameW
, boldW
);
2995 if (init_font_data_from_font(family
->fonts
[heaviest
], DWRITE_FONT_SIMULATIONS_BOLD
, facenameW
, &boldface
) == S_OK
) {
2996 boldface
->bold_sim_tested
= TRUE
;
2997 fontfamily_add_font(family
, boldface
);
3003 static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
*family
)
3007 for (i
= 0; i
< family
->font_count
; i
++) {
3008 UINT32 regular
= ~0u, oblique
= ~0u;
3009 struct dwrite_font_data
*obliqueface
;
3010 WCHAR facenameW
[255];
3012 if (family
->fonts
[i
]->oblique_sim_tested
)
3015 family
->fonts
[i
]->oblique_sim_tested
= TRUE
;
3016 if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3018 else if (family
->fonts
[i
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3021 /* find regular style with same weight/stretch values */
3022 for (j
= i
; j
< family
->font_count
; j
++) {
3023 if (family
->fonts
[j
]->oblique_sim_tested
)
3026 if ((family
->fonts
[i
]->weight
== family
->fonts
[j
]->weight
) &&
3027 (family
->fonts
[i
]->stretch
== family
->fonts
[j
]->stretch
)) {
3029 family
->fonts
[j
]->oblique_sim_tested
= TRUE
;
3030 if (regular
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_NORMAL
)
3033 if (oblique
== ~0 && family
->fonts
[j
]->style
== DWRITE_FONT_STYLE_OBLIQUE
)
3037 if (regular
!= ~0u && oblique
!= ~0u)
3041 /* no regular variant for this weight/stretch pair, nothing to base simulated face on */
3045 /* regular face exists, and corresponding oblique is present as well, nothing to do */
3049 /* add oblique simulation based on this regular face */
3051 /* remove regular term if any, append 'Oblique' */
3052 fontstrings_get_en_string(family
->fonts
[regular
]->names
, facenameW
, sizeof(facenameW
)/sizeof(WCHAR
));
3053 facename_remove_regular_term(facenameW
, -1);
3056 strcatW(facenameW
, spaceW
);
3057 strcatW(facenameW
, obliqueW
);
3059 if (init_font_data_from_font(family
->fonts
[regular
], DWRITE_FONT_SIMULATIONS_OBLIQUE
, facenameW
, &obliqueface
) == S_OK
) {
3060 obliqueface
->oblique_sim_tested
= TRUE
;
3061 fontfamily_add_font(family
, obliqueface
);
3066 HRESULT
create_font_collection(IDWriteFactory2
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
3068 struct fontfile_enum
{
3070 IDWriteFontFile
*file
;
3072 struct fontfile_enum
*fileenum
, *fileenum2
;
3073 struct dwrite_fontcollection
*collection
;
3074 struct list scannedfiles
;
3075 BOOL current
= FALSE
;
3081 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
3082 if (!collection
) return E_OUTOFMEMORY
;
3084 hr
= init_font_collection(collection
, is_system
);
3086 heap_free(collection
);
3090 *ret
= &collection
->IDWriteFontCollection_iface
;
3092 TRACE("building font collection:\n");
3094 list_init(&scannedfiles
);
3095 while (hr
== S_OK
) {
3096 DWRITE_FONT_FACE_TYPE face_type
;
3097 DWRITE_FONT_FILE_TYPE file_type
;
3098 BOOL supported
, same
= FALSE
;
3099 IDWriteFontFile
*file
;
3103 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
3104 if (FAILED(hr
) || !current
)
3107 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
3111 /* check if we've scanned this file already */
3112 LIST_FOR_EACH_ENTRY(fileenum
, &scannedfiles
, struct fontfile_enum
, entry
) {
3113 if ((same
= is_same_fontfile(fileenum
->file
, file
)))
3118 IDWriteFontFile_Release(file
);
3122 /* failed font files are skipped */
3123 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
3124 if (FAILED(hr
) || !supported
|| face_count
== 0) {
3125 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
3126 IDWriteFontFile_Release(file
);
3131 /* add to scanned list */
3132 fileenum
= heap_alloc(sizeof(*fileenum
));
3133 fileenum
->file
= file
;
3134 list_add_tail(&scannedfiles
, &fileenum
->entry
);
3136 for (i
= 0; i
< face_count
; i
++) {
3137 IDWriteLocalizedStrings
*family_name
= NULL
;
3138 struct dwrite_font_data
*font_data
;
3142 /* alloc and init new font data structure */
3143 hr
= init_font_data(factory
, file
, face_type
, i
, &family_name
, &font_data
);
3147 fontstrings_get_en_string(family_name
, familyW
, sizeof(familyW
)/sizeof(WCHAR
));
3149 index
= collection_find_family(collection
, familyW
);
3151 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
3153 struct dwrite_fontfamily_data
*family_data
;
3155 /* create and init new family */
3156 hr
= init_fontfamily_data(family_name
, &family_data
);
3158 /* add font to family, family - to collection */
3159 hr
= fontfamily_add_font(family_data
, font_data
);
3161 hr
= fontcollection_add_family(collection
, family_data
);
3164 release_fontfamily_data(family_data
);
3168 IDWriteLocalizedStrings_Release(family_name
);
3175 LIST_FOR_EACH_ENTRY_SAFE(fileenum
, fileenum2
, &scannedfiles
, struct fontfile_enum
, entry
) {
3176 IDWriteFontFile_Release(fileenum
->file
);
3177 list_remove(&fileenum
->entry
);
3178 heap_free(fileenum
);
3181 for (i
= 0; i
< collection
->family_count
; i
++) {
3182 fontfamily_add_bold_simulated_face(collection
->family_data
[i
]);
3183 fontfamily_add_oblique_simulated_face(collection
->family_data
[i
]);
3189 struct system_fontfile_enumerator
3191 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
3194 IDWriteFactory2
*factory
;
3199 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
3201 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
3204 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3208 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3209 IDWriteFontFileEnumerator_AddRef(iface
);
3214 return E_NOINTERFACE
;
3217 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3219 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3220 return InterlockedIncrement(&enumerator
->ref
);
3223 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3225 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3226 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
3229 IDWriteFactory2_Release(enumerator
->factory
);
3230 RegCloseKey(enumerator
->hkey
);
3231 heap_free(enumerator
);
3237 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3239 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3240 DWORD ret
, type
, val_count
, count
;
3241 WCHAR
*value
, *filename
;
3246 if (enumerator
->index
< 0)
3249 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
3250 if (ret
!= ERROR_SUCCESS
)
3254 value
= heap_alloc( val_count
* sizeof(value
[0]) );
3255 filename
= heap_alloc(count
);
3256 if (!value
|| !filename
) {
3258 heap_free(filename
);
3259 return E_OUTOFMEMORY
;
3262 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
3265 heap_free(filename
);
3269 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
3270 if (!strchrW(filename
, '\\')) {
3271 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
3272 WCHAR fullpathW
[MAX_PATH
];
3274 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
3275 strcatW(fullpathW
, fontsW
);
3276 strcatW(fullpathW
, filename
);
3278 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, fullpathW
, NULL
, file
);
3281 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, filename
, NULL
, file
);
3284 heap_free(filename
);
3288 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3290 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
3291 DWORD ret
, max_val_count
;
3295 enumerator
->index
++;
3297 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
3298 if (ret
!= ERROR_SUCCESS
)
3302 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
3303 return E_OUTOFMEMORY
;
3305 /* iterate until we find next string value */
3307 DWORD type
= 0, count
, val_count
;
3308 val_count
= max_val_count
;
3309 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
3311 if (type
== REG_SZ
) {
3315 enumerator
->index
++;
3318 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
3323 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
3325 systemfontfileenumerator_QueryInterface
,
3326 systemfontfileenumerator_AddRef
,
3327 systemfontfileenumerator_Release
,
3328 systemfontfileenumerator_MoveNext
,
3329 systemfontfileenumerator_GetCurrentFontFile
3332 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory2
*factory
, IDWriteFontFileEnumerator
**ret
)
3334 struct system_fontfile_enumerator
*enumerator
;
3335 static const WCHAR fontslistW
[] = {
3336 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3337 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3338 'F','o','n','t','s',0
3343 enumerator
= heap_alloc(sizeof(*enumerator
));
3345 return E_OUTOFMEMORY
;
3347 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
3348 enumerator
->ref
= 1;
3349 enumerator
->factory
= factory
;
3350 enumerator
->index
= -1;
3351 IDWriteFactory2_AddRef(factory
);
3353 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
3354 ERR("failed to open fonts list key\n");
3355 IDWriteFactory2_Release(factory
);
3356 heap_free(enumerator
);
3360 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
3365 HRESULT
get_system_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
3367 IDWriteFontFileEnumerator
*enumerator
;
3372 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
3376 TRACE("building system font collection for factory %p\n", factory
);
3377 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
3378 IDWriteFontFileEnumerator_Release(enumerator
);
3382 static HRESULT WINAPI
eudcfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
3386 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
3387 IDWriteFontFileEnumerator_AddRef(iface
);
3392 return E_NOINTERFACE
;
3395 static ULONG WINAPI
eudcfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
3400 static ULONG WINAPI
eudcfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
3405 static HRESULT WINAPI
eudcfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
3411 static HRESULT WINAPI
eudcfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
3417 static const struct IDWriteFontFileEnumeratorVtbl eudcfontfileenumeratorvtbl
=
3419 eudcfontfileenumerator_QueryInterface
,
3420 eudcfontfileenumerator_AddRef
,
3421 eudcfontfileenumerator_Release
,
3422 eudcfontfileenumerator_MoveNext
,
3423 eudcfontfileenumerator_GetCurrentFontFile
3426 static IDWriteFontFileEnumerator eudc_fontfile_enumerator
= { &eudcfontfileenumeratorvtbl
};
3428 HRESULT
get_eudc_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
3430 TRACE("building EUDC font collection for factory %p\n", factory
);
3431 return create_font_collection(factory
, &eudc_fontfile_enumerator
, FALSE
, collection
);
3434 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
3436 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3438 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3440 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
3443 IDWriteFontFile_AddRef(iface
);
3448 return E_NOINTERFACE
;
3451 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
3453 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3454 ULONG ref
= InterlockedIncrement(&This
->ref
);
3455 TRACE("(%p)->(%d)\n", This
, ref
);
3459 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
3461 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3462 ULONG ref
= InterlockedDecrement(&This
->ref
);
3464 TRACE("(%p)->(%d)\n", This
, ref
);
3468 IDWriteFontFileLoader_Release(This
->loader
);
3469 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
3470 heap_free(This
->reference_key
);
3477 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
3479 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3480 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
3481 *fontFileReferenceKey
= This
->reference_key
;
3482 *fontFileReferenceKeySize
= This
->key_size
;
3487 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
3489 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3490 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
3491 *fontFileLoader
= This
->loader
;
3492 IDWriteFontFileLoader_AddRef(This
->loader
);
3497 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
, DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
3499 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
3500 IDWriteFontFileStream
*stream
;
3503 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
3505 *isSupportedFontType
= FALSE
;
3506 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
3508 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
3511 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
3515 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
3517 /* TODO: Further Analysis */
3518 IDWriteFontFileStream_Release(stream
);
3522 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
3523 dwritefontfile_QueryInterface
,
3524 dwritefontfile_AddRef
,
3525 dwritefontfile_Release
,
3526 dwritefontfile_GetReferenceKey
,
3527 dwritefontfile_GetLoader
,
3528 dwritefontfile_Analyze
,
3531 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
3533 struct dwrite_fontfile
*This
;
3535 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
3536 if (!This
) return E_OUTOFMEMORY
;
3538 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
3540 IDWriteFontFileLoader_AddRef(loader
);
3541 This
->loader
= loader
;
3542 This
->stream
= NULL
;
3543 This
->reference_key
= heap_alloc(key_size
);
3544 memcpy(This
->reference_key
, reference_key
, key_size
);
3545 This
->key_size
= key_size
;
3547 *font_file
= &This
->IDWriteFontFile_iface
;
3552 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
3554 IDWriteFontFileLoader
*loader
;
3560 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
3564 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
3566 IDWriteFontFileLoader_Release(loader
);
3570 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
3571 IDWriteFontFileLoader_Release(loader
);
3576 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
3577 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace2
**ret
)
3579 struct dwrite_fontface
*fontface
;
3585 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
3587 return E_OUTOFMEMORY
;
3589 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
3590 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
3592 if (!fontface
->files
|| !fontface
->streams
) {
3593 heap_free(fontface
->files
);
3594 heap_free(fontface
->streams
);
3595 heap_free(fontface
);
3596 return E_OUTOFMEMORY
;
3599 fontface
->IDWriteFontFace2_iface
.lpVtbl
= &dwritefontfacevtbl
;
3601 fontface
->type
= facetype
;
3602 fontface
->file_count
= files_number
;
3603 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
3604 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
3605 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
3606 memset(&fontface
->cpal
, 0, sizeof(fontface
->cpal
));
3607 fontface
->cmap
.exists
= TRUE
;
3608 fontface
->vdmx
.exists
= TRUE
;
3609 fontface
->gasp
.exists
= TRUE
;
3610 fontface
->cpal
.exists
= TRUE
;
3611 fontface
->index
= index
;
3612 fontface
->simulations
= simulations
;
3613 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
3615 for (i
= 0; i
< fontface
->file_count
; i
++) {
3616 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
3618 IDWriteFontFace2_Release(&fontface
->IDWriteFontFace2_iface
);
3622 fontface
->files
[i
] = font_files
[i
];
3623 IDWriteFontFile_AddRef(font_files
[i
]);
3626 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
3627 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
3628 /* TODO: test what happens if caret is already slanted */
3629 if (fontface
->caret
.slopeRise
== 1) {
3630 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
3631 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
3634 fontface
->charmap
= freetype_get_charmap_index(&fontface
->IDWriteFontFace2_iface
, &fontface
->is_symbol
);
3636 *ret
= &fontface
->IDWriteFontFace2_iface
;
3640 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
3647 struct local_cached_stream
3650 IDWriteFontFileStream
*stream
;
3651 struct local_refkey
*key
;
3655 struct dwrite_localfontfilestream
3657 IDWriteFontFileStream IDWriteFontFileStream_iface
;
3660 struct local_cached_stream
*entry
;
3661 const void *file_ptr
;
3665 struct dwrite_localfontfileloader
{
3666 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
3669 struct list streams
;
3672 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
3674 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
3677 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
3679 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
3682 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
3684 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3685 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3686 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
3689 IDWriteFontFileStream_AddRef(iface
);
3694 return E_NOINTERFACE
;
3697 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
3699 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3700 ULONG ref
= InterlockedIncrement(&This
->ref
);
3701 TRACE("(%p)->(%d)\n", This
, ref
);
3705 static inline void release_cached_stream(struct local_cached_stream
*stream
)
3707 list_remove(&stream
->entry
);
3708 heap_free(stream
->key
);
3712 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
3714 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3715 ULONG ref
= InterlockedDecrement(&This
->ref
);
3717 TRACE("(%p)->(%d)\n", This
, ref
);
3720 UnmapViewOfFile(This
->file_ptr
);
3721 release_cached_stream(This
->entry
);
3728 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
3730 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3732 TRACE("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
3733 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
3735 *fragment_context
= NULL
;
3737 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
3738 *fragment_start
= NULL
;
3742 *fragment_start
= (char*)This
->file_ptr
+ offset
;
3746 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
3748 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3749 TRACE("(%p)->(%p)\n", This
, fragment_context
);
3752 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
3754 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3755 TRACE("(%p)->(%p)\n", This
, size
);
3760 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
3762 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
3765 TRACE("(%p)->(%p)\n", This
, last_writetime
);
3767 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
3768 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
3769 *last_writetime
= li
.QuadPart
;
3774 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
3776 localfontfilestream_QueryInterface
,
3777 localfontfilestream_AddRef
,
3778 localfontfilestream_Release
,
3779 localfontfilestream_ReadFileFragment
,
3780 localfontfilestream_ReleaseFileFragment
,
3781 localfontfilestream_GetFileSize
,
3782 localfontfilestream_GetLastWriteTime
3785 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
** iface
)
3787 struct dwrite_localfontfilestream
*This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
3789 return E_OUTOFMEMORY
;
3791 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
3794 This
->file_ptr
= file_ptr
;
3796 This
->entry
= entry
;
3798 *iface
= &This
->IDWriteFontFileStream_iface
;
3802 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
3804 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3806 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
3808 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
3811 IDWriteLocalFontFileLoader_AddRef(iface
);
3816 return E_NOINTERFACE
;
3819 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
3821 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3822 ULONG ref
= InterlockedIncrement(&This
->ref
);
3823 TRACE("(%p)->(%d)\n", This
, ref
);
3827 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
3829 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3830 ULONG ref
= InterlockedDecrement(&This
->ref
);
3832 TRACE("(%p)->(%d)\n", This
, ref
);
3835 struct local_cached_stream
*stream
, *stream2
;
3837 /* This will detach all entries from cache. Entries are released together with streams,
3838 so stream controls its lifetime. */
3839 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
3840 list_init(&stream
->entry
);
3848 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
3850 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3851 const struct local_refkey
*refkey
= key
;
3852 struct local_cached_stream
*stream
;
3853 IDWriteFontFileStream
*filestream
;
3854 HANDLE file
, mapping
;
3859 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
3860 TRACE("name: %s\n", debugstr_w(refkey
->name
));
3862 /* search cache first */
3863 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
3864 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
3865 *ret
= stream
->stream
;
3866 IDWriteFontFileStream_AddRef(*ret
);
3873 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
3874 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3875 if (file
== INVALID_HANDLE_VALUE
)
3878 GetFileSizeEx(file
, &size
);
3879 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3884 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
3885 CloseHandle(mapping
);
3887 stream
= heap_alloc(sizeof(*stream
));
3889 UnmapViewOfFile(file_ptr
);
3890 return E_OUTOFMEMORY
;
3893 stream
->key
= heap_alloc(key_size
);
3895 UnmapViewOfFile(file_ptr
);
3897 return E_OUTOFMEMORY
;
3900 stream
->key_size
= key_size
;
3901 memcpy(stream
->key
, key
, key_size
);
3903 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
3905 UnmapViewOfFile(file_ptr
);
3906 heap_free(stream
->key
);
3911 stream
->stream
= filestream
;
3912 list_add_head(&This
->streams
, &stream
->entry
);
3914 *ret
= stream
->stream
;
3919 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
3921 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3922 const struct local_refkey
*refkey
= key
;
3924 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
3926 *length
= strlenW(refkey
->name
);
3930 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
3932 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3933 const struct local_refkey
*refkey
= key
;
3935 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
3937 if (length
< strlenW(refkey
->name
))
3938 return E_INVALIDARG
;
3940 strcpyW(path
, refkey
->name
);
3944 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
3946 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
3947 const struct local_refkey
*refkey
= key
;
3949 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
3951 *writetime
= refkey
->writetime
;
3955 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
3956 localfontfileloader_QueryInterface
,
3957 localfontfileloader_AddRef
,
3958 localfontfileloader_Release
,
3959 localfontfileloader_CreateStreamFromKey
,
3960 localfontfileloader_GetFilePathLengthFromKey
,
3961 localfontfileloader_GetFilePathFromKey
,
3962 localfontfileloader_GetLastWriteTimeFromKey
3965 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
** iface
)
3967 struct dwrite_localfontfileloader
*This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
3969 return E_OUTOFMEMORY
;
3971 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
3973 list_init(&This
->streams
);
3975 *iface
= &This
->IDWriteLocalFontFileLoader_iface
;
3979 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
3981 struct local_refkey
*refkey
;
3983 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
3986 refkey
= heap_alloc(*size
);
3988 return E_OUTOFMEMORY
;
3991 refkey
->writetime
= *writetime
;
3993 WIN32_FILE_ATTRIBUTE_DATA info
;
3995 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
3996 refkey
->writetime
= info
.ftLastWriteTime
;
3998 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
4000 strcpyW(refkey
->name
, path
);
4007 /* IDWriteGlyphRunAnalysis */
4008 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
4010 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4012 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4014 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
4015 IsEqualIID(riid
, &IID_IUnknown
))
4018 IDWriteGlyphRunAnalysis_AddRef(iface
);
4023 return E_NOINTERFACE
;
4026 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
4028 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4029 ULONG ref
= InterlockedIncrement(&This
->ref
);
4030 TRACE("(%p)->(%u)\n", This
, ref
);
4034 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
4036 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4037 ULONG ref
= InterlockedDecrement(&This
->ref
);
4039 TRACE("(%p)->(%u)\n", This
, ref
);
4042 if (This
->run
.fontFace
)
4043 IDWriteFontFace_Release(This
->run
.fontFace
);
4044 heap_free(This
->glyphs
);
4045 heap_free(This
->advances
);
4046 heap_free(This
->advanceoffsets
);
4047 heap_free(This
->ascenderoffsets
);
4048 heap_free(This
->bitmap
);
4055 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
4057 struct dwrite_glyphbitmap glyph_bitmap
;
4058 IDWriteFontFace2
*fontface2
;
4059 D2D_POINT_2F origin
;
4064 if (analysis
->flags
& RUNANALYSIS_BOUNDS_READY
) {
4065 *bounds
= analysis
->bounds
;
4069 if (analysis
->run
.isSideways
)
4070 FIXME("sideways runs are not supported.\n");
4072 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
4074 WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr
);
4076 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
4077 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
4078 for any non-zero glyph ascender */
4079 origin
.x
= origin
.y
= 0.0f
;
4080 is_rtl
= analysis
->run
.bidiLevel
& 1;
4082 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4083 glyph_bitmap
.fontface
= fontface2
;
4084 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4085 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4086 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4087 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4088 glyph_bitmap
.m
= &analysis
->m
;
4090 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4091 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4092 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4093 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4094 RECT
*bbox
= &glyph_bitmap
.bbox
;
4096 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4097 freetype_get_glyph_bbox(&glyph_bitmap
);
4100 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4102 OffsetRect(bbox
, origin
.x
, origin
.y
);
4105 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4107 UnionRect(&analysis
->bounds
, &analysis
->bounds
, bbox
);
4108 origin
.x
+= advance
->x
;
4109 origin
.y
+= advance
->y
;
4112 IDWriteFontFace2_Release(fontface2
);
4114 /* translate to given run origin */
4115 OffsetRect(&analysis
->bounds
, analysis
->origin
.x
, analysis
->origin
.y
);
4116 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4117 OffsetRect(&analysis
->bounds
, analysis
->m
.dx
, analysis
->m
.dy
);
4119 analysis
->flags
|= RUNANALYSIS_BOUNDS_READY
;
4120 *bounds
= analysis
->bounds
;
4123 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
4125 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4127 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
4129 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4130 memset(bounds
, 0, sizeof(*bounds
));
4131 return E_INVALIDARG
;
4134 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
4135 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
4136 memset(bounds
, 0, sizeof(*bounds
));
4140 glyphrunanalysis_get_texturebounds(This
, bounds
);
4144 static inline int get_dib_stride( int width
, int bpp
)
4146 return ((width
* bpp
+ 31) >> 3) & ~3;
4149 static inline BYTE
*get_pixel_ptr(BYTE
*ptr
, DWRITE_TEXTURE_TYPE type
, const RECT
*runbounds
, const RECT
*bounds
)
4151 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4152 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) * 3 +
4153 (runbounds
->left
- bounds
->left
) * 3;
4155 return ptr
+ (runbounds
->top
- bounds
->top
) * (bounds
->right
- bounds
->left
) +
4156 runbounds
->left
- bounds
->left
;
4159 static void glyphrunanalysis_render(struct dwrite_glyphrunanalysis
*analysis
, DWRITE_TEXTURE_TYPE type
)
4161 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
4162 struct dwrite_glyphbitmap glyph_bitmap
;
4163 IDWriteFontFace2
*fontface2
;
4164 D2D_POINT_2F origin
;
4170 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
4172 WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr
);
4176 size
= (analysis
->bounds
.right
- analysis
->bounds
.left
)*(analysis
->bounds
.bottom
- analysis
->bounds
.top
);
4177 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4179 analysis
->bitmap
= heap_alloc_zero(size
);
4181 origin
.x
= origin
.y
= 0.0f
;
4182 is_rtl
= analysis
->run
.bidiLevel
& 1;
4184 memset(&glyph_bitmap
, 0, sizeof(glyph_bitmap
));
4185 glyph_bitmap
.fontface
= fontface2
;
4186 glyph_bitmap
.emsize
= analysis
->run
.fontEmSize
* analysis
->ppdip
;
4187 glyph_bitmap
.nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
||
4188 analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
4189 glyph_bitmap
.type
= type
;
4190 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4191 glyph_bitmap
.m
= &analysis
->m
;
4192 bbox
= &glyph_bitmap
.bbox
;
4194 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
4195 const D2D_POINT_2F
*advanceoffset
= analysis
->advanceoffsets
? analysis
->advanceoffsets
+ i
: NULL
;
4196 const D2D_POINT_2F
*ascenderoffset
= analysis
->ascenderoffsets
? analysis
->ascenderoffsets
+ i
: NULL
;
4197 const D2D_POINT_2F
*advance
= analysis
->advances
+ i
;
4198 int x
, y
, width
, height
;
4202 glyph_bitmap
.index
= analysis
->run
.glyphIndices
[i
];
4203 freetype_get_glyph_bbox(&glyph_bitmap
);
4205 if (IsRectEmpty(bbox
)) {
4206 origin
.x
+= advance
->x
;
4207 origin
.y
+= advance
->y
;
4211 width
= bbox
->right
- bbox
->left
;
4212 height
= bbox
->bottom
- bbox
->top
;
4214 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4215 glyph_bitmap
.pitch
= (width
+ 3) / 4 * 4;
4217 glyph_bitmap
.pitch
= ((width
+ 31) >> 5) << 2;
4219 glyph_bitmap
.buf
= src
= heap_alloc_zero(height
* glyph_bitmap
.pitch
);
4220 is_1bpp
= freetype_get_glyph_bitmap(&glyph_bitmap
);
4223 OffsetRect(bbox
, origin
.x
+ advance
->x
, origin
.y
+ advance
->y
);
4225 OffsetRect(bbox
, origin
.x
, origin
.y
);
4228 OffsetRect(bbox
, advanceoffset
->x
+ ascenderoffset
->x
, advanceoffset
->y
+ ascenderoffset
->y
);
4230 OffsetRect(bbox
, analysis
->origin
.x
, analysis
->origin
.y
);
4231 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4232 OffsetRect(bbox
, analysis
->m
.dx
, analysis
->m
.dy
);
4234 /* blit to analysis bitmap */
4235 dst
= get_pixel_ptr(analysis
->bitmap
, type
, bbox
, &analysis
->bounds
);
4238 /* convert 1bpp to 8bpp/24bpp */
4239 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
) {
4240 for (y
= 0; y
< height
; y
++) {
4241 for (x
= 0; x
< width
; x
++)
4242 if (src
[x
/ 8] & masks
[x
% 8])
4243 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = DWRITE_ALPHA_MAX
;
4244 src
+= glyph_bitmap
.pitch
;
4245 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4249 for (y
= 0; y
< height
; y
++) {
4250 for (x
= 0; x
< width
; x
++)
4251 if (src
[x
/ 8] & masks
[x
% 8])
4252 dst
[x
] = DWRITE_ALPHA_MAX
;
4253 src
+= get_dib_stride(width
, 1);
4254 dst
+= analysis
->bounds
.right
- analysis
->bounds
.left
;
4259 /* at this point it's DWRITE_TEXTURE_CLEARTYPE_3x1 with 8bpp src bitmap */
4260 for (y
= 0; y
< height
; y
++) {
4261 for (x
= 0; x
< width
; x
++)
4262 dst
[3*x
] = dst
[3*x
+1] = dst
[3*x
+2] = src
[x
] | dst
[3*x
];
4263 src
+= glyph_bitmap
.pitch
;
4264 dst
+= (analysis
->bounds
.right
- analysis
->bounds
.left
) * 3;
4268 heap_free(glyph_bitmap
.buf
);
4270 origin
.x
+= advance
->x
;
4271 origin
.y
+= advance
->y
;
4274 IDWriteFontFace2_Release(fontface2
);
4276 analysis
->flags
|= RUNANALYSIS_BITMAP_READY
;
4278 /* we don't need this anymore */
4279 heap_free(analysis
->glyphs
);
4280 heap_free(analysis
->advances
);
4281 heap_free(analysis
->advanceoffsets
);
4282 heap_free(analysis
->ascenderoffsets
);
4283 IDWriteFontFace_Release(analysis
->run
.fontFace
);
4285 analysis
->glyphs
= NULL
;
4286 analysis
->advances
= NULL
;
4287 analysis
->advanceoffsets
= NULL
;
4288 analysis
->ascenderoffsets
= NULL
;
4289 analysis
->run
.glyphIndices
= NULL
;
4290 analysis
->run
.fontFace
= NULL
;
4293 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
4294 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
4296 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4300 TRACE("(%p)->(%d %s %p %u)\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
4302 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
4303 return E_INVALIDARG
;
4305 /* make sure buffer is large enough for requested texture type */
4306 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
4307 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
4310 if (size
< required
)
4311 return E_NOT_SUFFICIENT_BUFFER
;
4313 /* validate requested texture type with rendering mode */
4314 switch (This
->rendering_mode
)
4316 case DWRITE_RENDERING_MODE_ALIASED
:
4317 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
4318 return DWRITE_E_UNSUPPORTEDOPERATION
;
4320 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4321 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4322 case DWRITE_RENDERING_MODE_NATURAL
:
4323 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4324 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
4325 return DWRITE_E_UNSUPPORTEDOPERATION
;
4331 memset(bitmap
, 0, size
);
4332 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
4333 if (IntersectRect(&runbounds
, &runbounds
, bounds
)) {
4334 int pixel_size
= type
== DWRITE_TEXTURE_CLEARTYPE_3x1
? 3 : 1;
4335 int src_width
= (This
->bounds
.right
- This
->bounds
.left
) * pixel_size
;
4336 int dst_width
= (bounds
->right
- bounds
->left
) * pixel_size
;
4337 int draw_width
= (runbounds
.right
- runbounds
.left
) * pixel_size
;
4341 if (!(This
->flags
& RUNANALYSIS_BITMAP_READY
))
4342 glyphrunanalysis_render(This
, type
);
4344 src
= get_pixel_ptr(This
->bitmap
, type
, &runbounds
, &This
->bounds
);
4345 dst
= get_pixel_ptr(bitmap
, type
, &runbounds
, bounds
);
4347 for (y
= 0; y
< runbounds
.bottom
- runbounds
.top
; y
++) {
4348 memcpy(dst
, src
, draw_width
);
4357 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
4358 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
4360 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
4362 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
4365 return E_INVALIDARG
;
4367 switch (This
->rendering_mode
)
4369 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
4370 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
4373 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
4374 *gamma
= (FLOAT
)value
/ 1000.0f
;
4376 *cleartypelevel
= 1.0f
;
4379 case DWRITE_RENDERING_MODE_ALIASED
:
4380 case DWRITE_RENDERING_MODE_NATURAL
:
4381 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
4382 *gamma
= IDWriteRenderingParams_GetGamma(params
);
4383 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
4384 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
4393 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
4394 glyphrunanalysis_QueryInterface
,
4395 glyphrunanalysis_AddRef
,
4396 glyphrunanalysis_Release
,
4397 glyphrunanalysis_GetAlphaTextureBounds
,
4398 glyphrunanalysis_CreateAlphaTexture
,
4399 glyphrunanalysis_GetAlphaBlendParams
4402 static inline void init_2d_vec(D2D_POINT_2F
*vec
, FLOAT length
, BOOL is_vertical
)
4414 static inline void transform_2d_vec(D2D_POINT_2F
*vec
, const DWRITE_MATRIX
*m
)
4417 ret
.x
= vec
->x
* m
->m11
+ vec
->y
* m
->m21
;
4418 ret
.y
= vec
->x
* m
->m12
+ vec
->y
* m
->m22
;
4422 HRESULT
create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_GLYPH_RUN
const *run
,
4423 FLOAT ppdip
, const DWRITE_MATRIX
*transform
, DWRITE_GRID_FIT_MODE gridfit_mode
, DWRITE_TEXT_ANTIALIAS_MODE aa_mode
,
4424 FLOAT originX
, FLOAT originY
, IDWriteGlyphRunAnalysis
**ret
)
4426 struct dwrite_glyphrunanalysis
*analysis
;
4432 /* check for valid rendering mode */
4433 if ((UINT32
)rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
4434 return E_INVALIDARG
;
4436 analysis
= heap_alloc(sizeof(*analysis
));
4438 return E_OUTOFMEMORY
;
4440 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
4442 analysis
->rendering_mode
= rendering_mode
;
4443 analysis
->flags
= 0;
4444 analysis
->bitmap
= NULL
;
4445 analysis
->ppdip
= ppdip
;
4446 analysis
->origin
.x
= originX
* ppdip
;
4447 analysis
->origin
.y
= originY
* ppdip
;
4448 SetRectEmpty(&analysis
->bounds
);
4449 analysis
->run
= *run
;
4450 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
4451 analysis
->glyphs
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphIndices
));
4452 analysis
->advances
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advances
));
4453 if (run
->glyphOffsets
) {
4454 analysis
->advanceoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->advanceoffsets
));
4455 analysis
->ascenderoffsets
= heap_alloc(run
->glyphCount
*sizeof(*analysis
->ascenderoffsets
));
4458 analysis
->advanceoffsets
= NULL
;
4459 analysis
->ascenderoffsets
= NULL
;
4462 if (!analysis
->glyphs
|| !analysis
->advances
|| ((!analysis
->advanceoffsets
|| !analysis
->ascenderoffsets
) && run
->glyphOffsets
)) {
4463 heap_free(analysis
->glyphs
);
4464 heap_free(analysis
->advances
);
4465 heap_free(analysis
->advanceoffsets
);
4466 heap_free(analysis
->ascenderoffsets
);
4468 analysis
->glyphs
= NULL
;
4469 analysis
->advances
= NULL
;
4470 analysis
->advanceoffsets
= NULL
;
4471 analysis
->ascenderoffsets
= NULL
;
4473 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
4474 return E_OUTOFMEMORY
;
4477 /* check if transform is usable */
4478 if (transform
&& memcmp(transform
, &identity
, sizeof(*transform
))) {
4479 analysis
->m
= *transform
;
4480 analysis
->flags
|= RUNANALYSIS_USE_TRANSFORM
;
4483 memset(&analysis
->m
, 0, sizeof(analysis
->m
));
4485 analysis
->run
.glyphIndices
= analysis
->glyphs
;
4486 analysis
->run
.glyphAdvances
= NULL
;
4487 analysis
->run
.glyphOffsets
= NULL
;
4489 rtl_factor
= run
->bidiLevel
& 1 ? -1.0f
: 1.0f
;
4491 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4492 transform_2d_vec(&analysis
->origin
, &analysis
->m
);
4494 memcpy(analysis
->glyphs
, run
->glyphIndices
, run
->glyphCount
*sizeof(*run
->glyphIndices
));
4496 if (run
->glyphAdvances
) {
4497 for (i
= 0; i
< run
->glyphCount
; i
++) {
4498 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* run
->glyphAdvances
[i
] * ppdip
, run
->isSideways
);
4499 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4500 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4504 DWRITE_FONT_METRICS metrics
;
4505 IDWriteFontFace1
*fontface1
;
4507 IDWriteFontFace_GetMetrics(run
->fontFace
, &metrics
);
4508 IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace1
, (void**)&fontface1
);
4510 for (i
= 0; i
< run
->glyphCount
; i
++) {
4514 switch (measuring_mode
)
4516 case DWRITE_MEASURING_MODE_NATURAL
:
4517 hr
= IDWriteFontFace1_GetDesignGlyphAdvances(fontface1
, 1, run
->glyphIndices
+ i
, &a
, run
->isSideways
);
4520 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* get_scaled_advance_width(a
, run
->fontEmSize
, &metrics
) * ppdip
,
4523 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
4524 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
4525 hr
= IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1
, run
->fontEmSize
, ppdip
, transform
,
4526 measuring_mode
== DWRITE_MEASURING_MODE_GDI_NATURAL
, run
->isSideways
, 1, run
->glyphIndices
+ i
, &a
);
4528 init_2d_vec(analysis
->advances
+ i
, 0.0f
, FALSE
);
4530 init_2d_vec(analysis
->advances
+ i
, rtl_factor
* floorf(a
* run
->fontEmSize
* ppdip
/ metrics
.designUnitsPerEm
+ 0.5f
),
4537 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
)
4538 transform_2d_vec(analysis
->advances
+ i
, &analysis
->m
);
4541 IDWriteFontFace1_Release(fontface1
);
4544 if (run
->glyphOffsets
) {
4545 for (i
= 0; i
< run
->glyphCount
; i
++) {
4546 init_2d_vec(analysis
->advanceoffsets
+ i
, rtl_factor
* run
->glyphOffsets
[i
].advanceOffset
* ppdip
, run
->isSideways
);
4547 /* Positive ascender offset moves glyph up. Keep it orthogonal to advance direction. */
4548 init_2d_vec(analysis
->ascenderoffsets
+ i
, -run
->glyphOffsets
[i
].ascenderOffset
* ppdip
, !run
->isSideways
);
4549 if (analysis
->flags
& RUNANALYSIS_USE_TRANSFORM
) {
4550 transform_2d_vec(analysis
->advanceoffsets
+ i
, &analysis
->m
);
4551 transform_2d_vec(analysis
->ascenderoffsets
+ i
, &analysis
->m
);
4556 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;
4560 /* IDWriteColorGlyphRunEnumerator */
4561 static HRESULT WINAPI
colorglyphenum_QueryInterface(IDWriteColorGlyphRunEnumerator
*iface
, REFIID riid
, void **ppv
)
4563 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4565 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
4567 if (IsEqualIID(riid
, &IID_IDWriteColorGlyphRunEnumerator
) ||
4568 IsEqualIID(riid
, &IID_IUnknown
))
4571 IDWriteColorGlyphRunEnumerator_AddRef(iface
);
4576 return E_NOINTERFACE
;
4579 static ULONG WINAPI
colorglyphenum_AddRef(IDWriteColorGlyphRunEnumerator
*iface
)
4581 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4582 ULONG ref
= InterlockedIncrement(&This
->ref
);
4583 TRACE("(%p)->(%u)\n", This
, ref
);
4587 static ULONG WINAPI
colorglyphenum_Release(IDWriteColorGlyphRunEnumerator
*iface
)
4589 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4590 ULONG ref
= InterlockedDecrement(&This
->ref
);
4592 TRACE("(%p)->(%u)\n", This
, ref
);
4600 static HRESULT WINAPI
colorglyphenum_MoveNext(IDWriteColorGlyphRunEnumerator
*iface
, BOOL
*has_run
)
4602 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4603 FIXME("(%p)->(%p): stub\n", This
, has_run
);
4607 static HRESULT WINAPI
colorglyphenum_GetCurrentRun(IDWriteColorGlyphRunEnumerator
*iface
, DWRITE_COLOR_GLYPH_RUN
const **run
)
4609 struct dwrite_colorglyphenum
*This
= impl_from_IDWriteColorGlyphRunEnumerator(iface
);
4610 FIXME("(%p)->(%p): stub\n", This
, run
);
4614 static const IDWriteColorGlyphRunEnumeratorVtbl colorglyphenumvtbl
= {
4615 colorglyphenum_QueryInterface
,
4616 colorglyphenum_AddRef
,
4617 colorglyphenum_Release
,
4618 colorglyphenum_MoveNext
,
4619 colorglyphenum_GetCurrentRun
4622 HRESULT
create_colorglyphenum(FLOAT originX
, FLOAT originY
, const DWRITE_GLYPH_RUN
*run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*rundescr
,
4623 DWRITE_MEASURING_MODE mode
, const DWRITE_MATRIX
*transform
, UINT32 palette
, IDWriteColorGlyphRunEnumerator
**ret
)
4625 struct dwrite_colorglyphenum
*colorglyphenum
;
4626 IDWriteFontFace2
*fontface2
;
4632 hr
= IDWriteFontFace_QueryInterface(run
->fontFace
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
4634 WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr
);
4638 colorfont
= IDWriteFontFace2_IsColorFont(fontface2
);
4639 IDWriteFontFace2_Release(fontface2
);
4641 return DWRITE_E_NOCOLOR
;
4643 colorglyphenum
= heap_alloc(sizeof(*colorglyphenum
));
4644 if (!colorglyphenum
)
4645 return E_OUTOFMEMORY
;
4647 colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
.lpVtbl
= &colorglyphenumvtbl
;
4648 colorglyphenum
->ref
= 1;
4650 *ret
= &colorglyphenum
->IDWriteColorGlyphRunEnumerator_iface
;