4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
5 * Copyright 2014 Aric Stewart for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/list.h"
25 #include "dwrite_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
29 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
30 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
31 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
32 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
34 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
36 struct dwrite_font_data
{
39 DWRITE_FONT_STYLE style
;
40 DWRITE_FONT_STRETCH stretch
;
41 DWRITE_FONT_WEIGHT weight
;
42 DWRITE_FONT_METRICS1 metrics
;
43 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
45 /* data needed to create fontface instance */
46 IDWriteFactory2
*factory
;
47 DWRITE_FONT_FACE_TYPE face_type
;
48 IDWriteFontFile
*file
;
54 struct dwrite_fontfamily_data
{
57 IDWriteLocalizedStrings
*familyname
;
59 struct dwrite_font_data
**fonts
;
64 struct dwrite_fontcollection
{
65 IDWriteFontCollection IDWriteFontCollection_iface
;
68 struct dwrite_fontfamily_data
**family_data
;
74 struct dwrite_fontfamily
{
75 IDWriteFontFamily IDWriteFontFamily_iface
;
78 struct dwrite_fontfamily_data
*data
;
80 IDWriteFontCollection
* collection
;
84 IDWriteFont2 IDWriteFont2_iface
;
87 IDWriteFontFamily
*family
;
90 DWRITE_FONT_STYLE style
;
91 struct dwrite_font_data
*data
;
94 struct dwrite_fonttable
{
100 #define GLYPH_BLOCK_SHIFT 8
101 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
102 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
103 #define GLYPH_MAX 65536
105 struct dwrite_fontface
{
106 IDWriteFontFace2 IDWriteFontFace2_iface
;
109 IDWriteFontFileStream
**streams
;
110 IDWriteFontFile
**files
;
115 DWRITE_FONT_FACE_TYPE type
;
116 DWRITE_FONT_METRICS1 metrics
;
117 DWRITE_CARET_METRICS caret
;
119 struct dwrite_fonttable cmap
;
120 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
123 struct dwrite_fontfile
{
124 IDWriteFontFile IDWriteFontFile_iface
;
127 IDWriteFontFileLoader
*loader
;
130 IDWriteFontFileStream
*stream
;
133 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace2(IDWriteFontFace2
*iface
)
135 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace2_iface
);
138 static inline struct dwrite_font
*impl_from_IDWriteFont2(IDWriteFont2
*iface
)
140 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont2_iface
);
143 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
145 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
148 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily(IDWriteFontFamily
*iface
)
150 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily_iface
);
153 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
155 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
158 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
160 static const DWRITE_GLYPH_METRICS nil
;
161 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
163 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
164 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
168 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
170 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
173 /* start new block */
174 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
176 return E_OUTOFMEMORY
;
179 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
183 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
188 if (fontface
->cmap
.data
)
189 return fontface
->cmap
.data
;
191 hr
= IDWriteFontFace2_TryGetFontTable(&fontface
->IDWriteFontFace2_iface
, MS_CMAP_TAG
, (const void**)&fontface
->cmap
.data
,
192 &fontface
->cmap
.size
, &fontface
->cmap
.context
, &exists
);
193 if (FAILED(hr
) || !exists
) {
194 ERR("Font does not have a CMAP table\n");
198 return fontface
->cmap
.data
;
201 static void release_font_data(struct dwrite_font_data
*data
)
205 if (InterlockedDecrement(&data
->ref
) > 0)
208 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
209 if (data
->info_strings
[i
])
210 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
213 IDWriteFontFile_Release(data
->file
);
214 IDWriteFactory2_Release(data
->factory
);
215 heap_free(data
->facename
);
219 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
223 if (InterlockedDecrement(&data
->ref
) > 0)
226 for (i
= 0; i
< data
->font_count
; i
++)
227 release_font_data(data
->fonts
[i
]);
228 heap_free(data
->fonts
);
229 IDWriteLocalizedStrings_Release(data
->familyname
);
233 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace2
*iface
, REFIID riid
, void **obj
)
235 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
237 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
239 if (IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
240 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
241 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
242 IsEqualIID(riid
, &IID_IUnknown
))
245 IDWriteFontFace2_AddRef(iface
);
250 return E_NOINTERFACE
;
253 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace2
*iface
)
255 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
256 ULONG ref
= InterlockedIncrement(&This
->ref
);
257 TRACE("(%p)->(%d)\n", This
, ref
);
261 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace2
*iface
)
263 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
264 ULONG ref
= InterlockedDecrement(&This
->ref
);
266 TRACE("(%p)->(%d)\n", This
, ref
);
271 if (This
->cmap
.context
)
272 IDWriteFontFace2_ReleaseFontTable(iface
, This
->cmap
.context
);
273 for (i
= 0; i
< This
->file_count
; i
++) {
274 if (This
->streams
[i
])
275 IDWriteFontFileStream_Release(This
->streams
[i
]);
277 IDWriteFontFile_Release(This
->files
[i
]);
280 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
281 heap_free(This
->glyphs
[i
]);
283 freetype_notify_cacheremove(iface
);
290 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace2
*iface
)
292 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
293 TRACE("(%p)\n", This
);
297 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace2
*iface
, UINT32
*number_of_files
,
298 IDWriteFontFile
**fontfiles
)
300 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
303 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
304 if (fontfiles
== NULL
)
306 *number_of_files
= This
->file_count
;
309 if (*number_of_files
< This
->file_count
)
312 for (i
= 0; i
< This
->file_count
; i
++)
314 IDWriteFontFile_AddRef(This
->files
[i
]);
315 fontfiles
[i
] = This
->files
[i
];
321 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace2
*iface
)
323 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
324 TRACE("(%p)\n", This
);
328 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace2
*iface
)
330 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
331 TRACE("(%p)\n", This
);
332 return This
->simulations
;
335 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace2
*iface
)
337 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
338 FIXME("(%p): stub\n", This
);
342 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS
*metrics
)
344 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
345 TRACE("(%p)->(%p)\n", This
, metrics
);
346 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
349 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace2
*iface
)
351 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
352 TRACE("(%p)\n", This
);
353 return freetype_get_glyphcount(iface
);
356 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2
*iface
,
357 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
359 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
363 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
369 FIXME("sideways metrics are not supported.\n");
371 for (i
= 0; i
< glyph_count
; i
++) {
372 DWRITE_GLYPH_METRICS metrics
;
374 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
376 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
377 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
387 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace2
*iface
, UINT32
const *codepoints
,
388 UINT32 count
, UINT16
*glyph_indices
)
390 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
393 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
399 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
403 for (i
= 0; i
< count
; i
++)
404 glyph_indices
[i
] = freetype_get_glyphindex(iface
, codepoints
[i
]);
409 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace2
*iface
, UINT32 table_tag
,
410 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
412 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
414 TRACE("(%p)->(%u %p %p %p %p)\n", This
, table_tag
, table_data
, table_size
, context
, exists
);
416 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
419 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace2
*iface
, void *table_context
)
421 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
423 TRACE("(%p)->(%p)\n", This
, table_context
);
425 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
428 HRESULT
new_glyph_outline(UINT32 count
, struct glyph_outline
**ret
)
430 struct glyph_outline
*outline
;
431 D2D1_POINT_2F
*points
;
436 outline
= heap_alloc(sizeof(*outline
));
438 return E_OUTOFMEMORY
;
440 points
= heap_alloc(count
*sizeof(D2D1_POINT_2F
));
441 tags
= heap_alloc(count
*sizeof(UINT8
));
442 if (!points
|| !tags
) {
446 return E_OUTOFMEMORY
;
449 outline
->points
= points
;
450 outline
->tags
= tags
;
451 outline
->count
= count
;
452 outline
->advance
= 0.0;
458 static void free_glyph_outline(struct glyph_outline
*outline
)
460 heap_free(outline
->points
);
461 heap_free(outline
->tags
);
465 static void report_glyph_outline(const struct glyph_outline
*outline
, IDWriteGeometrySink
*sink
)
469 for (p
= 0; p
< outline
->count
; p
++) {
470 if (outline
->tags
[p
] & OUTLINE_POINT_START
) {
471 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, outline
->points
[p
], D2D1_FIGURE_BEGIN_FILLED
);
475 if (outline
->tags
[p
] & OUTLINE_POINT_LINE
)
476 ID2D1SimplifiedGeometrySink_AddLines(sink
, outline
->points
+p
, 1);
477 else if (outline
->tags
[p
] & OUTLINE_POINT_BEZIER
) {
478 static const UINT16 segment_length
= 3;
479 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, (D2D1_BEZIER_SEGMENT
*)&outline
->points
[p
], 1);
480 p
+= segment_length
- 1;
483 if (outline
->tags
[p
] & OUTLINE_POINT_END
)
484 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
488 static inline void translate_glyph_outline(struct glyph_outline
*outline
, FLOAT xoffset
, FLOAT yoffset
)
492 for (p
= 0; p
< outline
->count
; p
++) {
493 outline
->points
[p
].x
+= xoffset
;
494 outline
->points
[p
].y
+= yoffset
;
498 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace2
*iface
, FLOAT emSize
,
499 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
500 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
502 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
507 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
508 count
, is_sideways
, is_rtl
, sink
);
510 if (!glyphs
|| !sink
)
514 FIXME("sideways mode is not supported.\n");
516 for (g
= 0; g
< count
; g
++) {
517 FLOAT xoffset
= 0.0, yoffset
= 0.0;
518 struct glyph_outline
*outline
;
520 /* FIXME: cache outlines */
522 hr
= freetype_get_glyph_outline(iface
, emSize
, glyphs
[g
], This
->simulations
, &outline
);
526 /* glyph offsets act as current glyph adjustment */
528 xoffset
+= is_rtl
? -offsets
[g
].advanceOffset
: offsets
[g
].advanceOffset
;
529 yoffset
-= offsets
[g
].ascenderOffset
;
533 advance
= is_rtl
? -outline
->advance
: 0.0;
536 translate_glyph_outline(outline
, xoffset
, yoffset
);
538 /* update advance to next glyph */
540 advance
+= is_rtl
? -advances
[g
] : advances
[g
];
542 advance
+= is_rtl
? -outline
->advance
: outline
->advance
;
544 report_glyph_outline(outline
, sink
);
545 free_glyph_outline(outline
);
551 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
552 FLOAT pixels_per_dip
, DWRITE_MEASURING_MODE mode
, IDWriteRenderingParams
* params
, DWRITE_RENDERING_MODE
* rendering_mode
)
554 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
555 FIXME("(%p)->(%f %f %d %p %p): stub\n", This
, emSize
, pixels_per_dip
, mode
, params
, rendering_mode
);
559 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
560 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
562 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
563 DWRITE_FONT_METRICS1 metrics1
;
566 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, emSize
, pixels_per_dip
, transform
, metrics
);
568 hr
= IDWriteFontFace2_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
572 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
576 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
577 DWRITE_MATRIX
const *transform
, BOOL use_gdi_natural
, UINT16
const *glyph_indices
, UINT32 glyph_count
,
578 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
580 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
581 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This
, emSize
, pixels_per_dip
, transform
, use_gdi_natural
, glyph_indices
,
582 glyph_count
, metrics
, is_sideways
);
586 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
588 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
589 TRACE("(%p)->(%p)\n", This
, metrics
);
590 *metrics
= This
->metrics
;
593 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
594 const DWRITE_MATRIX
*transform
, DWRITE_FONT_METRICS1
*metrics
)
596 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
597 FIXME("(%p)->(%f %f %p %p): stub\n", This
, em_size
, pixels_per_dip
, transform
, metrics
);
601 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace2
*iface
, DWRITE_CARET_METRICS
*metrics
)
603 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
604 TRACE("(%p)->(%p)\n", This
, metrics
);
605 *metrics
= This
->caret
;
608 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace2
*iface
, UINT32 max_count
,
609 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
611 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
613 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
616 if (max_count
&& !ranges
)
619 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
622 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace2
*iface
)
624 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
625 TRACE("(%p)\n", This
);
626 return freetype_is_monospaced(iface
);
629 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2
*iface
,
630 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
632 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
635 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
637 for (i
= 0; i
< glyph_count
; i
++) {
638 DWRITE_GLYPH_METRICS metrics
= { 0 };
641 hr
= IDWriteFontFace2_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &metrics
, is_sideways
);
645 advances
[i
] = is_sideways
? metrics
.advanceHeight
: metrics
.advanceWidth
;
651 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2
*iface
,
652 FLOAT em_size
, FLOAT pixels_per_dip
, const DWRITE_MATRIX
*transform
, BOOL use_gdi_natural
,
653 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *indices
, INT32
*advances
)
655 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
656 FIXME("(%p)->(%f %f %p %d %d %u %p %p): stub\n", This
, em_size
, pixels_per_dip
, transform
,
657 use_gdi_natural
, is_sideways
, glyph_count
, indices
, advances
);
661 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2
*iface
, UINT32 count
,
662 const UINT16
*indices
, INT32
*adjustments
)
664 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
667 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
669 if (!(indices
|| adjustments
) || !count
)
672 if (!indices
|| count
== 1) {
673 memset(adjustments
, 0, count
*sizeof(INT32
));
677 for (i
= 0; i
< count
-1; i
++)
678 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
679 adjustments
[count
-1] = 0;
684 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace2
*iface
)
686 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
687 TRACE("(%p)\n", This
);
688 return freetype_has_kerning_pairs(iface
);
691 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
,
692 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
693 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
695 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
696 FIXME("(%p)->(%f %f %f %p %d %d %d %p): stub\n", This
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
697 threshold
, measuring_mode
, rendering_mode
);
701 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2
*iface
, UINT32 glyph_count
,
702 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
704 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
705 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
709 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2
*iface
)
711 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
712 FIXME("(%p): stub\n", This
);
716 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace2
*iface
)
718 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
719 FIXME("(%p): stub\n", This
);
723 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace2
*iface
)
725 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
726 FIXME("(%p): stub\n", This
);
730 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2
*iface
)
732 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
733 FIXME("(%p): stub\n", This
);
737 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace2
*iface
, UINT32 palette_index
,
738 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
740 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
741 FIXME("(%p)->(%u %u %u %p): stub\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
745 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT fontEmSize
,
746 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
747 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
748 DWRITE_GRID_FIT_MODE
*gridfitmode
)
750 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
751 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This
, fontEmSize
, dpiX
, dpiY
, transform
, is_sideways
, threshold
,
752 measuringmode
, params
, renderingmode
, gridfitmode
);
756 static const IDWriteFontFace2Vtbl dwritefontfacevtbl
= {
757 dwritefontface_QueryInterface
,
758 dwritefontface_AddRef
,
759 dwritefontface_Release
,
760 dwritefontface_GetType
,
761 dwritefontface_GetFiles
,
762 dwritefontface_GetIndex
,
763 dwritefontface_GetSimulations
,
764 dwritefontface_IsSymbolFont
,
765 dwritefontface_GetMetrics
,
766 dwritefontface_GetGlyphCount
,
767 dwritefontface_GetDesignGlyphMetrics
,
768 dwritefontface_GetGlyphIndices
,
769 dwritefontface_TryGetFontTable
,
770 dwritefontface_ReleaseFontTable
,
771 dwritefontface_GetGlyphRunOutline
,
772 dwritefontface_GetRecommendedRenderingMode
,
773 dwritefontface_GetGdiCompatibleMetrics
,
774 dwritefontface_GetGdiCompatibleGlyphMetrics
,
775 dwritefontface1_GetMetrics
,
776 dwritefontface1_GetGdiCompatibleMetrics
,
777 dwritefontface1_GetCaretMetrics
,
778 dwritefontface1_GetUnicodeRanges
,
779 dwritefontface1_IsMonospacedFont
,
780 dwritefontface1_GetDesignGlyphAdvances
,
781 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
782 dwritefontface1_GetKerningPairAdjustments
,
783 dwritefontface1_HasKerningPairs
,
784 dwritefontface1_GetRecommendedRenderingMode
,
785 dwritefontface1_GetVerticalGlyphVariants
,
786 dwritefontface1_HasVerticalGlyphVariants
,
787 dwritefontface2_IsColorFont
,
788 dwritefontface2_GetColorPaletteCount
,
789 dwritefontface2_GetPaletteEntryCount
,
790 dwritefontface2_GetPaletteEntries
,
791 dwritefontface2_GetRecommendedRenderingMode
794 HRESULT
get_family_names_from_stream(IDWriteFontFileStream
*stream
, UINT32 index
, DWRITE_FONT_FACE_TYPE facetype
,
795 IDWriteLocalizedStrings
**names
)
797 const void *name_table
= NULL
;
801 opentype_get_font_table(stream
, facetype
, index
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
803 hr
= opentype_get_font_strings_from_id(name_table
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, names
);
804 IDWriteFontFileStream_ReleaseFileFragment(stream
, name_context
);
812 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace2
**fontface
)
814 struct dwrite_font_data
*data
= font
->data
;
815 IDWriteFontFace
*face
;
820 hr
= IDWriteFactory2_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
821 data
->face_index
, font
->simulations
, &face
);
825 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace2
, (void**)fontface
);
826 IDWriteFontFace_Release(face
);
831 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont2
*iface
, REFIID riid
, void **obj
)
833 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
835 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
837 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
838 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
839 IsEqualIID(riid
, &IID_IDWriteFont
) ||
840 IsEqualIID(riid
, &IID_IUnknown
))
843 IDWriteFont2_AddRef(iface
);
848 return E_NOINTERFACE
;
851 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont2
*iface
)
853 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
854 ULONG ref
= InterlockedIncrement(&This
->ref
);
855 TRACE("(%p)->(%d)\n", This
, ref
);
859 static ULONG WINAPI
dwritefont_Release(IDWriteFont2
*iface
)
861 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
862 ULONG ref
= InterlockedDecrement(&This
->ref
);
864 TRACE("(%p)->(%d)\n", This
, ref
);
867 IDWriteFontFamily_Release(This
->family
);
868 release_font_data(This
->data
);
875 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont2
*iface
, IDWriteFontFamily
**family
)
877 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
878 TRACE("(%p)->(%p)\n", This
, family
);
880 *family
= This
->family
;
881 IDWriteFontFamily_AddRef(*family
);
885 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont2
*iface
)
887 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
888 TRACE("(%p)\n", This
);
889 return This
->data
->weight
;
892 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont2
*iface
)
894 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
895 TRACE("(%p)\n", This
);
896 return This
->data
->stretch
;
899 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont2
*iface
)
901 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
902 TRACE("(%p)\n", This
);
906 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont2
*iface
)
908 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
909 IDWriteFontFace2
*fontface
;
912 TRACE("(%p)\n", This
);
914 hr
= get_fontface_from_font(This
, &fontface
);
918 return IDWriteFontFace2_IsSymbolFont(fontface
);
921 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont2
*iface
, IDWriteLocalizedStrings
**names
)
923 static const WCHAR boldobliqueW
[] = {'B','o','l','d',' ','O','b','l','i','q','u','e',0};
924 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
925 static const WCHAR boldW
[] = {'B','o','l','d',0};
926 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
928 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
929 IDWriteLocalizedStrings
*strings
;
933 TRACE("(%p)->(%p)\n", This
, names
);
937 if (This
->simulations
== DWRITE_FONT_SIMULATIONS_NONE
) {
939 return IDWriteFont2_GetInformationalStrings(iface
, DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES
,
943 switch (This
->simulations
) {
944 case DWRITE_FONT_SIMULATIONS_BOLD
|DWRITE_FONT_SIMULATIONS_OBLIQUE
:
947 case DWRITE_FONT_SIMULATIONS_BOLD
:
950 case DWRITE_FONT_SIMULATIONS_OBLIQUE
:
954 ERR("unknown simulations %d\n", This
->simulations
);
958 hr
= create_localizedstrings(&strings
);
959 if (FAILED(hr
)) return hr
;
961 hr
= add_localizedstring(strings
, enusW
, name
);
963 IDWriteLocalizedStrings_Release(strings
);
972 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont2
*iface
,
973 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
975 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
976 struct dwrite_font_data
*data
= This
->data
;
979 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
984 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
987 if (!data
->info_strings
[stringid
]) {
988 IDWriteFontFace2
*fontface
;
989 const void *table_data
;
994 hr
= get_fontface_from_font(This
, &fontface
);
998 table_exists
= FALSE
;
999 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1000 if (FAILED(hr
) || !table_exists
)
1001 WARN("no NAME table found.\n");
1004 hr
= opentype_get_font_strings_from_id(table_data
, stringid
, &data
->info_strings
[stringid
]);
1005 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1007 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
1011 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1019 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont2
*iface
)
1021 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1022 TRACE("(%p)\n", This
);
1023 return This
->simulations
;
1026 static void WINAPI
dwritefont_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS
*metrics
)
1028 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1030 TRACE("(%p)->(%p)\n", This
, metrics
);
1031 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1034 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont2
*iface
, UINT32 value
, BOOL
*exists
)
1036 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1037 IDWriteFontFace2
*fontface
;
1041 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1045 hr
= get_fontface_from_font(This
, &fontface
);
1050 hr
= IDWriteFontFace2_GetGlyphIndices(fontface
, &value
, 1, &index
);
1054 *exists
= index
!= 0;
1058 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont2
*iface
, IDWriteFontFace
**face
)
1060 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1063 TRACE("(%p)->(%p)\n", This
, face
);
1065 hr
= get_fontface_from_font(This
, (IDWriteFontFace2
**)face
);
1067 IDWriteFontFace_AddRef(*face
);
1072 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1074 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1075 TRACE("(%p)->(%p)\n", This
, metrics
);
1076 *metrics
= This
->data
->metrics
;
1079 static void WINAPI
dwritefont1_GetPanose(IDWriteFont2
*iface
, DWRITE_PANOSE
*panose
)
1081 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1082 FIXME("(%p)->(%p): stub\n", This
, panose
);
1085 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont2
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1087 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1088 IDWriteFontFace2
*fontface
;
1091 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1093 hr
= get_fontface_from_font(This
, &fontface
);
1097 return IDWriteFontFace2_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1100 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont2
*iface
)
1102 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1103 IDWriteFontFace2
*fontface
;
1106 TRACE("(%p)\n", This
);
1108 hr
= get_fontface_from_font(This
, &fontface
);
1112 return IDWriteFontFace2_IsMonospacedFont(fontface
);
1115 static HRESULT WINAPI
dwritefont2_IsColorFont(IDWriteFont2
*iface
)
1117 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1118 IDWriteFontFace2
*fontface
;
1121 TRACE("(%p)\n", This
);
1123 hr
= get_fontface_from_font(This
, &fontface
);
1127 return IDWriteFontFace2_IsColorFont(fontface
);
1130 static const IDWriteFont2Vtbl dwritefontvtbl
= {
1131 dwritefont_QueryInterface
,
1134 dwritefont_GetFontFamily
,
1135 dwritefont_GetWeight
,
1136 dwritefont_GetStretch
,
1137 dwritefont_GetStyle
,
1138 dwritefont_IsSymbolFont
,
1139 dwritefont_GetFaceNames
,
1140 dwritefont_GetInformationalStrings
,
1141 dwritefont_GetSimulations
,
1142 dwritefont_GetMetrics
,
1143 dwritefont_HasCharacter
,
1144 dwritefont_CreateFontFace
,
1145 dwritefont1_GetMetrics
,
1146 dwritefont1_GetPanose
,
1147 dwritefont1_GetUnicodeRanges
,
1148 dwritefont1_IsMonospacedFont
,
1149 dwritefont2_IsColorFont
1152 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily
*family
, DWRITE_FONT_SIMULATIONS simulations
,
1155 struct dwrite_font
*This
;
1158 This
= heap_alloc(sizeof(struct dwrite_font
));
1159 if (!This
) return E_OUTOFMEMORY
;
1161 This
->IDWriteFont2_iface
.lpVtbl
= &dwritefontvtbl
;
1163 This
->family
= family
;
1164 IDWriteFontFamily_AddRef(family
);
1165 This
->simulations
= simulations
;
1166 This
->style
= data
->style
;
1168 InterlockedIncrement(&This
->data
->ref
);
1170 /* set oblique style from requested simulation */
1171 if ((simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) && data
->style
== DWRITE_FONT_STYLE_NORMAL
)
1172 This
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
1174 *font
= (IDWriteFont
*)&This
->IDWriteFont2_iface
;
1179 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily
*iface
, REFIID riid
, void **obj
)
1181 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1182 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1184 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1185 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1186 IsEqualIID(riid
, &IID_IDWriteFontFamily
))
1189 IDWriteFontFamily_AddRef(iface
);
1194 return E_NOINTERFACE
;
1197 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily
*iface
)
1199 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1200 ULONG ref
= InterlockedIncrement(&This
->ref
);
1201 TRACE("(%p)->(%d)\n", This
, ref
);
1205 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily
*iface
)
1207 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1208 ULONG ref
= InterlockedDecrement(&This
->ref
);
1210 TRACE("(%p)->(%d)\n", This
, ref
);
1214 IDWriteFontCollection_Release(This
->collection
);
1215 release_fontfamily_data(This
->data
);
1222 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily
*iface
, IDWriteFontCollection
**collection
)
1224 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1225 TRACE("(%p)->(%p)\n", This
, collection
);
1227 *collection
= This
->collection
;
1228 IDWriteFontCollection_AddRef(This
->collection
);
1232 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily
*iface
)
1234 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1235 TRACE("(%p)\n", This
);
1236 return This
->data
->font_count
;
1239 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily
*iface
, UINT32 index
, IDWriteFont
**font
)
1241 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1243 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1247 if (This
->data
->font_count
== 0)
1250 if (index
>= This
->data
->font_count
)
1251 return E_INVALIDARG
;
1253 return create_font(This
->data
->fonts
[index
], iface
, DWRITE_FONT_SIMULATIONS_NONE
, font
);
1256 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily
*iface
, IDWriteLocalizedStrings
**names
)
1258 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1259 return clone_localizedstring(This
->data
->familyname
, names
);
1262 static inline BOOL
is_matching_font_style(DWRITE_FONT_STYLE style
, DWRITE_FONT_STYLE font_style
)
1264 if (style
== font_style
)
1267 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) && font_style
== DWRITE_FONT_STYLE_NORMAL
)
1273 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1274 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1276 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1277 UINT32 min_weight_diff
= ~0u;
1280 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1282 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1283 if (is_matching_font_style(style
, This
->data
->fonts
[i
]->style
) && stretch
== This
->data
->fonts
[i
]->stretch
) {
1284 DWRITE_FONT_WEIGHT font_weight
= This
->data
->fonts
[i
]->weight
;
1285 UINT32 weight_diff
= abs(font_weight
- weight
);
1286 if (weight_diff
< min_weight_diff
) {
1287 min_weight_diff
= weight_diff
;
1294 DWRITE_FONT_SIMULATIONS simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
1296 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) &&
1297 This
->data
->fonts
[found
]->style
== DWRITE_FONT_STYLE_NORMAL
) {
1298 simulations
= DWRITE_FONT_SIMULATIONS_OBLIQUE
;
1300 return create_font(This
->data
->fonts
[found
], iface
, simulations
, font
);
1304 return DWRITE_E_NOFONT
;
1308 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1309 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**fonts
)
1311 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1312 FIXME("(%p)->(%d %d %d %p): stub\n", This
, weight
, stretch
, style
, fonts
);
1316 static const IDWriteFontFamilyVtbl fontfamilyvtbl
= {
1317 dwritefontfamily_QueryInterface
,
1318 dwritefontfamily_AddRef
,
1319 dwritefontfamily_Release
,
1320 dwritefontfamily_GetFontCollection
,
1321 dwritefontfamily_GetFontCount
,
1322 dwritefontfamily_GetFont
,
1323 dwritefontfamily_GetFamilyNames
,
1324 dwritefontfamily_GetFirstMatchingFont
,
1325 dwritefontfamily_GetMatchingFonts
1328 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily
**family
)
1330 struct dwrite_fontfamily
*This
;
1334 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1335 if (!This
) return E_OUTOFMEMORY
;
1337 This
->IDWriteFontFamily_iface
.lpVtbl
= &fontfamilyvtbl
;
1339 This
->collection
= collection
;
1340 IDWriteFontCollection_AddRef(collection
);
1342 InterlockedIncrement(&This
->data
->ref
);
1344 *family
= &This
->IDWriteFontFamily_iface
;
1349 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1352 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1355 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
1357 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1358 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1360 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1361 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
1364 IDWriteFontCollection_AddRef(iface
);
1370 if (This
->is_system
&& IsEqualIID(riid
, &IID_issystemcollection
))
1373 return E_NOINTERFACE
;
1376 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection
*iface
)
1378 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1379 ULONG ref
= InterlockedIncrement(&This
->ref
);
1380 TRACE("(%p)->(%d)\n", This
, ref
);
1384 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection
*iface
)
1387 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1388 ULONG ref
= InterlockedDecrement(&This
->ref
);
1389 TRACE("(%p)->(%d)\n", This
, ref
);
1392 for (i
= 0; i
< This
->family_count
; i
++)
1393 release_fontfamily_data(This
->family_data
[i
]);
1394 heap_free(This
->family_data
);
1401 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
1403 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1404 TRACE("(%p)\n", This
);
1405 return This
->family_count
;
1408 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
1410 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1412 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
1414 if (index
>= This
->family_count
) {
1419 return create_fontfamily(This
->family_data
[index
], iface
, family
);
1422 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
1426 for (i
= 0; i
< collection
->family_count
; i
++) {
1427 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
1431 for (j
= 0; j
< IDWriteLocalizedStrings_GetCount(family_name
); j
++) {
1433 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
1434 if (SUCCEEDED(hr
) && !strcmpW(buffer
, name
))
1442 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
1444 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1445 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
1446 *index
= collection_find_family(This
, name
);
1447 *exists
= *index
!= ~0u;
1451 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
1453 UINT32 left_key_size
, right_key_size
;
1454 const void *left_key
, *right_key
;
1460 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
1464 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
1468 if (left_key_size
!= right_key_size
)
1471 return !memcmp(left_key
, right_key
, left_key_size
);
1474 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
1476 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1477 struct dwrite_fontfamily_data
*found_family
= NULL
;
1478 struct dwrite_font_data
*found_font
= NULL
;
1479 DWRITE_FONT_SIMULATIONS simulations
;
1480 IDWriteFontFamily
*family
;
1481 UINT32 i
, j
, face_index
;
1482 IDWriteFontFile
*file
;
1485 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
1490 return E_INVALIDARG
;
1493 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
1496 face_index
= IDWriteFontFace_GetIndex(face
);
1498 for (i
= 0; i
< This
->family_count
; i
++) {
1499 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
1500 for (j
= 0; j
< family_data
->font_count
; j
++) {
1501 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
1503 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
1504 found_font
= font_data
;
1505 found_family
= family_data
;
1512 return DWRITE_E_NOFONT
;
1514 hr
= create_fontfamily(found_family
, iface
, &family
);
1518 simulations
= IDWriteFontFace_GetSimulations(face
);
1519 hr
= create_font(found_font
, family
, simulations
, font
);
1520 IDWriteFontFamily_Release(family
);
1524 static const IDWriteFontCollectionVtbl fontcollectionvtbl
= {
1525 dwritefontcollection_QueryInterface
,
1526 dwritefontcollection_AddRef
,
1527 dwritefontcollection_Release
,
1528 dwritefontcollection_GetFontFamilyCount
,
1529 dwritefontcollection_GetFontFamily
,
1530 dwritefontcollection_FindFamilyName
,
1531 dwritefontcollection_GetFontFromFontFace
1534 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
1536 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
1537 struct dwrite_font_data
**new_list
;
1540 new_alloc
= family_data
->font_alloc
* 2;
1541 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
1543 return E_OUTOFMEMORY
;
1544 family_data
->fonts
= new_list
;
1545 family_data
->font_alloc
= new_alloc
;
1548 family_data
->fonts
[family_data
->font_count
] = font_data
;
1549 family_data
->font_count
++;
1553 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
1555 if (collection
->family_alloc
< collection
->family_count
+ 1) {
1556 struct dwrite_fontfamily_data
**new_list
;
1559 new_alloc
= collection
->family_alloc
* 2;
1560 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
1562 return E_OUTOFMEMORY
;
1564 collection
->family_alloc
= new_alloc
;
1565 collection
->family_data
= new_list
;
1568 collection
->family_data
[collection
->family_count
] = family
;
1569 collection
->family_count
++;
1574 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
1576 collection
->IDWriteFontCollection_iface
.lpVtbl
= &fontcollectionvtbl
;
1577 collection
->ref
= 1;
1578 collection
->family_count
= 0;
1579 collection
->family_alloc
= 2;
1580 collection
->is_system
= is_system
;
1582 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
)*2);
1583 if (!collection
->family_data
)
1584 return E_OUTOFMEMORY
;
1589 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
1591 IDWriteFontFileLoader
*loader
;
1598 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
1602 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
1606 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
1607 IDWriteFontFileLoader_Release(loader
);
1614 static HRESULT
init_font_data(IDWriteFactory2
*factory
, IDWriteFontFile
*file
, UINT32 face_index
, DWRITE_FONT_FACE_TYPE face_type
,
1615 IDWriteFontFileStream
**stream
, struct dwrite_font_data
**ret
)
1617 void *os2_context
, *head_context
;
1618 const void *tt_os2
= NULL
, *tt_head
= NULL
;
1619 struct dwrite_font_data
*data
;
1622 data
= heap_alloc_zero(sizeof(*data
));
1624 return E_OUTOFMEMORY
;
1626 hr
= get_filestream_from_file(file
, stream
);
1633 data
->factory
= factory
;
1635 data
->face_index
= face_index
;
1636 data
->face_type
= face_type
;
1637 IDWriteFontFile_AddRef(file
);
1638 IDWriteFactory2_AddRef(factory
);
1640 opentype_get_font_table(*stream
, face_type
, face_index
, MS_OS2_TAG
, &tt_os2
, &os2_context
, NULL
, NULL
);
1641 opentype_get_font_table(*stream
, face_type
, face_index
, MS_HEAD_TAG
, &tt_head
, &head_context
, NULL
, NULL
);
1643 opentype_get_font_properties(*stream
, face_type
, face_index
, &data
->stretch
, &data
->weight
, &data
->style
);
1644 opentype_get_font_metrics(*stream
, face_type
, face_index
, &data
->metrics
, NULL
);
1647 IDWriteFontFileStream_ReleaseFileFragment(*stream
, os2_context
);
1649 IDWriteFontFileStream_ReleaseFileFragment(*stream
, head_context
);
1655 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
1657 struct dwrite_fontfamily_data
*data
;
1659 data
= heap_alloc(sizeof(*data
));
1661 return E_OUTOFMEMORY
;
1664 data
->font_count
= 0;
1665 data
->font_alloc
= 2;
1667 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
1670 return E_OUTOFMEMORY
;
1673 data
->familyname
= familyname
;
1674 IDWriteLocalizedStrings_AddRef(familyname
);
1680 HRESULT
create_font_collection(IDWriteFactory2
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
1682 struct dwrite_fontcollection
*collection
;
1683 BOOL current
= FALSE
;
1688 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
1689 if (!collection
) return E_OUTOFMEMORY
;
1691 hr
= init_font_collection(collection
, is_system
);
1693 heap_free(collection
);
1697 *ret
= &collection
->IDWriteFontCollection_iface
;
1699 TRACE("building font collection:\n");
1701 while (hr
== S_OK
) {
1702 DWRITE_FONT_FACE_TYPE face_type
;
1703 DWRITE_FONT_FILE_TYPE file_type
;
1704 IDWriteFontFile
*file
;
1710 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
1711 if (FAILED(hr
) || !current
)
1714 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
1718 /* failed font files are skipped */
1719 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
1720 if (FAILED(hr
) || !supported
|| face_count
== 0) {
1721 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
1722 IDWriteFontFile_Release(file
);
1727 for (i
= 0; i
< face_count
; i
++) {
1728 IDWriteLocalizedStrings
*family_name
= NULL
;
1729 struct dwrite_font_data
*font_data
;
1730 IDWriteFontFileStream
*stream
;
1734 /* alloc and init new font data structure */
1735 hr
= init_font_data(factory
, file
, i
, face_type
, &stream
, &font_data
);
1739 /* get family name from font file */
1740 hr
= get_family_names_from_stream(stream
, i
, face_type
, &family_name
);
1741 IDWriteFontFileStream_Release(stream
);
1743 WARN("unable to get family name from font\n");
1744 release_font_data(font_data
);
1749 IDWriteLocalizedStrings_GetString(family_name
, 0, buffer
, sizeof(buffer
)/sizeof(WCHAR
));
1751 index
= collection_find_family(collection
, buffer
);
1753 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
1755 struct dwrite_fontfamily_data
*family_data
;
1757 /* create and init new family */
1758 hr
= init_fontfamily_data(family_name
, &family_data
);
1760 /* add font to family, family - to collection */
1761 hr
= fontfamily_add_font(family_data
, font_data
);
1763 hr
= fontcollection_add_family(collection
, family_data
);
1766 release_fontfamily_data(family_data
);
1770 IDWriteLocalizedStrings_Release(family_name
);
1776 IDWriteFontFile_Release(file
);
1782 struct system_fontfile_enumerator
1784 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
1787 IDWriteFactory2
*factory
;
1792 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
1794 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
1797 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
1801 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
1802 IDWriteFontFileEnumerator_AddRef(iface
);
1807 return E_NOINTERFACE
;
1810 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
1812 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1813 return InterlockedIncrement(&enumerator
->ref
);
1816 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
1818 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1819 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
1822 IDWriteFactory2_Release(enumerator
->factory
);
1823 RegCloseKey(enumerator
->hkey
);
1824 heap_free(enumerator
);
1830 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
1832 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1833 DWORD ret
, type
, count
;
1839 if (enumerator
->index
< 0)
1842 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, NULL
, NULL
, NULL
, &type
, NULL
, &count
))
1845 if (!(filename
= heap_alloc(count
)))
1846 return E_OUTOFMEMORY
;
1848 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, NULL
, NULL
, NULL
, &type
, (BYTE
*)filename
, &count
);
1850 heap_free(filename
);
1854 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
1855 if (!strchrW(filename
, '\\')) {
1856 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
1857 WCHAR fullpathW
[MAX_PATH
];
1859 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
1860 strcatW(fullpathW
, fontsW
);
1861 strcatW(fullpathW
, filename
);
1863 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, fullpathW
, NULL
, file
);
1866 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, filename
, NULL
, file
);
1868 heap_free(filename
);
1872 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
1874 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1877 enumerator
->index
++;
1879 /* iterate until we find next string value */
1881 DWORD type
= 0, count
;
1882 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, NULL
, NULL
, NULL
, &type
, NULL
, &count
))
1884 if (type
== REG_SZ
) {
1888 enumerator
->index
++;
1891 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
1895 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
1897 systemfontfileenumerator_QueryInterface
,
1898 systemfontfileenumerator_AddRef
,
1899 systemfontfileenumerator_Release
,
1900 systemfontfileenumerator_MoveNext
,
1901 systemfontfileenumerator_GetCurrentFontFile
1904 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory2
*factory
, IDWriteFontFileEnumerator
**ret
)
1906 struct system_fontfile_enumerator
*enumerator
;
1907 static const WCHAR fontslistW
[] = {
1908 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
1909 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1910 'F','o','n','t','s',0
1915 enumerator
= heap_alloc(sizeof(*enumerator
));
1917 return E_OUTOFMEMORY
;
1919 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
1920 enumerator
->ref
= 1;
1921 enumerator
->factory
= factory
;
1922 enumerator
->index
= -1;
1923 IDWriteFactory2_AddRef(factory
);
1925 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
1926 ERR("failed to open fonts list key\n");
1927 IDWriteFactory2_Release(factory
);
1928 heap_free(enumerator
);
1932 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
1937 HRESULT
get_system_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
1939 IDWriteFontFileEnumerator
*enumerator
;
1944 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
1948 TRACE("building system font collection for factory %p\n", factory
);
1949 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
1950 IDWriteFontFileEnumerator_Release(enumerator
);
1954 static HRESULT WINAPI
eudcfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
1958 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
1959 IDWriteFontFileEnumerator_AddRef(iface
);
1964 return E_NOINTERFACE
;
1967 static ULONG WINAPI
eudcfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
1972 static ULONG WINAPI
eudcfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
1977 static HRESULT WINAPI
eudcfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
1983 static HRESULT WINAPI
eudcfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
1989 static const struct IDWriteFontFileEnumeratorVtbl eudcfontfileenumeratorvtbl
=
1991 eudcfontfileenumerator_QueryInterface
,
1992 eudcfontfileenumerator_AddRef
,
1993 eudcfontfileenumerator_Release
,
1994 eudcfontfileenumerator_MoveNext
,
1995 eudcfontfileenumerator_GetCurrentFontFile
1998 static IDWriteFontFileEnumerator eudc_fontfile_enumerator
= { &eudcfontfileenumeratorvtbl
};
2000 HRESULT
get_eudc_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
2002 TRACE("building EUDC font collection for factory %p\n", factory
);
2003 return create_font_collection(factory
, &eudc_fontfile_enumerator
, FALSE
, collection
);
2006 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
2008 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2010 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2012 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
2015 IDWriteFontFile_AddRef(iface
);
2020 return E_NOINTERFACE
;
2023 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
2025 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2026 ULONG ref
= InterlockedIncrement(&This
->ref
);
2027 TRACE("(%p)->(%d)\n", This
, ref
);
2031 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
2033 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2034 ULONG ref
= InterlockedDecrement(&This
->ref
);
2036 TRACE("(%p)->(%d)\n", This
, ref
);
2040 IDWriteFontFileLoader_Release(This
->loader
);
2041 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
2042 heap_free(This
->reference_key
);
2049 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
2051 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2052 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
2053 *fontFileReferenceKey
= This
->reference_key
;
2054 *fontFileReferenceKeySize
= This
->key_size
;
2059 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
2061 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2062 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
2063 *fontFileLoader
= This
->loader
;
2064 IDWriteFontFileLoader_AddRef(This
->loader
);
2069 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
, DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
2071 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2072 IDWriteFontFileStream
*stream
;
2075 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
2077 *isSupportedFontType
= FALSE
;
2078 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
2080 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
2083 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
2087 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
2089 /* TODO: Further Analysis */
2090 IDWriteFontFileStream_Release(stream
);
2094 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
2095 dwritefontfile_QueryInterface
,
2096 dwritefontfile_AddRef
,
2097 dwritefontfile_Release
,
2098 dwritefontfile_GetReferenceKey
,
2099 dwritefontfile_GetLoader
,
2100 dwritefontfile_Analyze
,
2103 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
2105 struct dwrite_fontfile
*This
;
2107 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
2108 if (!This
) return E_OUTOFMEMORY
;
2110 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
2112 IDWriteFontFileLoader_AddRef(loader
);
2113 This
->loader
= loader
;
2114 This
->stream
= NULL
;
2115 This
->reference_key
= heap_alloc(key_size
);
2116 memcpy(This
->reference_key
, reference_key
, key_size
);
2117 This
->key_size
= key_size
;
2119 *font_file
= &This
->IDWriteFontFile_iface
;
2124 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2126 IDWriteFontFileLoader
*loader
;
2132 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2136 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2138 IDWriteFontFileLoader_Release(loader
);
2142 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2143 IDWriteFontFileLoader_Release(loader
);
2148 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
2149 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace2
**ret
)
2151 struct dwrite_fontface
*fontface
;
2157 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
2159 return E_OUTOFMEMORY
;
2161 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
2162 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
2164 if (!fontface
->files
|| !fontface
->streams
) {
2165 heap_free(fontface
->files
);
2166 heap_free(fontface
->streams
);
2167 heap_free(fontface
);
2168 return E_OUTOFMEMORY
;
2171 fontface
->IDWriteFontFace2_iface
.lpVtbl
= &dwritefontfacevtbl
;
2173 fontface
->type
= facetype
;
2174 fontface
->file_count
= files_number
;
2175 fontface
->cmap
.data
= NULL
;
2176 fontface
->cmap
.context
= NULL
;
2177 fontface
->cmap
.size
= 0;
2178 fontface
->index
= index
;
2179 fontface
->simulations
= simulations
;
2180 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
2182 for (i
= 0; i
< fontface
->file_count
; i
++) {
2183 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
2185 IDWriteFontFace2_Release(&fontface
->IDWriteFontFace2_iface
);
2189 fontface
->files
[i
] = font_files
[i
];
2190 IDWriteFontFile_AddRef(font_files
[i
]);
2193 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
2194 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
2195 /* TODO: test what happens if caret is already slanted */
2196 if (fontface
->caret
.slopeRise
== 1) {
2197 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
2198 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
2202 *ret
= &fontface
->IDWriteFontFace2_iface
;
2206 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
2213 struct local_cached_stream
2216 IDWriteFontFileStream
*stream
;
2217 struct local_refkey
*key
;
2221 struct dwrite_localfontfilestream
2223 IDWriteFontFileStream IDWriteFontFileStream_iface
;
2226 struct local_cached_stream
*entry
;
2227 const void *file_ptr
;
2231 struct dwrite_localfontfileloader
{
2232 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
2235 struct list streams
;
2238 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
2240 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
2243 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
2245 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
2248 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
2250 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2251 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2252 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
2255 IDWriteFontFileStream_AddRef(iface
);
2260 return E_NOINTERFACE
;
2263 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
2265 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2266 ULONG ref
= InterlockedIncrement(&This
->ref
);
2267 TRACE("(%p)->(%d)\n", This
, ref
);
2271 static inline void release_cached_stream(struct local_cached_stream
*stream
)
2273 list_remove(&stream
->entry
);
2274 heap_free(stream
->key
);
2278 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
2280 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2281 ULONG ref
= InterlockedDecrement(&This
->ref
);
2283 TRACE("(%p)->(%d)\n", This
, ref
);
2286 UnmapViewOfFile(This
->file_ptr
);
2287 release_cached_stream(This
->entry
);
2294 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
2296 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2298 TRACE("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
2299 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
2301 *fragment_context
= NULL
;
2303 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
2304 *fragment_start
= NULL
;
2308 *fragment_start
= (char*)This
->file_ptr
+ offset
;
2312 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
2314 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2315 TRACE("(%p)->(%p)\n", This
, fragment_context
);
2318 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
2320 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2321 TRACE("(%p)->(%p)\n", This
, size
);
2326 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
2328 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2331 TRACE("(%p)->(%p)\n", This
, last_writetime
);
2333 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
2334 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
2335 *last_writetime
= li
.QuadPart
;
2340 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
2342 localfontfilestream_QueryInterface
,
2343 localfontfilestream_AddRef
,
2344 localfontfilestream_Release
,
2345 localfontfilestream_ReadFileFragment
,
2346 localfontfilestream_ReleaseFileFragment
,
2347 localfontfilestream_GetFileSize
,
2348 localfontfilestream_GetLastWriteTime
2351 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
** iface
)
2353 struct dwrite_localfontfilestream
*This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
2355 return E_OUTOFMEMORY
;
2357 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
2360 This
->file_ptr
= file_ptr
;
2362 This
->entry
= entry
;
2364 *iface
= &This
->IDWriteFontFileStream_iface
;
2368 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
2370 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2372 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2374 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
2377 IDWriteLocalFontFileLoader_AddRef(iface
);
2382 return E_NOINTERFACE
;
2385 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
2387 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2388 ULONG ref
= InterlockedIncrement(&This
->ref
);
2389 TRACE("(%p)->(%d)\n", This
, ref
);
2393 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
2395 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2396 ULONG ref
= InterlockedDecrement(&This
->ref
);
2398 TRACE("(%p)->(%d)\n", This
, ref
);
2401 struct local_cached_stream
*stream
, *stream2
;
2403 /* This will detach all entries from cache. Entries are released together with streams,
2404 so stream controls its lifetime. */
2405 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
2406 list_init(&stream
->entry
);
2414 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
2416 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2417 const struct local_refkey
*refkey
= key
;
2418 struct local_cached_stream
*stream
;
2419 IDWriteFontFileStream
*filestream
;
2420 HANDLE file
, mapping
;
2425 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
2426 TRACE("name: %s\n", debugstr_w(refkey
->name
));
2428 /* search cache first */
2429 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
2430 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
2431 *ret
= stream
->stream
;
2432 IDWriteFontFileStream_AddRef(*ret
);
2439 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2440 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2441 if (file
== INVALID_HANDLE_VALUE
)
2444 GetFileSizeEx(file
, &size
);
2445 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
2450 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
2451 CloseHandle(mapping
);
2453 stream
= heap_alloc(sizeof(*stream
));
2455 UnmapViewOfFile(file_ptr
);
2456 return E_OUTOFMEMORY
;
2459 stream
->key
= heap_alloc(key_size
);
2461 UnmapViewOfFile(file_ptr
);
2463 return E_OUTOFMEMORY
;
2466 stream
->key_size
= key_size
;
2467 memcpy(stream
->key
, key
, key_size
);
2469 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
2471 UnmapViewOfFile(file_ptr
);
2472 heap_free(stream
->key
);
2477 stream
->stream
= filestream
;
2478 list_add_head(&This
->streams
, &stream
->entry
);
2480 *ret
= stream
->stream
;
2485 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
2487 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2488 const struct local_refkey
*refkey
= key
;
2490 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
2492 *length
= strlenW(refkey
->name
);
2496 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
2498 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2499 const struct local_refkey
*refkey
= key
;
2501 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
2503 if (length
< strlenW(refkey
->name
))
2504 return E_INVALIDARG
;
2506 strcpyW(path
, refkey
->name
);
2510 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
2512 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2513 const struct local_refkey
*refkey
= key
;
2515 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
2517 *writetime
= refkey
->writetime
;
2521 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
2522 localfontfileloader_QueryInterface
,
2523 localfontfileloader_AddRef
,
2524 localfontfileloader_Release
,
2525 localfontfileloader_CreateStreamFromKey
,
2526 localfontfileloader_GetFilePathLengthFromKey
,
2527 localfontfileloader_GetFilePathFromKey
,
2528 localfontfileloader_GetLastWriteTimeFromKey
2531 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
** iface
)
2533 struct dwrite_localfontfileloader
*This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
2535 return E_OUTOFMEMORY
;
2537 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
2539 list_init(&This
->streams
);
2541 *iface
= &This
->IDWriteLocalFontFileLoader_iface
;
2545 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
2547 struct local_refkey
*refkey
;
2549 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
2552 refkey
= heap_alloc(*size
);
2554 return E_OUTOFMEMORY
;
2557 refkey
->writetime
= *writetime
;
2559 WIN32_FILE_ATTRIBUTE_DATA info
;
2561 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
2562 refkey
->writetime
= info
.ftLastWriteTime
;
2564 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
2566 strcpyW(refkey
->name
, path
);