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
25 #include "wine/list.h"
26 #include "dwrite_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
30 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
31 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
32 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
33 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
34 #define MS_VDMX_TAG DWRITE_MAKE_OPENTYPE_TAG('V','D','M','X')
36 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
38 struct dwrite_font_data
{
41 DWRITE_FONT_STYLE style
;
42 DWRITE_FONT_STRETCH stretch
;
43 DWRITE_FONT_WEIGHT weight
;
45 DWRITE_FONT_METRICS1 metrics
;
46 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
48 /* data needed to create fontface instance */
49 IDWriteFactory2
*factory
;
50 DWRITE_FONT_FACE_TYPE face_type
;
51 IDWriteFontFile
*file
;
57 struct dwrite_fontfamily_data
{
60 IDWriteLocalizedStrings
*familyname
;
62 struct dwrite_font_data
**fonts
;
67 struct dwrite_fontcollection
{
68 IDWriteFontCollection IDWriteFontCollection_iface
;
71 struct dwrite_fontfamily_data
**family_data
;
77 struct dwrite_fontfamily
{
78 IDWriteFontFamily IDWriteFontFamily_iface
;
81 struct dwrite_fontfamily_data
*data
;
83 IDWriteFontCollection
* collection
;
87 IDWriteFont2 IDWriteFont2_iface
;
90 IDWriteFontFamily
*family
;
93 DWRITE_FONT_STYLE style
;
94 struct dwrite_font_data
*data
;
97 struct dwrite_fonttable
{
104 struct dwrite_glyphrunanalysis
{
105 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
109 #define GLYPH_BLOCK_SHIFT 8
110 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
111 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
112 #define GLYPH_MAX 65536
114 struct dwrite_fontface
{
115 IDWriteFontFace2 IDWriteFontFace2_iface
;
118 IDWriteFontFileStream
**streams
;
119 IDWriteFontFile
**files
;
124 DWRITE_FONT_FACE_TYPE type
;
125 DWRITE_FONT_METRICS1 metrics
;
126 DWRITE_CARET_METRICS caret
;
128 struct dwrite_fonttable cmap
;
129 struct dwrite_fonttable vdmx
;
130 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
133 struct dwrite_fontfile
{
134 IDWriteFontFile IDWriteFontFile_iface
;
137 IDWriteFontFileLoader
*loader
;
140 IDWriteFontFileStream
*stream
;
143 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace2(IDWriteFontFace2
*iface
)
145 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace2_iface
);
148 static inline struct dwrite_font
*impl_from_IDWriteFont2(IDWriteFont2
*iface
)
150 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont2_iface
);
153 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
155 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
158 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily(IDWriteFontFamily
*iface
)
160 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily_iface
);
163 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
165 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
168 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
170 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
173 static inline const char *debugstr_tag(UINT32 tag
)
175 return wine_dbg_sprintf("%c%c%c%c", tag
>> 24, (tag
>> 16) & 0xff, (tag
>> 8) & 0xff, tag
& 0xff);
178 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
180 static const DWRITE_GLYPH_METRICS nil
;
181 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
183 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
184 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
188 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
190 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
193 /* start new block */
194 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
196 return E_OUTOFMEMORY
;
199 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
203 static void* get_fontface_table(struct dwrite_fontface
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
207 if (table
->data
|| !table
->exists
)
210 table
->exists
= FALSE
;
211 hr
= IDWriteFontFace2_TryGetFontTable(&fontface
->IDWriteFontFace2_iface
, tag
, (const void**)&table
->data
,
212 &table
->size
, &table
->context
, &table
->exists
);
213 if (FAILED(hr
) || !table
->exists
) {
214 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
221 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
223 return get_fontface_table(fontface
, MS_CMAP_TAG
, &fontface
->cmap
);
226 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
228 return get_fontface_table(fontface
, MS_VDMX_TAG
, &fontface
->vdmx
);
231 static void release_font_data(struct dwrite_font_data
*data
)
235 if (InterlockedDecrement(&data
->ref
) > 0)
238 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
239 if (data
->info_strings
[i
])
240 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
243 IDWriteFontFile_Release(data
->file
);
244 IDWriteFactory2_Release(data
->factory
);
245 heap_free(data
->facename
);
249 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
253 if (InterlockedDecrement(&data
->ref
) > 0)
256 for (i
= 0; i
< data
->font_count
; i
++)
257 release_font_data(data
->fonts
[i
]);
258 heap_free(data
->fonts
);
259 IDWriteLocalizedStrings_Release(data
->familyname
);
263 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace2
*iface
, REFIID riid
, void **obj
)
265 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
267 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
269 if (IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
270 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
271 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
272 IsEqualIID(riid
, &IID_IUnknown
))
275 IDWriteFontFace2_AddRef(iface
);
280 return E_NOINTERFACE
;
283 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace2
*iface
)
285 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
286 ULONG ref
= InterlockedIncrement(&This
->ref
);
287 TRACE("(%p)->(%d)\n", This
, ref
);
291 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace2
*iface
)
293 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
294 ULONG ref
= InterlockedDecrement(&This
->ref
);
296 TRACE("(%p)->(%d)\n", This
, ref
);
301 if (This
->cmap
.context
)
302 IDWriteFontFace2_ReleaseFontTable(iface
, This
->cmap
.context
);
303 if (This
->vdmx
.context
)
304 IDWriteFontFace2_ReleaseFontTable(iface
, This
->vdmx
.context
);
305 for (i
= 0; i
< This
->file_count
; i
++) {
306 if (This
->streams
[i
])
307 IDWriteFontFileStream_Release(This
->streams
[i
]);
309 IDWriteFontFile_Release(This
->files
[i
]);
312 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
313 heap_free(This
->glyphs
[i
]);
315 freetype_notify_cacheremove(iface
);
322 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace2
*iface
)
324 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
325 TRACE("(%p)\n", This
);
329 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace2
*iface
, UINT32
*number_of_files
,
330 IDWriteFontFile
**fontfiles
)
332 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
335 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
336 if (fontfiles
== NULL
)
338 *number_of_files
= This
->file_count
;
341 if (*number_of_files
< This
->file_count
)
344 for (i
= 0; i
< This
->file_count
; i
++)
346 IDWriteFontFile_AddRef(This
->files
[i
]);
347 fontfiles
[i
] = This
->files
[i
];
353 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace2
*iface
)
355 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
356 TRACE("(%p)\n", This
);
360 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace2
*iface
)
362 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
363 TRACE("(%p)\n", This
);
364 return This
->simulations
;
367 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace2
*iface
)
369 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
370 FIXME("(%p): stub\n", This
);
374 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS
*metrics
)
376 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
377 TRACE("(%p)->(%p)\n", This
, metrics
);
378 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
381 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace2
*iface
)
383 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
384 TRACE("(%p)\n", This
);
385 return freetype_get_glyphcount(iface
);
388 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2
*iface
,
389 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
391 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
395 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
401 FIXME("sideways metrics are not supported.\n");
403 for (i
= 0; i
< glyph_count
; i
++) {
404 DWRITE_GLYPH_METRICS metrics
;
406 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
408 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
409 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
419 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace2
*iface
, UINT32
const *codepoints
,
420 UINT32 count
, UINT16
*glyph_indices
)
422 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
425 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
431 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
435 for (i
= 0; i
< count
; i
++)
436 glyph_indices
[i
] = freetype_get_glyphindex(iface
, codepoints
[i
]);
441 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace2
*iface
, UINT32 table_tag
,
442 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
444 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
446 TRACE("(%p)->(%u %p %p %p %p)\n", This
, table_tag
, table_data
, table_size
, context
, exists
);
448 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
451 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace2
*iface
, void *table_context
)
453 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
455 TRACE("(%p)->(%p)\n", This
, table_context
);
457 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
460 HRESULT
new_glyph_outline(UINT32 count
, struct glyph_outline
**ret
)
462 struct glyph_outline
*outline
;
463 D2D1_POINT_2F
*points
;
468 outline
= heap_alloc(sizeof(*outline
));
470 return E_OUTOFMEMORY
;
472 points
= heap_alloc(count
*sizeof(D2D1_POINT_2F
));
473 tags
= heap_alloc_zero(count
*sizeof(UINT8
));
474 if (!points
|| !tags
) {
478 return E_OUTOFMEMORY
;
481 outline
->points
= points
;
482 outline
->tags
= tags
;
483 outline
->count
= count
;
484 outline
->advance
= 0.0;
490 static void free_glyph_outline(struct glyph_outline
*outline
)
492 heap_free(outline
->points
);
493 heap_free(outline
->tags
);
497 static void report_glyph_outline(const struct glyph_outline
*outline
, IDWriteGeometrySink
*sink
)
501 for (p
= 0; p
< outline
->count
; p
++) {
502 if (outline
->tags
[p
] & OUTLINE_POINT_START
) {
503 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, outline
->points
[p
], D2D1_FIGURE_BEGIN_FILLED
);
507 if (outline
->tags
[p
] & OUTLINE_POINT_LINE
)
508 ID2D1SimplifiedGeometrySink_AddLines(sink
, outline
->points
+p
, 1);
509 else if (outline
->tags
[p
] & OUTLINE_POINT_BEZIER
) {
510 static const UINT16 segment_length
= 3;
511 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, (D2D1_BEZIER_SEGMENT
*)&outline
->points
[p
], 1);
512 p
+= segment_length
- 1;
515 if (outline
->tags
[p
] & OUTLINE_POINT_END
)
516 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
520 static inline void translate_glyph_outline(struct glyph_outline
*outline
, FLOAT xoffset
, FLOAT yoffset
)
524 for (p
= 0; p
< outline
->count
; p
++) {
525 outline
->points
[p
].x
+= xoffset
;
526 outline
->points
[p
].y
+= yoffset
;
530 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace2
*iface
, FLOAT emSize
,
531 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
532 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
534 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
539 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
540 count
, is_sideways
, is_rtl
, sink
);
542 if (!glyphs
|| !sink
)
546 FIXME("sideways mode is not supported.\n");
549 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
551 for (g
= 0; g
< count
; g
++) {
552 FLOAT xoffset
= 0.0, yoffset
= 0.0;
553 struct glyph_outline
*outline
;
555 /* FIXME: cache outlines */
557 hr
= freetype_get_glyph_outline(iface
, emSize
, glyphs
[g
], This
->simulations
, &outline
);
561 /* glyph offsets act as current glyph adjustment */
563 xoffset
+= is_rtl
? -offsets
[g
].advanceOffset
: offsets
[g
].advanceOffset
;
564 yoffset
-= offsets
[g
].ascenderOffset
;
568 advance
= is_rtl
? -outline
->advance
: 0.0;
571 translate_glyph_outline(outline
, xoffset
, yoffset
);
573 /* update advance to next glyph */
575 advance
+= is_rtl
? -advances
[g
] : advances
[g
];
577 advance
+= is_rtl
? -outline
->advance
: outline
->advance
;
579 report_glyph_outline(outline
, sink
);
580 free_glyph_outline(outline
);
586 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
587 FLOAT pixels_per_dip
, DWRITE_MEASURING_MODE mode
, IDWriteRenderingParams
* params
, DWRITE_RENDERING_MODE
* rendering_mode
)
589 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
590 FIXME("(%p)->(%f %f %d %p %p): stub\n", This
, emSize
, pixels_per_dip
, mode
, params
, rendering_mode
);
594 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
595 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
597 DWRITE_FONT_METRICS1 metrics1
;
598 HRESULT hr
= IDWriteFontFace2_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
599 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
603 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
604 DWRITE_MATRIX
const *transform
, BOOL use_gdi_natural
, UINT16
const *glyph_indices
, UINT32 glyph_count
,
605 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
607 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
608 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This
, emSize
, pixels_per_dip
, transform
, use_gdi_natural
, glyph_indices
,
609 glyph_count
, metrics
, is_sideways
);
613 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
615 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
616 TRACE("(%p)->(%p)\n", This
, metrics
);
617 *metrics
= This
->metrics
;
620 static inline int round_metric(FLOAT metric
)
622 return (int)floorf(metric
+ 0.5f
);
625 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
626 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
628 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
629 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
630 UINT16 ascent
, descent
;
633 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
635 if (em_size
<= 0.0 || pixels_per_dip
<= 0.0) {
636 memset(metrics
, 0, sizeof(*metrics
));
640 em_size
*= pixels_per_dip
;
641 if (m
&& m
->m22
!= 0.0)
642 em_size
*= fabs(m
->m22
);
644 scale
= em_size
/ design
->designUnitsPerEm
;
645 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
646 ascent
= round_metric(design
->ascent
* scale
);
647 descent
= round_metric(design
->descent
* scale
);
650 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
651 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
652 metrics
->ascent
= round_metric(ascent
/ scale
);
653 metrics
->descent
= round_metric(descent
/ scale
);
655 SCALE_METRIC(lineGap
);
656 SCALE_METRIC(capHeight
);
657 SCALE_METRIC(xHeight
);
658 SCALE_METRIC(underlinePosition
);
659 SCALE_METRIC(underlineThickness
);
660 SCALE_METRIC(strikethroughPosition
);
661 SCALE_METRIC(strikethroughThickness
);
662 SCALE_METRIC(glyphBoxLeft
);
663 SCALE_METRIC(glyphBoxTop
);
664 SCALE_METRIC(glyphBoxRight
);
665 SCALE_METRIC(glyphBoxBottom
);
666 SCALE_METRIC(subscriptPositionX
);
667 SCALE_METRIC(subscriptPositionY
);
668 SCALE_METRIC(subscriptSizeX
);
669 SCALE_METRIC(subscriptSizeY
);
670 SCALE_METRIC(superscriptPositionX
);
671 SCALE_METRIC(superscriptPositionY
);
672 SCALE_METRIC(superscriptSizeX
);
673 SCALE_METRIC(superscriptSizeY
);
675 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
681 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace2
*iface
, DWRITE_CARET_METRICS
*metrics
)
683 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
684 TRACE("(%p)->(%p)\n", This
, metrics
);
685 *metrics
= This
->caret
;
688 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace2
*iface
, UINT32 max_count
,
689 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
691 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
693 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
696 if (max_count
&& !ranges
)
699 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
702 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace2
*iface
)
704 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
705 TRACE("(%p)\n", This
);
706 return freetype_is_monospaced(iface
);
709 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2
*iface
,
710 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
712 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
715 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
717 for (i
= 0; i
< glyph_count
; i
++) {
718 DWRITE_GLYPH_METRICS metrics
= { 0 };
721 hr
= IDWriteFontFace2_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &metrics
, is_sideways
);
725 advances
[i
] = is_sideways
? metrics
.advanceHeight
: metrics
.advanceWidth
;
731 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2
*iface
,
732 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
733 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
735 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
739 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
740 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
742 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
743 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
745 for (i
= 0; i
< glyph_count
; i
++) {
748 hr
= IDWriteFontFace2_GetDesignGlyphAdvances(iface
, 1, glyphs
+ i
, advances
+ i
, is_sideways
);
752 scale
= em_size
* ppdip
/ This
->metrics
.designUnitsPerEm
;
753 #define SCALE_METRIC(x) x = round_metric(round_metric((x) * scale) / scale)
754 SCALE_METRIC(advances
[i
]);
761 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2
*iface
, UINT32 count
,
762 const UINT16
*indices
, INT32
*adjustments
)
764 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
767 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
769 if (!(indices
|| adjustments
) || !count
)
772 if (!indices
|| count
== 1) {
773 memset(adjustments
, 0, count
*sizeof(INT32
));
777 for (i
= 0; i
< count
-1; i
++)
778 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
779 adjustments
[count
-1] = 0;
784 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace2
*iface
)
786 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
787 TRACE("(%p)\n", This
);
788 return freetype_has_kerning_pairs(iface
);
791 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
,
792 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
793 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
795 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
796 DWRITE_GRID_FIT_MODE gridfitmode
;
797 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p)\n", This
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
798 threshold
, measuring_mode
, rendering_mode
);
799 return IDWriteFontFace2_GetRecommendedRenderingMode(iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
800 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
803 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2
*iface
, UINT32 glyph_count
,
804 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
806 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
807 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
811 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2
*iface
)
813 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
814 FIXME("(%p): stub\n", This
);
818 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace2
*iface
)
820 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
821 FIXME("(%p): stub\n", This
);
825 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace2
*iface
)
827 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
828 FIXME("(%p): stub\n", This
);
832 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2
*iface
)
834 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
835 FIXME("(%p): stub\n", This
);
839 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace2
*iface
, UINT32 palette_index
,
840 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
842 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
843 FIXME("(%p)->(%u %u %u %p): stub\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
847 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT fontEmSize
,
848 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *transform
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
849 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
850 DWRITE_GRID_FIT_MODE
*gridfitmode
)
852 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
853 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This
, fontEmSize
, dpiX
, dpiY
, transform
, is_sideways
, threshold
,
854 measuringmode
, params
, renderingmode
, gridfitmode
);
858 static const IDWriteFontFace2Vtbl dwritefontfacevtbl
= {
859 dwritefontface_QueryInterface
,
860 dwritefontface_AddRef
,
861 dwritefontface_Release
,
862 dwritefontface_GetType
,
863 dwritefontface_GetFiles
,
864 dwritefontface_GetIndex
,
865 dwritefontface_GetSimulations
,
866 dwritefontface_IsSymbolFont
,
867 dwritefontface_GetMetrics
,
868 dwritefontface_GetGlyphCount
,
869 dwritefontface_GetDesignGlyphMetrics
,
870 dwritefontface_GetGlyphIndices
,
871 dwritefontface_TryGetFontTable
,
872 dwritefontface_ReleaseFontTable
,
873 dwritefontface_GetGlyphRunOutline
,
874 dwritefontface_GetRecommendedRenderingMode
,
875 dwritefontface_GetGdiCompatibleMetrics
,
876 dwritefontface_GetGdiCompatibleGlyphMetrics
,
877 dwritefontface1_GetMetrics
,
878 dwritefontface1_GetGdiCompatibleMetrics
,
879 dwritefontface1_GetCaretMetrics
,
880 dwritefontface1_GetUnicodeRanges
,
881 dwritefontface1_IsMonospacedFont
,
882 dwritefontface1_GetDesignGlyphAdvances
,
883 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
884 dwritefontface1_GetKerningPairAdjustments
,
885 dwritefontface1_HasKerningPairs
,
886 dwritefontface1_GetRecommendedRenderingMode
,
887 dwritefontface1_GetVerticalGlyphVariants
,
888 dwritefontface1_HasVerticalGlyphVariants
,
889 dwritefontface2_IsColorFont
,
890 dwritefontface2_GetColorPaletteCount
,
891 dwritefontface2_GetPaletteEntryCount
,
892 dwritefontface2_GetPaletteEntries
,
893 dwritefontface2_GetRecommendedRenderingMode
896 HRESULT
get_family_names_from_stream(IDWriteFontFileStream
*stream
, UINT32 index
, DWRITE_FONT_FACE_TYPE facetype
,
897 IDWriteLocalizedStrings
**names
)
899 const void *name_table
= NULL
;
903 opentype_get_font_table(stream
, facetype
, index
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
905 hr
= opentype_get_font_strings_from_id(name_table
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, names
);
906 IDWriteFontFileStream_ReleaseFileFragment(stream
, name_context
);
914 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace2
**fontface
)
916 struct dwrite_font_data
*data
= font
->data
;
917 IDWriteFontFace
*face
;
922 hr
= IDWriteFactory2_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
923 data
->face_index
, font
->simulations
, &face
);
927 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace2
, (void**)fontface
);
928 IDWriteFontFace_Release(face
);
933 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont2
*iface
, REFIID riid
, void **obj
)
935 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
937 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
939 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
940 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
941 IsEqualIID(riid
, &IID_IDWriteFont
) ||
942 IsEqualIID(riid
, &IID_IUnknown
))
945 IDWriteFont2_AddRef(iface
);
950 return E_NOINTERFACE
;
953 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont2
*iface
)
955 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
956 ULONG ref
= InterlockedIncrement(&This
->ref
);
957 TRACE("(%p)->(%d)\n", This
, ref
);
961 static ULONG WINAPI
dwritefont_Release(IDWriteFont2
*iface
)
963 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
964 ULONG ref
= InterlockedDecrement(&This
->ref
);
966 TRACE("(%p)->(%d)\n", This
, ref
);
969 IDWriteFontFamily_Release(This
->family
);
970 release_font_data(This
->data
);
977 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont2
*iface
, IDWriteFontFamily
**family
)
979 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
980 TRACE("(%p)->(%p)\n", This
, family
);
982 *family
= This
->family
;
983 IDWriteFontFamily_AddRef(*family
);
987 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont2
*iface
)
989 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
990 TRACE("(%p)\n", This
);
991 return This
->data
->weight
;
994 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont2
*iface
)
996 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
997 TRACE("(%p)\n", This
);
998 return This
->data
->stretch
;
1001 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont2
*iface
)
1003 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1004 TRACE("(%p)\n", This
);
1008 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont2
*iface
)
1010 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1011 IDWriteFontFace2
*fontface
;
1014 TRACE("(%p)\n", This
);
1016 hr
= get_fontface_from_font(This
, &fontface
);
1020 return IDWriteFontFace2_IsSymbolFont(fontface
);
1023 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont2
*iface
, IDWriteLocalizedStrings
**names
)
1025 static const WCHAR boldobliqueW
[] = {'B','o','l','d',' ','O','b','l','i','q','u','e',0};
1026 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
1027 static const WCHAR boldW
[] = {'B','o','l','d',0};
1028 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
1030 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1031 IDWriteLocalizedStrings
*strings
;
1035 TRACE("(%p)->(%p)\n", This
, names
);
1039 if (This
->simulations
== DWRITE_FONT_SIMULATIONS_NONE
) {
1041 return IDWriteFont2_GetInformationalStrings(iface
, DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES
,
1045 switch (This
->simulations
) {
1046 case DWRITE_FONT_SIMULATIONS_BOLD
|DWRITE_FONT_SIMULATIONS_OBLIQUE
:
1047 name
= boldobliqueW
;
1049 case DWRITE_FONT_SIMULATIONS_BOLD
:
1052 case DWRITE_FONT_SIMULATIONS_OBLIQUE
:
1056 ERR("unknown simulations %d\n", This
->simulations
);
1060 hr
= create_localizedstrings(&strings
);
1061 if (FAILED(hr
)) return hr
;
1063 hr
= add_localizedstring(strings
, enusW
, name
);
1065 IDWriteLocalizedStrings_Release(strings
);
1074 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont2
*iface
,
1075 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1077 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1078 struct dwrite_font_data
*data
= This
->data
;
1081 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1086 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1089 if (!data
->info_strings
[stringid
]) {
1090 IDWriteFontFace2
*fontface
;
1091 const void *table_data
;
1096 hr
= get_fontface_from_font(This
, &fontface
);
1100 table_exists
= FALSE
;
1101 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1102 if (FAILED(hr
) || !table_exists
)
1103 WARN("no NAME table found.\n");
1106 hr
= opentype_get_font_strings_from_id(table_data
, stringid
, &data
->info_strings
[stringid
]);
1107 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1109 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
1113 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1121 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont2
*iface
)
1123 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1124 TRACE("(%p)\n", This
);
1125 return This
->simulations
;
1128 static void WINAPI
dwritefont_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS
*metrics
)
1130 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1132 TRACE("(%p)->(%p)\n", This
, metrics
);
1133 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1136 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont2
*iface
, UINT32 value
, BOOL
*exists
)
1138 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1139 IDWriteFontFace2
*fontface
;
1143 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1147 hr
= get_fontface_from_font(This
, &fontface
);
1152 hr
= IDWriteFontFace2_GetGlyphIndices(fontface
, &value
, 1, &index
);
1156 *exists
= index
!= 0;
1160 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont2
*iface
, IDWriteFontFace
**face
)
1162 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1165 TRACE("(%p)->(%p)\n", This
, face
);
1167 hr
= get_fontface_from_font(This
, (IDWriteFontFace2
**)face
);
1169 IDWriteFontFace_AddRef(*face
);
1174 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1176 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1177 TRACE("(%p)->(%p)\n", This
, metrics
);
1178 *metrics
= This
->data
->metrics
;
1181 static void WINAPI
dwritefont1_GetPanose(IDWriteFont2
*iface
, DWRITE_PANOSE
*panose
)
1183 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1184 TRACE("(%p)->(%p)\n", This
, panose
);
1185 *panose
= This
->data
->panose
;
1188 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont2
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1190 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1191 IDWriteFontFace2
*fontface
;
1194 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1196 hr
= get_fontface_from_font(This
, &fontface
);
1200 return IDWriteFontFace2_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1203 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont2
*iface
)
1205 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1206 IDWriteFontFace2
*fontface
;
1209 TRACE("(%p)\n", This
);
1211 hr
= get_fontface_from_font(This
, &fontface
);
1215 return IDWriteFontFace2_IsMonospacedFont(fontface
);
1218 static HRESULT WINAPI
dwritefont2_IsColorFont(IDWriteFont2
*iface
)
1220 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1221 IDWriteFontFace2
*fontface
;
1224 TRACE("(%p)\n", This
);
1226 hr
= get_fontface_from_font(This
, &fontface
);
1230 return IDWriteFontFace2_IsColorFont(fontface
);
1233 static const IDWriteFont2Vtbl dwritefontvtbl
= {
1234 dwritefont_QueryInterface
,
1237 dwritefont_GetFontFamily
,
1238 dwritefont_GetWeight
,
1239 dwritefont_GetStretch
,
1240 dwritefont_GetStyle
,
1241 dwritefont_IsSymbolFont
,
1242 dwritefont_GetFaceNames
,
1243 dwritefont_GetInformationalStrings
,
1244 dwritefont_GetSimulations
,
1245 dwritefont_GetMetrics
,
1246 dwritefont_HasCharacter
,
1247 dwritefont_CreateFontFace
,
1248 dwritefont1_GetMetrics
,
1249 dwritefont1_GetPanose
,
1250 dwritefont1_GetUnicodeRanges
,
1251 dwritefont1_IsMonospacedFont
,
1252 dwritefont2_IsColorFont
1255 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily
*family
, DWRITE_FONT_SIMULATIONS simulations
,
1258 struct dwrite_font
*This
;
1261 This
= heap_alloc(sizeof(struct dwrite_font
));
1262 if (!This
) return E_OUTOFMEMORY
;
1264 This
->IDWriteFont2_iface
.lpVtbl
= &dwritefontvtbl
;
1266 This
->family
= family
;
1267 IDWriteFontFamily_AddRef(family
);
1268 This
->simulations
= simulations
;
1269 This
->style
= data
->style
;
1271 InterlockedIncrement(&This
->data
->ref
);
1273 /* set oblique style from requested simulation */
1274 if ((simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) && data
->style
== DWRITE_FONT_STYLE_NORMAL
)
1275 This
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
1277 *font
= (IDWriteFont
*)&This
->IDWriteFont2_iface
;
1282 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily
*iface
, REFIID riid
, void **obj
)
1284 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1285 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1287 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1288 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1289 IsEqualIID(riid
, &IID_IDWriteFontFamily
))
1292 IDWriteFontFamily_AddRef(iface
);
1297 return E_NOINTERFACE
;
1300 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily
*iface
)
1302 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1303 ULONG ref
= InterlockedIncrement(&This
->ref
);
1304 TRACE("(%p)->(%d)\n", This
, ref
);
1308 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily
*iface
)
1310 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1311 ULONG ref
= InterlockedDecrement(&This
->ref
);
1313 TRACE("(%p)->(%d)\n", This
, ref
);
1317 IDWriteFontCollection_Release(This
->collection
);
1318 release_fontfamily_data(This
->data
);
1325 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily
*iface
, IDWriteFontCollection
**collection
)
1327 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1328 TRACE("(%p)->(%p)\n", This
, collection
);
1330 *collection
= This
->collection
;
1331 IDWriteFontCollection_AddRef(This
->collection
);
1335 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily
*iface
)
1337 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1338 TRACE("(%p)\n", This
);
1339 return This
->data
->font_count
;
1342 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily
*iface
, UINT32 index
, IDWriteFont
**font
)
1344 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1346 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1350 if (This
->data
->font_count
== 0)
1353 if (index
>= This
->data
->font_count
)
1354 return E_INVALIDARG
;
1356 return create_font(This
->data
->fonts
[index
], iface
, DWRITE_FONT_SIMULATIONS_NONE
, font
);
1359 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily
*iface
, IDWriteLocalizedStrings
**names
)
1361 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1362 return clone_localizedstring(This
->data
->familyname
, names
);
1365 static inline BOOL
is_matching_font_style(DWRITE_FONT_STYLE style
, DWRITE_FONT_STYLE font_style
)
1367 if (style
== font_style
)
1370 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) && font_style
== DWRITE_FONT_STYLE_NORMAL
)
1376 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1377 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1379 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1380 UINT32 min_weight_diff
= ~0u;
1383 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1385 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1386 if (is_matching_font_style(style
, This
->data
->fonts
[i
]->style
) && stretch
== This
->data
->fonts
[i
]->stretch
) {
1387 DWRITE_FONT_WEIGHT font_weight
= This
->data
->fonts
[i
]->weight
;
1388 UINT32 weight_diff
= abs(font_weight
- weight
);
1389 if (weight_diff
< min_weight_diff
) {
1390 min_weight_diff
= weight_diff
;
1397 DWRITE_FONT_SIMULATIONS simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
1399 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) &&
1400 This
->data
->fonts
[found
]->style
== DWRITE_FONT_STYLE_NORMAL
) {
1401 simulations
= DWRITE_FONT_SIMULATIONS_OBLIQUE
;
1403 return create_font(This
->data
->fonts
[found
], iface
, simulations
, font
);
1407 return DWRITE_E_NOFONT
;
1411 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1412 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**fonts
)
1414 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1415 FIXME("(%p)->(%d %d %d %p): stub\n", This
, weight
, stretch
, style
, fonts
);
1419 static const IDWriteFontFamilyVtbl fontfamilyvtbl
= {
1420 dwritefontfamily_QueryInterface
,
1421 dwritefontfamily_AddRef
,
1422 dwritefontfamily_Release
,
1423 dwritefontfamily_GetFontCollection
,
1424 dwritefontfamily_GetFontCount
,
1425 dwritefontfamily_GetFont
,
1426 dwritefontfamily_GetFamilyNames
,
1427 dwritefontfamily_GetFirstMatchingFont
,
1428 dwritefontfamily_GetMatchingFonts
1431 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily
**family
)
1433 struct dwrite_fontfamily
*This
;
1437 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1438 if (!This
) return E_OUTOFMEMORY
;
1440 This
->IDWriteFontFamily_iface
.lpVtbl
= &fontfamilyvtbl
;
1442 This
->collection
= collection
;
1443 IDWriteFontCollection_AddRef(collection
);
1445 InterlockedIncrement(&This
->data
->ref
);
1447 *family
= &This
->IDWriteFontFamily_iface
;
1452 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1455 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1458 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
1460 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1461 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1463 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1464 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
1467 IDWriteFontCollection_AddRef(iface
);
1473 if (This
->is_system
&& IsEqualIID(riid
, &IID_issystemcollection
))
1476 return E_NOINTERFACE
;
1479 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection
*iface
)
1481 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1482 ULONG ref
= InterlockedIncrement(&This
->ref
);
1483 TRACE("(%p)->(%d)\n", This
, ref
);
1487 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection
*iface
)
1490 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1491 ULONG ref
= InterlockedDecrement(&This
->ref
);
1492 TRACE("(%p)->(%d)\n", This
, ref
);
1495 for (i
= 0; i
< This
->family_count
; i
++)
1496 release_fontfamily_data(This
->family_data
[i
]);
1497 heap_free(This
->family_data
);
1504 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
1506 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1507 TRACE("(%p)\n", This
);
1508 return This
->family_count
;
1511 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
1513 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1515 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
1517 if (index
>= This
->family_count
) {
1522 return create_fontfamily(This
->family_data
[index
], iface
, family
);
1525 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
1529 for (i
= 0; i
< collection
->family_count
; i
++) {
1530 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
1531 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
1534 for (j
= 0; j
< count
; j
++) {
1536 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
1537 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
1545 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
1547 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1548 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
1549 *index
= collection_find_family(This
, name
);
1550 *exists
= *index
!= ~0u;
1554 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
1556 UINT32 left_key_size
, right_key_size
;
1557 const void *left_key
, *right_key
;
1563 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
1567 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
1571 if (left_key_size
!= right_key_size
)
1574 return !memcmp(left_key
, right_key
, left_key_size
);
1577 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
1579 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1580 struct dwrite_fontfamily_data
*found_family
= NULL
;
1581 struct dwrite_font_data
*found_font
= NULL
;
1582 DWRITE_FONT_SIMULATIONS simulations
;
1583 IDWriteFontFamily
*family
;
1584 UINT32 i
, j
, face_index
;
1585 IDWriteFontFile
*file
;
1588 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
1593 return E_INVALIDARG
;
1596 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
1599 face_index
= IDWriteFontFace_GetIndex(face
);
1601 for (i
= 0; i
< This
->family_count
; i
++) {
1602 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
1603 for (j
= 0; j
< family_data
->font_count
; j
++) {
1604 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
1606 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
1607 found_font
= font_data
;
1608 found_family
= family_data
;
1615 return DWRITE_E_NOFONT
;
1617 hr
= create_fontfamily(found_family
, iface
, &family
);
1621 simulations
= IDWriteFontFace_GetSimulations(face
);
1622 hr
= create_font(found_font
, family
, simulations
, font
);
1623 IDWriteFontFamily_Release(family
);
1627 static const IDWriteFontCollectionVtbl fontcollectionvtbl
= {
1628 dwritefontcollection_QueryInterface
,
1629 dwritefontcollection_AddRef
,
1630 dwritefontcollection_Release
,
1631 dwritefontcollection_GetFontFamilyCount
,
1632 dwritefontcollection_GetFontFamily
,
1633 dwritefontcollection_FindFamilyName
,
1634 dwritefontcollection_GetFontFromFontFace
1637 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
1639 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
1640 struct dwrite_font_data
**new_list
;
1643 new_alloc
= family_data
->font_alloc
* 2;
1644 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
1646 return E_OUTOFMEMORY
;
1647 family_data
->fonts
= new_list
;
1648 family_data
->font_alloc
= new_alloc
;
1651 family_data
->fonts
[family_data
->font_count
] = font_data
;
1652 family_data
->font_count
++;
1656 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
1658 if (collection
->family_alloc
< collection
->family_count
+ 1) {
1659 struct dwrite_fontfamily_data
**new_list
;
1662 new_alloc
= collection
->family_alloc
* 2;
1663 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
1665 return E_OUTOFMEMORY
;
1667 collection
->family_alloc
= new_alloc
;
1668 collection
->family_data
= new_list
;
1671 collection
->family_data
[collection
->family_count
] = family
;
1672 collection
->family_count
++;
1677 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
1679 collection
->IDWriteFontCollection_iface
.lpVtbl
= &fontcollectionvtbl
;
1680 collection
->ref
= 1;
1681 collection
->family_count
= 0;
1682 collection
->family_alloc
= 2;
1683 collection
->is_system
= is_system
;
1685 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
)*2);
1686 if (!collection
->family_data
)
1687 return E_OUTOFMEMORY
;
1692 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
1694 IDWriteFontFileLoader
*loader
;
1701 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
1705 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
1709 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
1710 IDWriteFontFileLoader_Release(loader
);
1717 static HRESULT
init_font_data(IDWriteFactory2
*factory
, IDWriteFontFile
*file
, UINT32 face_index
, DWRITE_FONT_FACE_TYPE face_type
,
1718 IDWriteFontFileStream
**stream
, struct dwrite_font_data
**ret
)
1720 void *os2_context
, *head_context
;
1721 const void *tt_os2
= NULL
, *tt_head
= NULL
;
1722 struct dwrite_font_props props
;
1723 struct dwrite_font_data
*data
;
1726 data
= heap_alloc_zero(sizeof(*data
));
1728 return E_OUTOFMEMORY
;
1730 hr
= get_filestream_from_file(file
, stream
);
1737 data
->factory
= factory
;
1739 data
->face_index
= face_index
;
1740 data
->face_type
= face_type
;
1741 IDWriteFontFile_AddRef(file
);
1742 IDWriteFactory2_AddRef(factory
);
1744 opentype_get_font_table(*stream
, face_type
, face_index
, MS_OS2_TAG
, &tt_os2
, &os2_context
, NULL
, NULL
);
1745 opentype_get_font_table(*stream
, face_type
, face_index
, MS_HEAD_TAG
, &tt_head
, &head_context
, NULL
, NULL
);
1747 opentype_get_font_properties(*stream
, face_type
, face_index
, &props
);
1748 opentype_get_font_metrics(*stream
, face_type
, face_index
, &data
->metrics
, NULL
);
1750 data
->style
= props
.style
;
1751 data
->stretch
= props
.stretch
;
1752 data
->weight
= props
.weight
;
1753 data
->panose
= props
.panose
;
1756 IDWriteFontFileStream_ReleaseFileFragment(*stream
, os2_context
);
1758 IDWriteFontFileStream_ReleaseFileFragment(*stream
, head_context
);
1764 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
1766 struct dwrite_fontfamily_data
*data
;
1768 data
= heap_alloc(sizeof(*data
));
1770 return E_OUTOFMEMORY
;
1773 data
->font_count
= 0;
1774 data
->font_alloc
= 2;
1776 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
1779 return E_OUTOFMEMORY
;
1782 data
->familyname
= familyname
;
1783 IDWriteLocalizedStrings_AddRef(familyname
);
1789 HRESULT
create_font_collection(IDWriteFactory2
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
1791 struct dwrite_fontcollection
*collection
;
1792 BOOL current
= FALSE
;
1797 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
1798 if (!collection
) return E_OUTOFMEMORY
;
1800 hr
= init_font_collection(collection
, is_system
);
1802 heap_free(collection
);
1806 *ret
= &collection
->IDWriteFontCollection_iface
;
1808 TRACE("building font collection:\n");
1810 while (hr
== S_OK
) {
1811 DWRITE_FONT_FACE_TYPE face_type
;
1812 DWRITE_FONT_FILE_TYPE file_type
;
1813 IDWriteFontFile
*file
;
1819 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
1820 if (FAILED(hr
) || !current
)
1823 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
1827 /* failed font files are skipped */
1828 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
1829 if (FAILED(hr
) || !supported
|| face_count
== 0) {
1830 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
1831 IDWriteFontFile_Release(file
);
1836 for (i
= 0; i
< face_count
; i
++) {
1837 IDWriteLocalizedStrings
*family_name
= NULL
;
1838 struct dwrite_font_data
*font_data
;
1839 IDWriteFontFileStream
*stream
;
1843 /* alloc and init new font data structure */
1844 hr
= init_font_data(factory
, file
, i
, face_type
, &stream
, &font_data
);
1848 /* get family name from font file */
1849 hr
= get_family_names_from_stream(stream
, i
, face_type
, &family_name
);
1850 IDWriteFontFileStream_Release(stream
);
1852 WARN("unable to get family name from font\n");
1853 release_font_data(font_data
);
1858 IDWriteLocalizedStrings_GetString(family_name
, 0, buffer
, sizeof(buffer
)/sizeof(WCHAR
));
1860 index
= collection_find_family(collection
, buffer
);
1862 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
1864 struct dwrite_fontfamily_data
*family_data
;
1866 /* create and init new family */
1867 hr
= init_fontfamily_data(family_name
, &family_data
);
1869 /* add font to family, family - to collection */
1870 hr
= fontfamily_add_font(family_data
, font_data
);
1872 hr
= fontcollection_add_family(collection
, family_data
);
1875 release_fontfamily_data(family_data
);
1879 IDWriteLocalizedStrings_Release(family_name
);
1885 IDWriteFontFile_Release(file
);
1891 struct system_fontfile_enumerator
1893 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
1896 IDWriteFactory2
*factory
;
1901 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
1903 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
1906 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
1910 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
1911 IDWriteFontFileEnumerator_AddRef(iface
);
1916 return E_NOINTERFACE
;
1919 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
1921 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1922 return InterlockedIncrement(&enumerator
->ref
);
1925 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
1927 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1928 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
1931 IDWriteFactory2_Release(enumerator
->factory
);
1932 RegCloseKey(enumerator
->hkey
);
1933 heap_free(enumerator
);
1939 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
1941 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1942 DWORD ret
, type
, val_count
, count
;
1943 WCHAR
*value
, *filename
;
1948 if (enumerator
->index
< 0)
1951 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
1952 if (ret
!= ERROR_SUCCESS
)
1956 value
= heap_alloc( val_count
* sizeof(value
[0]) );
1957 filename
= heap_alloc(count
);
1958 if (!value
|| !filename
) {
1960 heap_free(filename
);
1961 return E_OUTOFMEMORY
;
1964 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
1967 heap_free(filename
);
1971 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
1972 if (!strchrW(filename
, '\\')) {
1973 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
1974 WCHAR fullpathW
[MAX_PATH
];
1976 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
1977 strcatW(fullpathW
, fontsW
);
1978 strcatW(fullpathW
, filename
);
1980 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, fullpathW
, NULL
, file
);
1983 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, filename
, NULL
, file
);
1986 heap_free(filename
);
1990 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
1992 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
1993 DWORD ret
, max_val_count
;
1997 enumerator
->index
++;
1999 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
2000 if (ret
!= ERROR_SUCCESS
)
2004 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
2005 return E_OUTOFMEMORY
;
2007 /* iterate until we find next string value */
2009 DWORD type
= 0, count
, val_count
;
2010 val_count
= max_val_count
;
2011 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
2013 if (type
== REG_SZ
) {
2017 enumerator
->index
++;
2020 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
2025 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
2027 systemfontfileenumerator_QueryInterface
,
2028 systemfontfileenumerator_AddRef
,
2029 systemfontfileenumerator_Release
,
2030 systemfontfileenumerator_MoveNext
,
2031 systemfontfileenumerator_GetCurrentFontFile
2034 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory2
*factory
, IDWriteFontFileEnumerator
**ret
)
2036 struct system_fontfile_enumerator
*enumerator
;
2037 static const WCHAR fontslistW
[] = {
2038 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
2039 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2040 'F','o','n','t','s',0
2045 enumerator
= heap_alloc(sizeof(*enumerator
));
2047 return E_OUTOFMEMORY
;
2049 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
2050 enumerator
->ref
= 1;
2051 enumerator
->factory
= factory
;
2052 enumerator
->index
= -1;
2053 IDWriteFactory2_AddRef(factory
);
2055 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
2056 ERR("failed to open fonts list key\n");
2057 IDWriteFactory2_Release(factory
);
2058 heap_free(enumerator
);
2062 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
2067 HRESULT
get_system_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
2069 IDWriteFontFileEnumerator
*enumerator
;
2074 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
2078 TRACE("building system font collection for factory %p\n", factory
);
2079 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
2080 IDWriteFontFileEnumerator_Release(enumerator
);
2084 static HRESULT WINAPI
eudcfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2088 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
2089 IDWriteFontFileEnumerator_AddRef(iface
);
2094 return E_NOINTERFACE
;
2097 static ULONG WINAPI
eudcfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2102 static ULONG WINAPI
eudcfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2107 static HRESULT WINAPI
eudcfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2113 static HRESULT WINAPI
eudcfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2119 static const struct IDWriteFontFileEnumeratorVtbl eudcfontfileenumeratorvtbl
=
2121 eudcfontfileenumerator_QueryInterface
,
2122 eudcfontfileenumerator_AddRef
,
2123 eudcfontfileenumerator_Release
,
2124 eudcfontfileenumerator_MoveNext
,
2125 eudcfontfileenumerator_GetCurrentFontFile
2128 static IDWriteFontFileEnumerator eudc_fontfile_enumerator
= { &eudcfontfileenumeratorvtbl
};
2130 HRESULT
get_eudc_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
2132 TRACE("building EUDC font collection for factory %p\n", factory
);
2133 return create_font_collection(factory
, &eudc_fontfile_enumerator
, FALSE
, collection
);
2136 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
2138 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2140 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2142 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
2145 IDWriteFontFile_AddRef(iface
);
2150 return E_NOINTERFACE
;
2153 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
2155 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2156 ULONG ref
= InterlockedIncrement(&This
->ref
);
2157 TRACE("(%p)->(%d)\n", This
, ref
);
2161 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
2163 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2164 ULONG ref
= InterlockedDecrement(&This
->ref
);
2166 TRACE("(%p)->(%d)\n", This
, ref
);
2170 IDWriteFontFileLoader_Release(This
->loader
);
2171 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
2172 heap_free(This
->reference_key
);
2179 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
2181 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2182 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
2183 *fontFileReferenceKey
= This
->reference_key
;
2184 *fontFileReferenceKeySize
= This
->key_size
;
2189 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
2191 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2192 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
2193 *fontFileLoader
= This
->loader
;
2194 IDWriteFontFileLoader_AddRef(This
->loader
);
2199 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
, DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
2201 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2202 IDWriteFontFileStream
*stream
;
2205 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
2207 *isSupportedFontType
= FALSE
;
2208 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
2210 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
2213 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
2217 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
2219 /* TODO: Further Analysis */
2220 IDWriteFontFileStream_Release(stream
);
2224 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
2225 dwritefontfile_QueryInterface
,
2226 dwritefontfile_AddRef
,
2227 dwritefontfile_Release
,
2228 dwritefontfile_GetReferenceKey
,
2229 dwritefontfile_GetLoader
,
2230 dwritefontfile_Analyze
,
2233 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
2235 struct dwrite_fontfile
*This
;
2237 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
2238 if (!This
) return E_OUTOFMEMORY
;
2240 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
2242 IDWriteFontFileLoader_AddRef(loader
);
2243 This
->loader
= loader
;
2244 This
->stream
= NULL
;
2245 This
->reference_key
= heap_alloc(key_size
);
2246 memcpy(This
->reference_key
, reference_key
, key_size
);
2247 This
->key_size
= key_size
;
2249 *font_file
= &This
->IDWriteFontFile_iface
;
2254 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2256 IDWriteFontFileLoader
*loader
;
2262 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2266 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2268 IDWriteFontFileLoader_Release(loader
);
2272 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2273 IDWriteFontFileLoader_Release(loader
);
2278 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
2279 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace2
**ret
)
2281 struct dwrite_fontface
*fontface
;
2287 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
2289 return E_OUTOFMEMORY
;
2291 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
2292 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
2294 if (!fontface
->files
|| !fontface
->streams
) {
2295 heap_free(fontface
->files
);
2296 heap_free(fontface
->streams
);
2297 heap_free(fontface
);
2298 return E_OUTOFMEMORY
;
2301 fontface
->IDWriteFontFace2_iface
.lpVtbl
= &dwritefontfacevtbl
;
2303 fontface
->type
= facetype
;
2304 fontface
->file_count
= files_number
;
2305 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
2306 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
2307 fontface
->cmap
.exists
= TRUE
;
2308 fontface
->vdmx
.exists
= TRUE
;
2309 fontface
->index
= index
;
2310 fontface
->simulations
= simulations
;
2311 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
2313 for (i
= 0; i
< fontface
->file_count
; i
++) {
2314 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
2316 IDWriteFontFace2_Release(&fontface
->IDWriteFontFace2_iface
);
2320 fontface
->files
[i
] = font_files
[i
];
2321 IDWriteFontFile_AddRef(font_files
[i
]);
2324 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
2325 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
2326 /* TODO: test what happens if caret is already slanted */
2327 if (fontface
->caret
.slopeRise
== 1) {
2328 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
2329 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
2333 *ret
= &fontface
->IDWriteFontFace2_iface
;
2337 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
2344 struct local_cached_stream
2347 IDWriteFontFileStream
*stream
;
2348 struct local_refkey
*key
;
2352 struct dwrite_localfontfilestream
2354 IDWriteFontFileStream IDWriteFontFileStream_iface
;
2357 struct local_cached_stream
*entry
;
2358 const void *file_ptr
;
2362 struct dwrite_localfontfileloader
{
2363 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
2366 struct list streams
;
2369 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
2371 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
2374 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
2376 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
2379 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
2381 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2382 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2383 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
2386 IDWriteFontFileStream_AddRef(iface
);
2391 return E_NOINTERFACE
;
2394 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
2396 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2397 ULONG ref
= InterlockedIncrement(&This
->ref
);
2398 TRACE("(%p)->(%d)\n", This
, ref
);
2402 static inline void release_cached_stream(struct local_cached_stream
*stream
)
2404 list_remove(&stream
->entry
);
2405 heap_free(stream
->key
);
2409 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
2411 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2412 ULONG ref
= InterlockedDecrement(&This
->ref
);
2414 TRACE("(%p)->(%d)\n", This
, ref
);
2417 UnmapViewOfFile(This
->file_ptr
);
2418 release_cached_stream(This
->entry
);
2425 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
2427 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2429 TRACE("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
2430 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
2432 *fragment_context
= NULL
;
2434 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
2435 *fragment_start
= NULL
;
2439 *fragment_start
= (char*)This
->file_ptr
+ offset
;
2443 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
2445 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2446 TRACE("(%p)->(%p)\n", This
, fragment_context
);
2449 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
2451 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2452 TRACE("(%p)->(%p)\n", This
, size
);
2457 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
2459 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2462 TRACE("(%p)->(%p)\n", This
, last_writetime
);
2464 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
2465 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
2466 *last_writetime
= li
.QuadPart
;
2471 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
2473 localfontfilestream_QueryInterface
,
2474 localfontfilestream_AddRef
,
2475 localfontfilestream_Release
,
2476 localfontfilestream_ReadFileFragment
,
2477 localfontfilestream_ReleaseFileFragment
,
2478 localfontfilestream_GetFileSize
,
2479 localfontfilestream_GetLastWriteTime
2482 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
** iface
)
2484 struct dwrite_localfontfilestream
*This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
2486 return E_OUTOFMEMORY
;
2488 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
2491 This
->file_ptr
= file_ptr
;
2493 This
->entry
= entry
;
2495 *iface
= &This
->IDWriteFontFileStream_iface
;
2499 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
2501 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2503 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2505 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
2508 IDWriteLocalFontFileLoader_AddRef(iface
);
2513 return E_NOINTERFACE
;
2516 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
2518 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2519 ULONG ref
= InterlockedIncrement(&This
->ref
);
2520 TRACE("(%p)->(%d)\n", This
, ref
);
2524 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
2526 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2527 ULONG ref
= InterlockedDecrement(&This
->ref
);
2529 TRACE("(%p)->(%d)\n", This
, ref
);
2532 struct local_cached_stream
*stream
, *stream2
;
2534 /* This will detach all entries from cache. Entries are released together with streams,
2535 so stream controls its lifetime. */
2536 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
2537 list_init(&stream
->entry
);
2545 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
2547 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2548 const struct local_refkey
*refkey
= key
;
2549 struct local_cached_stream
*stream
;
2550 IDWriteFontFileStream
*filestream
;
2551 HANDLE file
, mapping
;
2556 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
2557 TRACE("name: %s\n", debugstr_w(refkey
->name
));
2559 /* search cache first */
2560 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
2561 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
2562 *ret
= stream
->stream
;
2563 IDWriteFontFileStream_AddRef(*ret
);
2570 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2571 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2572 if (file
== INVALID_HANDLE_VALUE
)
2575 GetFileSizeEx(file
, &size
);
2576 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
2581 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
2582 CloseHandle(mapping
);
2584 stream
= heap_alloc(sizeof(*stream
));
2586 UnmapViewOfFile(file_ptr
);
2587 return E_OUTOFMEMORY
;
2590 stream
->key
= heap_alloc(key_size
);
2592 UnmapViewOfFile(file_ptr
);
2594 return E_OUTOFMEMORY
;
2597 stream
->key_size
= key_size
;
2598 memcpy(stream
->key
, key
, key_size
);
2600 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
2602 UnmapViewOfFile(file_ptr
);
2603 heap_free(stream
->key
);
2608 stream
->stream
= filestream
;
2609 list_add_head(&This
->streams
, &stream
->entry
);
2611 *ret
= stream
->stream
;
2616 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
2618 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2619 const struct local_refkey
*refkey
= key
;
2621 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
2623 *length
= strlenW(refkey
->name
);
2627 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
2629 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2630 const struct local_refkey
*refkey
= key
;
2632 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
2634 if (length
< strlenW(refkey
->name
))
2635 return E_INVALIDARG
;
2637 strcpyW(path
, refkey
->name
);
2641 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
2643 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2644 const struct local_refkey
*refkey
= key
;
2646 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
2648 *writetime
= refkey
->writetime
;
2652 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
2653 localfontfileloader_QueryInterface
,
2654 localfontfileloader_AddRef
,
2655 localfontfileloader_Release
,
2656 localfontfileloader_CreateStreamFromKey
,
2657 localfontfileloader_GetFilePathLengthFromKey
,
2658 localfontfileloader_GetFilePathFromKey
,
2659 localfontfileloader_GetLastWriteTimeFromKey
2662 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
** iface
)
2664 struct dwrite_localfontfileloader
*This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
2666 return E_OUTOFMEMORY
;
2668 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
2670 list_init(&This
->streams
);
2672 *iface
= &This
->IDWriteLocalFontFileLoader_iface
;
2676 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
2678 struct local_refkey
*refkey
;
2680 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
2683 refkey
= heap_alloc(*size
);
2685 return E_OUTOFMEMORY
;
2688 refkey
->writetime
= *writetime
;
2690 WIN32_FILE_ATTRIBUTE_DATA info
;
2692 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
2693 refkey
->writetime
= info
.ftLastWriteTime
;
2695 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
2697 strcpyW(refkey
->name
, path
);
2704 /* IDWriteGlyphRunAnalysis */
2705 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
2707 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2709 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
2711 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
2712 IsEqualIID(riid
, &IID_IUnknown
))
2715 IDWriteGlyphRunAnalysis_AddRef(iface
);
2720 return E_NOINTERFACE
;
2723 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
2725 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2726 ULONG ref
= InterlockedIncrement(&This
->ref
);
2727 TRACE("(%p)->(%u)\n", This
, ref
);
2731 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
2733 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2734 ULONG ref
= InterlockedDecrement(&This
->ref
);
2736 TRACE("(%p)->(%u)\n", This
, ref
);
2745 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
* bounds
)
2747 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2748 FIXME("(%p)->(%d %p): stub\n", This
, type
, bounds
);
2752 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
2753 RECT
const* bounds
, BYTE
* alphaValues
, UINT32 bufferSize
)
2755 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2756 FIXME("(%p)->(%d %p %p %u): stub\n", This
, type
, bounds
, alphaValues
, bufferSize
);
2760 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
2761 FLOAT
*blendGamma
, FLOAT
*blendEnhancedContrast
, FLOAT
*blendClearTypeLevel
)
2763 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2764 FIXME("(%p)->(%p %p %p %p): stub\n", This
, params
, blendGamma
, blendEnhancedContrast
, blendClearTypeLevel
);
2768 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
2769 glyphrunanalysis_QueryInterface
,
2770 glyphrunanalysis_AddRef
,
2771 glyphrunanalysis_Release
,
2772 glyphrunanalysis_GetAlphaTextureBounds
,
2773 glyphrunanalysis_CreateAlphaTexture
,
2774 glyphrunanalysis_GetAlphaBlendParams
2777 HRESULT
create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode
, IDWriteGlyphRunAnalysis
**ret
)
2779 struct dwrite_glyphrunanalysis
*analysis
;
2783 /* check for valid rendering mode */
2784 if ((UINT32
)rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
2785 return E_INVALIDARG
;
2787 analysis
= heap_alloc(sizeof(*analysis
));
2789 return E_OUTOFMEMORY
;
2791 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
2794 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;