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')
35 #define MS_GASP_TAG DWRITE_MAKE_OPENTYPE_TAG('g','a','s','p')
37 static const IID IID_issystemcollection
= {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
39 static const FLOAT RECOMMENDED_OUTLINE_AA_THRESHOLD
= 100.0f
;
40 static const FLOAT RECOMMENDED_OUTLINE_A_THRESHOLD
= 350.0f
;
41 static const FLOAT RECOMMENDED_NATURAL_PPEM
= 20.0f
;
43 struct dwrite_font_data
{
46 DWRITE_FONT_STYLE style
;
47 DWRITE_FONT_STRETCH stretch
;
48 DWRITE_FONT_WEIGHT weight
;
50 DWRITE_FONT_METRICS1 metrics
;
51 IDWriteLocalizedStrings
*info_strings
[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
+1];
53 /* data needed to create fontface instance */
54 IDWriteFactory2
*factory
;
55 DWRITE_FONT_FACE_TYPE face_type
;
56 IDWriteFontFile
*file
;
62 struct dwrite_fontfamily_data
{
65 IDWriteLocalizedStrings
*familyname
;
67 struct dwrite_font_data
**fonts
;
72 struct dwrite_fontcollection
{
73 IDWriteFontCollection IDWriteFontCollection_iface
;
76 struct dwrite_fontfamily_data
**family_data
;
82 struct dwrite_fontfamily
{
83 IDWriteFontFamily IDWriteFontFamily_iface
;
86 struct dwrite_fontfamily_data
*data
;
88 IDWriteFontCollection
* collection
;
92 IDWriteFont2 IDWriteFont2_iface
;
95 IDWriteFontFamily
*family
;
98 DWRITE_FONT_STYLE style
;
99 struct dwrite_font_data
*data
;
102 struct dwrite_fonttable
{
109 enum runanalysis_readystate
{
110 RUNANALYSIS_BOUNDS
= 1 << 0,
113 struct dwrite_glyphrunanalysis
{
114 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface
;
117 DWRITE_RENDERING_MODE rendering_mode
;
118 DWRITE_GLYPH_RUN run
;
124 DWRITE_GLYPH_OFFSET
*offsets
;
129 #define GLYPH_BLOCK_SHIFT 8
130 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
131 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
132 #define GLYPH_MAX 65536
134 struct dwrite_fontface
{
135 IDWriteFontFace2 IDWriteFontFace2_iface
;
138 IDWriteFontFileStream
**streams
;
139 IDWriteFontFile
**files
;
144 DWRITE_FONT_FACE_TYPE type
;
145 DWRITE_FONT_METRICS1 metrics
;
146 DWRITE_CARET_METRICS caret
;
148 struct dwrite_fonttable cmap
;
149 struct dwrite_fonttable vdmx
;
150 struct dwrite_fonttable gasp
;
151 DWRITE_GLYPH_METRICS
*glyphs
[GLYPH_MAX
/GLYPH_BLOCK_SIZE
];
154 struct dwrite_fontfile
{
155 IDWriteFontFile IDWriteFontFile_iface
;
158 IDWriteFontFileLoader
*loader
;
161 IDWriteFontFileStream
*stream
;
164 static inline struct dwrite_fontface
*impl_from_IDWriteFontFace2(IDWriteFontFace2
*iface
)
166 return CONTAINING_RECORD(iface
, struct dwrite_fontface
, IDWriteFontFace2_iface
);
169 static inline struct dwrite_font
*impl_from_IDWriteFont2(IDWriteFont2
*iface
)
171 return CONTAINING_RECORD(iface
, struct dwrite_font
, IDWriteFont2_iface
);
174 static inline struct dwrite_fontfile
*impl_from_IDWriteFontFile(IDWriteFontFile
*iface
)
176 return CONTAINING_RECORD(iface
, struct dwrite_fontfile
, IDWriteFontFile_iface
);
179 static inline struct dwrite_fontfamily
*impl_from_IDWriteFontFamily(IDWriteFontFamily
*iface
)
181 return CONTAINING_RECORD(iface
, struct dwrite_fontfamily
, IDWriteFontFamily_iface
);
184 static inline struct dwrite_fontcollection
*impl_from_IDWriteFontCollection(IDWriteFontCollection
*iface
)
186 return CONTAINING_RECORD(iface
, struct dwrite_fontcollection
, IDWriteFontCollection_iface
);
189 static inline struct dwrite_glyphrunanalysis
*impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis
*iface
)
191 return CONTAINING_RECORD(iface
, struct dwrite_glyphrunanalysis
, IDWriteGlyphRunAnalysis_iface
);
194 static inline const char *debugstr_tag(UINT32 tag
)
196 return wine_dbg_sprintf("%c%c%c%c", tag
>> 24, (tag
>> 16) & 0xff, (tag
>> 8) & 0xff, tag
& 0xff);
199 static HRESULT
get_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
201 static const DWRITE_GLYPH_METRICS nil
;
202 DWRITE_GLYPH_METRICS
*block
= fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
204 if (!block
|| !memcmp(&block
[glyph
& GLYPH_BLOCK_MASK
], &nil
, sizeof(DWRITE_GLYPH_METRICS
))) return S_FALSE
;
205 memcpy(metrics
, &block
[glyph
& GLYPH_BLOCK_MASK
], sizeof(*metrics
));
209 static HRESULT
set_cached_glyph_metrics(struct dwrite_fontface
*fontface
, UINT16 glyph
, DWRITE_GLYPH_METRICS
*metrics
)
211 DWRITE_GLYPH_METRICS
**block
= &fontface
->glyphs
[glyph
>> GLYPH_BLOCK_SHIFT
];
214 /* start new block */
215 *block
= heap_alloc_zero(sizeof(*metrics
) * GLYPH_BLOCK_SIZE
);
217 return E_OUTOFMEMORY
;
220 memcpy(&(*block
)[glyph
& GLYPH_BLOCK_MASK
], metrics
, sizeof(*metrics
));
224 static void* get_fontface_table(struct dwrite_fontface
*fontface
, UINT32 tag
, struct dwrite_fonttable
*table
)
228 if (table
->data
|| !table
->exists
)
231 table
->exists
= FALSE
;
232 hr
= IDWriteFontFace2_TryGetFontTable(&fontface
->IDWriteFontFace2_iface
, tag
, (const void**)&table
->data
,
233 &table
->size
, &table
->context
, &table
->exists
);
234 if (FAILED(hr
) || !table
->exists
) {
235 WARN("Font does not have a %s table\n", debugstr_tag(tag
));
242 static inline void* get_fontface_cmap(struct dwrite_fontface
*fontface
)
244 return get_fontface_table(fontface
, MS_CMAP_TAG
, &fontface
->cmap
);
247 static inline void* get_fontface_vdmx(struct dwrite_fontface
*fontface
)
249 return get_fontface_table(fontface
, MS_VDMX_TAG
, &fontface
->vdmx
);
252 static inline void* get_fontface_gasp(struct dwrite_fontface
*fontface
, UINT32
*size
)
254 void *ptr
= get_fontface_table(fontface
, MS_GASP_TAG
, &fontface
->gasp
);
255 *size
= fontface
->gasp
.size
;
259 static void release_font_data(struct dwrite_font_data
*data
)
263 if (InterlockedDecrement(&data
->ref
) > 0)
266 for (i
= DWRITE_INFORMATIONAL_STRING_NONE
; i
< sizeof(data
->info_strings
)/sizeof(data
->info_strings
[0]); i
++) {
267 if (data
->info_strings
[i
])
268 IDWriteLocalizedStrings_Release(data
->info_strings
[i
]);
271 IDWriteFontFile_Release(data
->file
);
272 IDWriteFactory2_Release(data
->factory
);
273 heap_free(data
->facename
);
277 static void release_fontfamily_data(struct dwrite_fontfamily_data
*data
)
281 if (InterlockedDecrement(&data
->ref
) > 0)
284 for (i
= 0; i
< data
->font_count
; i
++)
285 release_font_data(data
->fonts
[i
]);
286 heap_free(data
->fonts
);
287 IDWriteLocalizedStrings_Release(data
->familyname
);
291 static HRESULT WINAPI
dwritefontface_QueryInterface(IDWriteFontFace2
*iface
, REFIID riid
, void **obj
)
293 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
295 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
297 if (IsEqualIID(riid
, &IID_IDWriteFontFace2
) ||
298 IsEqualIID(riid
, &IID_IDWriteFontFace1
) ||
299 IsEqualIID(riid
, &IID_IDWriteFontFace
) ||
300 IsEqualIID(riid
, &IID_IUnknown
))
303 IDWriteFontFace2_AddRef(iface
);
308 return E_NOINTERFACE
;
311 static ULONG WINAPI
dwritefontface_AddRef(IDWriteFontFace2
*iface
)
313 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
314 ULONG ref
= InterlockedIncrement(&This
->ref
);
315 TRACE("(%p)->(%d)\n", This
, ref
);
319 static ULONG WINAPI
dwritefontface_Release(IDWriteFontFace2
*iface
)
321 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
322 ULONG ref
= InterlockedDecrement(&This
->ref
);
324 TRACE("(%p)->(%d)\n", This
, ref
);
329 if (This
->cmap
.context
)
330 IDWriteFontFace2_ReleaseFontTable(iface
, This
->cmap
.context
);
331 if (This
->vdmx
.context
)
332 IDWriteFontFace2_ReleaseFontTable(iface
, This
->vdmx
.context
);
333 if (This
->gasp
.context
)
334 IDWriteFontFace2_ReleaseFontTable(iface
, This
->gasp
.context
);
335 for (i
= 0; i
< This
->file_count
; i
++) {
336 if (This
->streams
[i
])
337 IDWriteFontFileStream_Release(This
->streams
[i
]);
339 IDWriteFontFile_Release(This
->files
[i
]);
342 for (i
= 0; i
< sizeof(This
->glyphs
)/sizeof(This
->glyphs
[0]); i
++)
343 heap_free(This
->glyphs
[i
]);
345 freetype_notify_cacheremove(iface
);
352 static DWRITE_FONT_FACE_TYPE WINAPI
dwritefontface_GetType(IDWriteFontFace2
*iface
)
354 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
355 TRACE("(%p)\n", This
);
359 static HRESULT WINAPI
dwritefontface_GetFiles(IDWriteFontFace2
*iface
, UINT32
*number_of_files
,
360 IDWriteFontFile
**fontfiles
)
362 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
365 TRACE("(%p)->(%p %p)\n", This
, number_of_files
, fontfiles
);
366 if (fontfiles
== NULL
)
368 *number_of_files
= This
->file_count
;
371 if (*number_of_files
< This
->file_count
)
374 for (i
= 0; i
< This
->file_count
; i
++)
376 IDWriteFontFile_AddRef(This
->files
[i
]);
377 fontfiles
[i
] = This
->files
[i
];
383 static UINT32 WINAPI
dwritefontface_GetIndex(IDWriteFontFace2
*iface
)
385 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
386 TRACE("(%p)\n", This
);
390 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefontface_GetSimulations(IDWriteFontFace2
*iface
)
392 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
393 TRACE("(%p)\n", This
);
394 return This
->simulations
;
397 static BOOL WINAPI
dwritefontface_IsSymbolFont(IDWriteFontFace2
*iface
)
399 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
400 FIXME("(%p): stub\n", This
);
404 static void WINAPI
dwritefontface_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS
*metrics
)
406 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
407 TRACE("(%p)->(%p)\n", This
, metrics
);
408 memcpy(metrics
, &This
->metrics
, sizeof(*metrics
));
411 static UINT16 WINAPI
dwritefontface_GetGlyphCount(IDWriteFontFace2
*iface
)
413 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
414 TRACE("(%p)\n", This
);
415 return freetype_get_glyphcount(iface
);
418 static HRESULT WINAPI
dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2
*iface
,
419 UINT16
const *glyphs
, UINT32 glyph_count
, DWRITE_GLYPH_METRICS
*ret
, BOOL is_sideways
)
421 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
425 TRACE("(%p)->(%p %u %p %d)\n", This
, glyphs
, glyph_count
, ret
, is_sideways
);
431 FIXME("sideways metrics are not supported.\n");
433 for (i
= 0; i
< glyph_count
; i
++) {
434 DWRITE_GLYPH_METRICS metrics
;
436 hr
= get_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
438 freetype_get_design_glyph_metrics(iface
, This
->metrics
.designUnitsPerEm
, glyphs
[i
], &metrics
);
439 hr
= set_cached_glyph_metrics(This
, glyphs
[i
], &metrics
);
449 static HRESULT WINAPI
dwritefontface_GetGlyphIndices(IDWriteFontFace2
*iface
, UINT32
const *codepoints
,
450 UINT32 count
, UINT16
*glyph_indices
)
452 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
455 TRACE("(%p)->(%p %u %p)\n", This
, codepoints
, count
, glyph_indices
);
461 memset(glyph_indices
, 0, count
*sizeof(UINT16
));
465 for (i
= 0; i
< count
; i
++)
466 glyph_indices
[i
] = freetype_get_glyphindex(iface
, codepoints
[i
]);
471 static HRESULT WINAPI
dwritefontface_TryGetFontTable(IDWriteFontFace2
*iface
, UINT32 table_tag
,
472 const void **table_data
, UINT32
*table_size
, void **context
, BOOL
*exists
)
474 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
476 TRACE("(%p)->(%u %p %p %p %p)\n", This
, table_tag
, table_data
, table_size
, context
, exists
);
478 return opentype_get_font_table(This
->streams
[0], This
->type
, This
->index
, table_tag
, table_data
, context
, table_size
, exists
);
481 static void WINAPI
dwritefontface_ReleaseFontTable(IDWriteFontFace2
*iface
, void *table_context
)
483 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
485 TRACE("(%p)->(%p)\n", This
, table_context
);
487 IDWriteFontFileStream_ReleaseFileFragment(This
->streams
[0], table_context
);
490 HRESULT
new_glyph_outline(UINT32 count
, struct glyph_outline
**ret
)
492 struct glyph_outline
*outline
;
493 D2D1_POINT_2F
*points
;
498 outline
= heap_alloc(sizeof(*outline
));
500 return E_OUTOFMEMORY
;
502 points
= heap_alloc(count
*sizeof(D2D1_POINT_2F
));
503 tags
= heap_alloc_zero(count
*sizeof(UINT8
));
504 if (!points
|| !tags
) {
508 return E_OUTOFMEMORY
;
511 outline
->points
= points
;
512 outline
->tags
= tags
;
513 outline
->count
= count
;
514 outline
->advance
= 0.0;
520 static void free_glyph_outline(struct glyph_outline
*outline
)
522 heap_free(outline
->points
);
523 heap_free(outline
->tags
);
527 static void report_glyph_outline(const struct glyph_outline
*outline
, IDWriteGeometrySink
*sink
)
531 for (p
= 0; p
< outline
->count
; p
++) {
532 if (outline
->tags
[p
] & OUTLINE_POINT_START
) {
533 ID2D1SimplifiedGeometrySink_BeginFigure(sink
, outline
->points
[p
], D2D1_FIGURE_BEGIN_FILLED
);
537 if (outline
->tags
[p
] & OUTLINE_POINT_LINE
)
538 ID2D1SimplifiedGeometrySink_AddLines(sink
, outline
->points
+p
, 1);
539 else if (outline
->tags
[p
] & OUTLINE_POINT_BEZIER
) {
540 static const UINT16 segment_length
= 3;
541 ID2D1SimplifiedGeometrySink_AddBeziers(sink
, (D2D1_BEZIER_SEGMENT
*)&outline
->points
[p
], 1);
542 p
+= segment_length
- 1;
545 if (outline
->tags
[p
] & OUTLINE_POINT_END
)
546 ID2D1SimplifiedGeometrySink_EndFigure(sink
, D2D1_FIGURE_END_CLOSED
);
550 static inline void translate_glyph_outline(struct glyph_outline
*outline
, FLOAT xoffset
, FLOAT yoffset
)
554 for (p
= 0; p
< outline
->count
; p
++) {
555 outline
->points
[p
].x
+= xoffset
;
556 outline
->points
[p
].y
+= yoffset
;
560 static HRESULT WINAPI
dwritefontface_GetGlyphRunOutline(IDWriteFontFace2
*iface
, FLOAT emSize
,
561 UINT16
const *glyphs
, FLOAT
const* advances
, DWRITE_GLYPH_OFFSET
const *offsets
,
562 UINT32 count
, BOOL is_sideways
, BOOL is_rtl
, IDWriteGeometrySink
*sink
)
564 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
569 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This
, emSize
, glyphs
, advances
, offsets
,
570 count
, is_sideways
, is_rtl
, sink
);
572 if (!glyphs
|| !sink
)
576 FIXME("sideways mode is not supported.\n");
579 ID2D1SimplifiedGeometrySink_SetFillMode(sink
, D2D1_FILL_MODE_WINDING
);
581 for (g
= 0; g
< count
; g
++) {
582 FLOAT xoffset
= 0.0, yoffset
= 0.0;
583 struct glyph_outline
*outline
;
585 /* FIXME: cache outlines */
587 hr
= freetype_get_glyph_outline(iface
, emSize
, glyphs
[g
], This
->simulations
, &outline
);
591 /* glyph offsets act as current glyph adjustment */
593 xoffset
+= is_rtl
? -offsets
[g
].advanceOffset
: offsets
[g
].advanceOffset
;
594 yoffset
-= offsets
[g
].ascenderOffset
;
598 advance
= is_rtl
? -outline
->advance
: 0.0;
601 translate_glyph_outline(outline
, xoffset
, yoffset
);
603 /* update advance to next glyph */
605 advance
+= is_rtl
? -advances
[g
] : advances
[g
];
607 advance
+= is_rtl
? -outline
->advance
: outline
->advance
;
609 report_glyph_outline(outline
, sink
);
610 free_glyph_outline(outline
);
616 static DWRITE_RENDERING_MODE
fontface_renderingmode_from_measuringmode(DWRITE_MEASURING_MODE measuring
,
617 FLOAT ppem
, WORD gasp
)
619 DWRITE_RENDERING_MODE mode
= DWRITE_RENDERING_MODE_DEFAULT
;
623 case DWRITE_MEASURING_MODE_NATURAL
:
625 if (!(gasp
& GASP_SYMMETRIC_SMOOTHING
) && (ppem
<= RECOMMENDED_NATURAL_PPEM
))
626 mode
= DWRITE_RENDERING_MODE_NATURAL
;
628 mode
= DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
631 case DWRITE_MEASURING_MODE_GDI_CLASSIC
:
632 mode
= DWRITE_RENDERING_MODE_GDI_CLASSIC
;
634 case DWRITE_MEASURING_MODE_GDI_NATURAL
:
635 mode
= DWRITE_RENDERING_MODE_GDI_NATURAL
;
644 static HRESULT WINAPI
dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
645 FLOAT ppdip
, DWRITE_MEASURING_MODE measuring
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*mode
)
647 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
652 TRACE("(%p)->(%.2f %.2f %d %p %p)\n", This
, emSize
, ppdip
, measuring
, params
, mode
);
655 *mode
= DWRITE_RENDERING_MODE_DEFAULT
;
659 *mode
= IDWriteRenderingParams_GetRenderingMode(params
);
660 if (*mode
!= DWRITE_RENDERING_MODE_DEFAULT
)
663 ppem
= emSize
* ppdip
;
665 if (ppem
>= RECOMMENDED_OUTLINE_AA_THRESHOLD
) {
666 *mode
= DWRITE_RENDERING_MODE_OUTLINE
;
670 ptr
= get_fontface_gasp(This
, &size
);
671 gasp
= opentype_get_gasp_flags(ptr
, size
, ppem
);
672 *mode
= fontface_renderingmode_from_measuringmode(measuring
, ppem
, gasp
);
676 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT pixels_per_dip
,
677 DWRITE_MATRIX
const *transform
, DWRITE_FONT_METRICS
*metrics
)
679 DWRITE_FONT_METRICS1 metrics1
;
680 HRESULT hr
= IDWriteFontFace2_GetGdiCompatibleMetrics(iface
, emSize
, pixels_per_dip
, transform
, &metrics1
);
681 memcpy(metrics
, &metrics1
, sizeof(*metrics
));
685 static inline int round_metric(FLOAT metric
)
687 return (int)floorf(metric
+ 0.5f
);
690 static HRESULT WINAPI
dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2
*iface
, FLOAT emSize
, FLOAT ppdip
,
691 DWRITE_MATRIX
const *m
, BOOL use_gdi_natural
, UINT16
const *glyphs
, UINT32 glyph_count
,
692 DWRITE_GLYPH_METRICS
*metrics
, BOOL is_sideways
)
694 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
699 TRACE("(%p)->(%.2f %.2f %p %d %p %u %p %d)\n", This
, emSize
, ppdip
, m
, use_gdi_natural
, glyphs
,
700 glyph_count
, metrics
, is_sideways
);
702 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
703 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
705 scale
= emSize
* ppdip
/ This
->metrics
.designUnitsPerEm
;
707 for (i
= 0; i
< glyph_count
; i
++) {
708 DWRITE_GLYPH_METRICS
*ret
= metrics
+ i
;
709 DWRITE_GLYPH_METRICS design
;
711 hr
= IDWriteFontFace2_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &design
, is_sideways
);
715 #define SCALE_METRIC(x) ret->x = round_metric(round_metric((design.x) * scale) / scale)
716 SCALE_METRIC(leftSideBearing
);
717 SCALE_METRIC(advanceWidth
);
718 SCALE_METRIC(rightSideBearing
);
719 SCALE_METRIC(topSideBearing
);
720 SCALE_METRIC(advanceHeight
);
721 SCALE_METRIC(bottomSideBearing
);
722 SCALE_METRIC(verticalOriginY
);
729 static void WINAPI
dwritefontface1_GetMetrics(IDWriteFontFace2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
731 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
732 TRACE("(%p)->(%p)\n", This
, metrics
);
733 *metrics
= This
->metrics
;
736 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2
*iface
, FLOAT em_size
, FLOAT pixels_per_dip
,
737 const DWRITE_MATRIX
*m
, DWRITE_FONT_METRICS1
*metrics
)
739 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
740 const DWRITE_FONT_METRICS1
*design
= &This
->metrics
;
741 UINT16 ascent
, descent
;
744 TRACE("(%p)->(%.2f %.2f %p %p)\n", This
, em_size
, pixels_per_dip
, m
, metrics
);
746 if (em_size
<= 0.0 || pixels_per_dip
<= 0.0) {
747 memset(metrics
, 0, sizeof(*metrics
));
751 em_size
*= pixels_per_dip
;
752 if (m
&& m
->m22
!= 0.0)
753 em_size
*= fabs(m
->m22
);
755 scale
= em_size
/ design
->designUnitsPerEm
;
756 if (!opentype_get_vdmx_size(get_fontface_vdmx(This
), em_size
, &ascent
, &descent
)) {
757 ascent
= round_metric(design
->ascent
* scale
);
758 descent
= round_metric(design
->descent
* scale
);
761 #define SCALE_METRIC(x) metrics->x = round_metric(round_metric((design->x) * scale) / scale)
762 metrics
->designUnitsPerEm
= design
->designUnitsPerEm
;
763 metrics
->ascent
= round_metric(ascent
/ scale
);
764 metrics
->descent
= round_metric(descent
/ scale
);
766 SCALE_METRIC(lineGap
);
767 SCALE_METRIC(capHeight
);
768 SCALE_METRIC(xHeight
);
769 SCALE_METRIC(underlinePosition
);
770 SCALE_METRIC(underlineThickness
);
771 SCALE_METRIC(strikethroughPosition
);
772 SCALE_METRIC(strikethroughThickness
);
773 SCALE_METRIC(glyphBoxLeft
);
774 SCALE_METRIC(glyphBoxTop
);
775 SCALE_METRIC(glyphBoxRight
);
776 SCALE_METRIC(glyphBoxBottom
);
777 SCALE_METRIC(subscriptPositionX
);
778 SCALE_METRIC(subscriptPositionY
);
779 SCALE_METRIC(subscriptSizeX
);
780 SCALE_METRIC(subscriptSizeY
);
781 SCALE_METRIC(superscriptPositionX
);
782 SCALE_METRIC(superscriptPositionY
);
783 SCALE_METRIC(superscriptSizeX
);
784 SCALE_METRIC(superscriptSizeY
);
786 metrics
->hasTypographicMetrics
= design
->hasTypographicMetrics
;
792 static void WINAPI
dwritefontface1_GetCaretMetrics(IDWriteFontFace2
*iface
, DWRITE_CARET_METRICS
*metrics
)
794 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
795 TRACE("(%p)->(%p)\n", This
, metrics
);
796 *metrics
= This
->caret
;
799 static HRESULT WINAPI
dwritefontface1_GetUnicodeRanges(IDWriteFontFace2
*iface
, UINT32 max_count
,
800 DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
802 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
804 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
807 if (max_count
&& !ranges
)
810 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This
), max_count
, ranges
, count
);
813 static BOOL WINAPI
dwritefontface1_IsMonospacedFont(IDWriteFontFace2
*iface
)
815 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
816 TRACE("(%p)\n", This
);
817 return freetype_is_monospaced(iface
);
820 static HRESULT WINAPI
dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2
*iface
,
821 UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
, BOOL is_sideways
)
823 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
826 TRACE("(%p)->(%u %p %p %d)\n", This
, glyph_count
, glyphs
, advances
, is_sideways
);
828 for (i
= 0; i
< glyph_count
; i
++) {
829 DWRITE_GLYPH_METRICS metrics
= { 0 };
832 hr
= IDWriteFontFace2_GetDesignGlyphMetrics(iface
, glyphs
+ i
, 1, &metrics
, is_sideways
);
836 advances
[i
] = is_sideways
? metrics
.advanceHeight
: metrics
.advanceWidth
;
842 static HRESULT WINAPI
dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2
*iface
,
843 FLOAT em_size
, FLOAT ppdip
, const DWRITE_MATRIX
*m
, BOOL use_gdi_natural
,
844 BOOL is_sideways
, UINT32 glyph_count
, UINT16
const *glyphs
, INT32
*advances
)
846 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
851 TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This
, em_size
, ppdip
, m
,
852 use_gdi_natural
, is_sideways
, glyph_count
, glyphs
, advances
);
854 if (em_size
< 0.0 || ppdip
<= 0.0) {
855 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
859 scale
= em_size
* ppdip
/ This
->metrics
.designUnitsPerEm
;
861 memset(advances
, 0, sizeof(*advances
) * glyph_count
);
865 if (m
&& memcmp(m
, &identity
, sizeof(*m
)))
866 FIXME("transform is not supported, %s\n", debugstr_matrix(m
));
868 for (i
= 0; i
< glyph_count
; i
++) {
869 hr
= IDWriteFontFace2_GetDesignGlyphAdvances(iface
, 1, glyphs
+ i
, advances
+ i
, is_sideways
);
873 #define SCALE_METRIC(x) x = round_metric(round_metric((x) * scale) / scale)
874 SCALE_METRIC(advances
[i
]);
881 static HRESULT WINAPI
dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2
*iface
, UINT32 count
,
882 const UINT16
*indices
, INT32
*adjustments
)
884 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
887 TRACE("(%p)->(%u %p %p)\n", This
, count
, indices
, adjustments
);
889 if (!(indices
|| adjustments
) || !count
)
892 if (!indices
|| count
== 1) {
893 memset(adjustments
, 0, count
*sizeof(INT32
));
897 for (i
= 0; i
< count
-1; i
++)
898 adjustments
[i
] = freetype_get_kerning_pair_adjustment(iface
, indices
[i
], indices
[i
+1]);
899 adjustments
[count
-1] = 0;
904 static BOOL WINAPI
dwritefontface1_HasKerningPairs(IDWriteFontFace2
*iface
)
906 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
907 TRACE("(%p)\n", This
);
908 return freetype_has_kerning_pairs(iface
);
911 static HRESULT WINAPI
dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
,
912 FLOAT font_emsize
, FLOAT dpiX
, FLOAT dpiY
, const DWRITE_MATRIX
*transform
, BOOL is_sideways
,
913 DWRITE_OUTLINE_THRESHOLD threshold
, DWRITE_MEASURING_MODE measuring_mode
, DWRITE_RENDERING_MODE
*rendering_mode
)
915 DWRITE_GRID_FIT_MODE gridfitmode
;
916 return IDWriteFontFace2_GetRecommendedRenderingMode(iface
, font_emsize
, dpiX
, dpiY
, transform
, is_sideways
,
917 threshold
, measuring_mode
, NULL
, rendering_mode
, &gridfitmode
);
920 static HRESULT WINAPI
dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2
*iface
, UINT32 glyph_count
,
921 const UINT16
*nominal_indices
, UINT16
*vertical_indices
)
923 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
924 FIXME("(%p)->(%u %p %p): stub\n", This
, glyph_count
, nominal_indices
, vertical_indices
);
928 static BOOL WINAPI
dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2
*iface
)
930 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
931 FIXME("(%p): stub\n", This
);
935 static BOOL WINAPI
dwritefontface2_IsColorFont(IDWriteFontFace2
*iface
)
937 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
938 FIXME("(%p): stub\n", This
);
942 static UINT32 WINAPI
dwritefontface2_GetColorPaletteCount(IDWriteFontFace2
*iface
)
944 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
945 FIXME("(%p): stub\n", This
);
949 static UINT32 WINAPI
dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2
*iface
)
951 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
952 FIXME("(%p): stub\n", This
);
956 static HRESULT WINAPI
dwritefontface2_GetPaletteEntries(IDWriteFontFace2
*iface
, UINT32 palette_index
,
957 UINT32 first_entry_index
, UINT32 entry_count
, DWRITE_COLOR_F
*entries
)
959 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
960 FIXME("(%p)->(%u %u %u %p): stub\n", This
, palette_index
, first_entry_index
, entry_count
, entries
);
964 static HRESULT WINAPI
dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2
*iface
, FLOAT emSize
,
965 FLOAT dpiX
, FLOAT dpiY
, DWRITE_MATRIX
const *m
, BOOL is_sideways
, DWRITE_OUTLINE_THRESHOLD threshold
,
966 DWRITE_MEASURING_MODE measuringmode
, IDWriteRenderingParams
*params
, DWRITE_RENDERING_MODE
*renderingmode
,
967 DWRITE_GRID_FIT_MODE
*gridfitmode
)
969 struct dwrite_fontface
*This
= impl_from_IDWriteFontFace2(iface
);
974 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p %p %p)\n", This
, emSize
, dpiX
, dpiY
, m
, is_sideways
, threshold
,
975 measuringmode
, params
, renderingmode
, gridfitmode
);
978 FIXME("transform not supported %s\n", debugstr_matrix(m
));
981 FIXME("sideways mode not supported\n");
983 *renderingmode
= DWRITE_RENDERING_MODE_DEFAULT
;
984 *gridfitmode
= DWRITE_GRID_FIT_MODE_DEFAULT
;
986 IDWriteRenderingParams2
*params2
;
989 hr
= IDWriteRenderingParams_QueryInterface(params
, &IID_IDWriteRenderingParams2
, (void**)¶ms2
);
991 *renderingmode
= IDWriteRenderingParams2_GetRenderingMode(params2
);
992 *gridfitmode
= IDWriteRenderingParams2_GetGridFitMode(params2
);
993 IDWriteRenderingParams2_Release(params2
);
996 *renderingmode
= IDWriteRenderingParams_GetRenderingMode(params
);
999 emthreshold
= threshold
== DWRITE_OUTLINE_THRESHOLD_ANTIALIASED
? RECOMMENDED_OUTLINE_AA_THRESHOLD
: RECOMMENDED_OUTLINE_A_THRESHOLD
;
1001 ptr
= get_fontface_gasp(This
, &size
);
1002 gasp
= opentype_get_gasp_flags(ptr
, size
, emSize
);
1004 if (*renderingmode
== DWRITE_RENDERING_MODE_DEFAULT
) {
1005 if (emSize
>= emthreshold
)
1006 *renderingmode
= DWRITE_RENDERING_MODE_OUTLINE
;
1008 *renderingmode
= fontface_renderingmode_from_measuringmode(measuringmode
, emSize
, gasp
);
1011 if (*gridfitmode
== DWRITE_GRID_FIT_MODE_DEFAULT
) {
1012 if (emSize
>= emthreshold
)
1013 *gridfitmode
= DWRITE_GRID_FIT_MODE_DISABLED
;
1014 else if (measuringmode
== DWRITE_MEASURING_MODE_GDI_CLASSIC
|| measuringmode
== DWRITE_MEASURING_MODE_GDI_NATURAL
)
1015 *gridfitmode
= DWRITE_GRID_FIT_MODE_ENABLED
;
1017 *gridfitmode
= (gasp
& (GASP_GRIDFIT
|GASP_SYMMETRIC_GRIDFIT
)) ? DWRITE_GRID_FIT_MODE_ENABLED
: DWRITE_GRID_FIT_MODE_DISABLED
;
1023 static const IDWriteFontFace2Vtbl dwritefontfacevtbl
= {
1024 dwritefontface_QueryInterface
,
1025 dwritefontface_AddRef
,
1026 dwritefontface_Release
,
1027 dwritefontface_GetType
,
1028 dwritefontface_GetFiles
,
1029 dwritefontface_GetIndex
,
1030 dwritefontface_GetSimulations
,
1031 dwritefontface_IsSymbolFont
,
1032 dwritefontface_GetMetrics
,
1033 dwritefontface_GetGlyphCount
,
1034 dwritefontface_GetDesignGlyphMetrics
,
1035 dwritefontface_GetGlyphIndices
,
1036 dwritefontface_TryGetFontTable
,
1037 dwritefontface_ReleaseFontTable
,
1038 dwritefontface_GetGlyphRunOutline
,
1039 dwritefontface_GetRecommendedRenderingMode
,
1040 dwritefontface_GetGdiCompatibleMetrics
,
1041 dwritefontface_GetGdiCompatibleGlyphMetrics
,
1042 dwritefontface1_GetMetrics
,
1043 dwritefontface1_GetGdiCompatibleMetrics
,
1044 dwritefontface1_GetCaretMetrics
,
1045 dwritefontface1_GetUnicodeRanges
,
1046 dwritefontface1_IsMonospacedFont
,
1047 dwritefontface1_GetDesignGlyphAdvances
,
1048 dwritefontface1_GetGdiCompatibleGlyphAdvances
,
1049 dwritefontface1_GetKerningPairAdjustments
,
1050 dwritefontface1_HasKerningPairs
,
1051 dwritefontface1_GetRecommendedRenderingMode
,
1052 dwritefontface1_GetVerticalGlyphVariants
,
1053 dwritefontface1_HasVerticalGlyphVariants
,
1054 dwritefontface2_IsColorFont
,
1055 dwritefontface2_GetColorPaletteCount
,
1056 dwritefontface2_GetPaletteEntryCount
,
1057 dwritefontface2_GetPaletteEntries
,
1058 dwritefontface2_GetRecommendedRenderingMode
1061 HRESULT
get_family_names_from_stream(IDWriteFontFileStream
*stream
, UINT32 index
, DWRITE_FONT_FACE_TYPE facetype
,
1062 IDWriteLocalizedStrings
**names
)
1064 const void *name_table
= NULL
;
1066 HRESULT hr
= E_FAIL
;
1068 opentype_get_font_table(stream
, facetype
, index
, MS_NAME_TAG
, &name_table
, &name_context
, NULL
, NULL
);
1070 hr
= opentype_get_font_strings_from_id(name_table
, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES
, names
);
1071 IDWriteFontFileStream_ReleaseFileFragment(stream
, name_context
);
1079 static HRESULT
get_fontface_from_font(struct dwrite_font
*font
, IDWriteFontFace2
**fontface
)
1081 struct dwrite_font_data
*data
= font
->data
;
1082 IDWriteFontFace
*face
;
1087 hr
= IDWriteFactory2_CreateFontFace(data
->factory
, data
->face_type
, 1, &data
->file
,
1088 data
->face_index
, font
->simulations
, &face
);
1092 hr
= IDWriteFontFace_QueryInterface(face
, &IID_IDWriteFontFace2
, (void**)fontface
);
1093 IDWriteFontFace_Release(face
);
1098 static HRESULT WINAPI
dwritefont_QueryInterface(IDWriteFont2
*iface
, REFIID riid
, void **obj
)
1100 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1102 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1104 if (IsEqualIID(riid
, &IID_IDWriteFont2
) ||
1105 IsEqualIID(riid
, &IID_IDWriteFont1
) ||
1106 IsEqualIID(riid
, &IID_IDWriteFont
) ||
1107 IsEqualIID(riid
, &IID_IUnknown
))
1110 IDWriteFont2_AddRef(iface
);
1115 return E_NOINTERFACE
;
1118 static ULONG WINAPI
dwritefont_AddRef(IDWriteFont2
*iface
)
1120 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1121 ULONG ref
= InterlockedIncrement(&This
->ref
);
1122 TRACE("(%p)->(%d)\n", This
, ref
);
1126 static ULONG WINAPI
dwritefont_Release(IDWriteFont2
*iface
)
1128 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1129 ULONG ref
= InterlockedDecrement(&This
->ref
);
1131 TRACE("(%p)->(%d)\n", This
, ref
);
1134 IDWriteFontFamily_Release(This
->family
);
1135 release_font_data(This
->data
);
1142 static HRESULT WINAPI
dwritefont_GetFontFamily(IDWriteFont2
*iface
, IDWriteFontFamily
**family
)
1144 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1145 TRACE("(%p)->(%p)\n", This
, family
);
1147 *family
= This
->family
;
1148 IDWriteFontFamily_AddRef(*family
);
1152 static DWRITE_FONT_WEIGHT WINAPI
dwritefont_GetWeight(IDWriteFont2
*iface
)
1154 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1155 TRACE("(%p)\n", This
);
1156 return This
->data
->weight
;
1159 static DWRITE_FONT_STRETCH WINAPI
dwritefont_GetStretch(IDWriteFont2
*iface
)
1161 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1162 TRACE("(%p)\n", This
);
1163 return This
->data
->stretch
;
1166 static DWRITE_FONT_STYLE WINAPI
dwritefont_GetStyle(IDWriteFont2
*iface
)
1168 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1169 TRACE("(%p)\n", This
);
1173 static BOOL WINAPI
dwritefont_IsSymbolFont(IDWriteFont2
*iface
)
1175 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1176 IDWriteFontFace2
*fontface
;
1179 TRACE("(%p)\n", This
);
1181 hr
= get_fontface_from_font(This
, &fontface
);
1185 return IDWriteFontFace2_IsSymbolFont(fontface
);
1188 static HRESULT WINAPI
dwritefont_GetFaceNames(IDWriteFont2
*iface
, IDWriteLocalizedStrings
**names
)
1190 static const WCHAR boldobliqueW
[] = {'B','o','l','d',' ','O','b','l','i','q','u','e',0};
1191 static const WCHAR obliqueW
[] = {'O','b','l','i','q','u','e',0};
1192 static const WCHAR boldW
[] = {'B','o','l','d',0};
1193 static const WCHAR enusW
[] = {'e','n','-','u','s',0};
1195 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1196 IDWriteLocalizedStrings
*strings
;
1200 TRACE("(%p)->(%p)\n", This
, names
);
1204 if (This
->simulations
== DWRITE_FONT_SIMULATIONS_NONE
) {
1206 return IDWriteFont2_GetInformationalStrings(iface
, DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES
,
1210 switch (This
->simulations
) {
1211 case DWRITE_FONT_SIMULATIONS_BOLD
|DWRITE_FONT_SIMULATIONS_OBLIQUE
:
1212 name
= boldobliqueW
;
1214 case DWRITE_FONT_SIMULATIONS_BOLD
:
1217 case DWRITE_FONT_SIMULATIONS_OBLIQUE
:
1221 ERR("unknown simulations %d\n", This
->simulations
);
1225 hr
= create_localizedstrings(&strings
);
1226 if (FAILED(hr
)) return hr
;
1228 hr
= add_localizedstring(strings
, enusW
, name
);
1230 IDWriteLocalizedStrings_Release(strings
);
1239 static HRESULT WINAPI
dwritefont_GetInformationalStrings(IDWriteFont2
*iface
,
1240 DWRITE_INFORMATIONAL_STRING_ID stringid
, IDWriteLocalizedStrings
**strings
, BOOL
*exists
)
1242 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1243 struct dwrite_font_data
*data
= This
->data
;
1246 TRACE("(%p)->(%d %p %p)\n", This
, stringid
, strings
, exists
);
1251 if (stringid
> DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME
|| stringid
== DWRITE_INFORMATIONAL_STRING_NONE
)
1254 if (!data
->info_strings
[stringid
]) {
1255 IDWriteFontFace2
*fontface
;
1256 const void *table_data
;
1261 hr
= get_fontface_from_font(This
, &fontface
);
1265 table_exists
= FALSE
;
1266 hr
= IDWriteFontFace2_TryGetFontTable(fontface
, MS_NAME_TAG
, &table_data
, &size
, &context
, &table_exists
);
1267 if (FAILED(hr
) || !table_exists
)
1268 WARN("no NAME table found.\n");
1271 hr
= opentype_get_font_strings_from_id(table_data
, stringid
, &data
->info_strings
[stringid
]);
1272 if (FAILED(hr
) || !data
->info_strings
[stringid
])
1274 IDWriteFontFace2_ReleaseFontTable(fontface
, context
);
1278 hr
= clone_localizedstring(data
->info_strings
[stringid
], strings
);
1286 static DWRITE_FONT_SIMULATIONS WINAPI
dwritefont_GetSimulations(IDWriteFont2
*iface
)
1288 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1289 TRACE("(%p)\n", This
);
1290 return This
->simulations
;
1293 static void WINAPI
dwritefont_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS
*metrics
)
1295 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1297 TRACE("(%p)->(%p)\n", This
, metrics
);
1298 memcpy(metrics
, &This
->data
->metrics
, sizeof(*metrics
));
1301 static HRESULT WINAPI
dwritefont_HasCharacter(IDWriteFont2
*iface
, UINT32 value
, BOOL
*exists
)
1303 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1304 IDWriteFontFace2
*fontface
;
1308 TRACE("(%p)->(0x%08x %p)\n", This
, value
, exists
);
1312 hr
= get_fontface_from_font(This
, &fontface
);
1317 hr
= IDWriteFontFace2_GetGlyphIndices(fontface
, &value
, 1, &index
);
1321 *exists
= index
!= 0;
1325 static HRESULT WINAPI
dwritefont_CreateFontFace(IDWriteFont2
*iface
, IDWriteFontFace
**face
)
1327 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1330 TRACE("(%p)->(%p)\n", This
, face
);
1332 hr
= get_fontface_from_font(This
, (IDWriteFontFace2
**)face
);
1334 IDWriteFontFace_AddRef(*face
);
1339 static void WINAPI
dwritefont1_GetMetrics(IDWriteFont2
*iface
, DWRITE_FONT_METRICS1
*metrics
)
1341 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1342 TRACE("(%p)->(%p)\n", This
, metrics
);
1343 *metrics
= This
->data
->metrics
;
1346 static void WINAPI
dwritefont1_GetPanose(IDWriteFont2
*iface
, DWRITE_PANOSE
*panose
)
1348 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1349 TRACE("(%p)->(%p)\n", This
, panose
);
1350 *panose
= This
->data
->panose
;
1353 static HRESULT WINAPI
dwritefont1_GetUnicodeRanges(IDWriteFont2
*iface
, UINT32 max_count
, DWRITE_UNICODE_RANGE
*ranges
, UINT32
*count
)
1355 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1356 IDWriteFontFace2
*fontface
;
1359 TRACE("(%p)->(%u %p %p)\n", This
, max_count
, ranges
, count
);
1361 hr
= get_fontface_from_font(This
, &fontface
);
1365 return IDWriteFontFace2_GetUnicodeRanges(fontface
, max_count
, ranges
, count
);
1368 static BOOL WINAPI
dwritefont1_IsMonospacedFont(IDWriteFont2
*iface
)
1370 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1371 IDWriteFontFace2
*fontface
;
1374 TRACE("(%p)\n", This
);
1376 hr
= get_fontface_from_font(This
, &fontface
);
1380 return IDWriteFontFace2_IsMonospacedFont(fontface
);
1383 static HRESULT WINAPI
dwritefont2_IsColorFont(IDWriteFont2
*iface
)
1385 struct dwrite_font
*This
= impl_from_IDWriteFont2(iface
);
1386 IDWriteFontFace2
*fontface
;
1389 TRACE("(%p)\n", This
);
1391 hr
= get_fontface_from_font(This
, &fontface
);
1395 return IDWriteFontFace2_IsColorFont(fontface
);
1398 static const IDWriteFont2Vtbl dwritefontvtbl
= {
1399 dwritefont_QueryInterface
,
1402 dwritefont_GetFontFamily
,
1403 dwritefont_GetWeight
,
1404 dwritefont_GetStretch
,
1405 dwritefont_GetStyle
,
1406 dwritefont_IsSymbolFont
,
1407 dwritefont_GetFaceNames
,
1408 dwritefont_GetInformationalStrings
,
1409 dwritefont_GetSimulations
,
1410 dwritefont_GetMetrics
,
1411 dwritefont_HasCharacter
,
1412 dwritefont_CreateFontFace
,
1413 dwritefont1_GetMetrics
,
1414 dwritefont1_GetPanose
,
1415 dwritefont1_GetUnicodeRanges
,
1416 dwritefont1_IsMonospacedFont
,
1417 dwritefont2_IsColorFont
1420 static HRESULT
create_font(struct dwrite_font_data
*data
, IDWriteFontFamily
*family
, DWRITE_FONT_SIMULATIONS simulations
,
1423 struct dwrite_font
*This
;
1426 This
= heap_alloc(sizeof(struct dwrite_font
));
1427 if (!This
) return E_OUTOFMEMORY
;
1429 This
->IDWriteFont2_iface
.lpVtbl
= &dwritefontvtbl
;
1431 This
->family
= family
;
1432 IDWriteFontFamily_AddRef(family
);
1433 This
->simulations
= simulations
;
1434 This
->style
= data
->style
;
1436 InterlockedIncrement(&This
->data
->ref
);
1438 /* set oblique style from requested simulation */
1439 if ((simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) && data
->style
== DWRITE_FONT_STYLE_NORMAL
)
1440 This
->style
= DWRITE_FONT_STYLE_OBLIQUE
;
1442 *font
= (IDWriteFont
*)&This
->IDWriteFont2_iface
;
1447 static HRESULT WINAPI
dwritefontfamily_QueryInterface(IDWriteFontFamily
*iface
, REFIID riid
, void **obj
)
1449 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1450 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1452 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1453 IsEqualIID(riid
, &IID_IDWriteFontList
) ||
1454 IsEqualIID(riid
, &IID_IDWriteFontFamily
))
1457 IDWriteFontFamily_AddRef(iface
);
1462 return E_NOINTERFACE
;
1465 static ULONG WINAPI
dwritefontfamily_AddRef(IDWriteFontFamily
*iface
)
1467 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1468 ULONG ref
= InterlockedIncrement(&This
->ref
);
1469 TRACE("(%p)->(%d)\n", This
, ref
);
1473 static ULONG WINAPI
dwritefontfamily_Release(IDWriteFontFamily
*iface
)
1475 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1476 ULONG ref
= InterlockedDecrement(&This
->ref
);
1478 TRACE("(%p)->(%d)\n", This
, ref
);
1482 IDWriteFontCollection_Release(This
->collection
);
1483 release_fontfamily_data(This
->data
);
1490 static HRESULT WINAPI
dwritefontfamily_GetFontCollection(IDWriteFontFamily
*iface
, IDWriteFontCollection
**collection
)
1492 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1493 TRACE("(%p)->(%p)\n", This
, collection
);
1495 *collection
= This
->collection
;
1496 IDWriteFontCollection_AddRef(This
->collection
);
1500 static UINT32 WINAPI
dwritefontfamily_GetFontCount(IDWriteFontFamily
*iface
)
1502 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1503 TRACE("(%p)\n", This
);
1504 return This
->data
->font_count
;
1507 static HRESULT WINAPI
dwritefontfamily_GetFont(IDWriteFontFamily
*iface
, UINT32 index
, IDWriteFont
**font
)
1509 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1511 TRACE("(%p)->(%u %p)\n", This
, index
, font
);
1515 if (This
->data
->font_count
== 0)
1518 if (index
>= This
->data
->font_count
)
1519 return E_INVALIDARG
;
1521 return create_font(This
->data
->fonts
[index
], iface
, DWRITE_FONT_SIMULATIONS_NONE
, font
);
1524 static HRESULT WINAPI
dwritefontfamily_GetFamilyNames(IDWriteFontFamily
*iface
, IDWriteLocalizedStrings
**names
)
1526 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1527 return clone_localizedstring(This
->data
->familyname
, names
);
1530 static inline BOOL
is_matching_font_style(DWRITE_FONT_STYLE style
, DWRITE_FONT_STYLE font_style
)
1532 if (style
== font_style
)
1535 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) && font_style
== DWRITE_FONT_STYLE_NORMAL
)
1541 static HRESULT WINAPI
dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1542 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFont
**font
)
1544 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1545 UINT32 min_weight_diff
= ~0u;
1548 TRACE("(%p)->(%d %d %d %p)\n", This
, weight
, stretch
, style
, font
);
1550 for (i
= 0; i
< This
->data
->font_count
; i
++) {
1551 if (is_matching_font_style(style
, This
->data
->fonts
[i
]->style
) && stretch
== This
->data
->fonts
[i
]->stretch
) {
1552 DWRITE_FONT_WEIGHT font_weight
= This
->data
->fonts
[i
]->weight
;
1553 UINT32 weight_diff
= abs(font_weight
- weight
);
1554 if (weight_diff
< min_weight_diff
) {
1555 min_weight_diff
= weight_diff
;
1562 DWRITE_FONT_SIMULATIONS simulations
= DWRITE_FONT_SIMULATIONS_NONE
;
1564 if (((style
== DWRITE_FONT_STYLE_ITALIC
) || (style
== DWRITE_FONT_STYLE_OBLIQUE
)) &&
1565 This
->data
->fonts
[found
]->style
== DWRITE_FONT_STYLE_NORMAL
) {
1566 simulations
= DWRITE_FONT_SIMULATIONS_OBLIQUE
;
1568 return create_font(This
->data
->fonts
[found
], iface
, simulations
, font
);
1572 return DWRITE_E_NOFONT
;
1576 static HRESULT WINAPI
dwritefontfamily_GetMatchingFonts(IDWriteFontFamily
*iface
, DWRITE_FONT_WEIGHT weight
,
1577 DWRITE_FONT_STRETCH stretch
, DWRITE_FONT_STYLE style
, IDWriteFontList
**fonts
)
1579 struct dwrite_fontfamily
*This
= impl_from_IDWriteFontFamily(iface
);
1580 FIXME("(%p)->(%d %d %d %p): stub\n", This
, weight
, stretch
, style
, fonts
);
1584 static const IDWriteFontFamilyVtbl fontfamilyvtbl
= {
1585 dwritefontfamily_QueryInterface
,
1586 dwritefontfamily_AddRef
,
1587 dwritefontfamily_Release
,
1588 dwritefontfamily_GetFontCollection
,
1589 dwritefontfamily_GetFontCount
,
1590 dwritefontfamily_GetFont
,
1591 dwritefontfamily_GetFamilyNames
,
1592 dwritefontfamily_GetFirstMatchingFont
,
1593 dwritefontfamily_GetMatchingFonts
1596 static HRESULT
create_fontfamily(struct dwrite_fontfamily_data
*data
, IDWriteFontCollection
*collection
, IDWriteFontFamily
**family
)
1598 struct dwrite_fontfamily
*This
;
1602 This
= heap_alloc(sizeof(struct dwrite_fontfamily
));
1603 if (!This
) return E_OUTOFMEMORY
;
1605 This
->IDWriteFontFamily_iface
.lpVtbl
= &fontfamilyvtbl
;
1607 This
->collection
= collection
;
1608 IDWriteFontCollection_AddRef(collection
);
1610 InterlockedIncrement(&This
->data
->ref
);
1612 *family
= &This
->IDWriteFontFamily_iface
;
1617 BOOL
is_system_collection(IDWriteFontCollection
*collection
)
1620 return IDWriteFontCollection_QueryInterface(collection
, &IID_issystemcollection
, (void**)&obj
) == S_OK
;
1623 static HRESULT WINAPI
dwritefontcollection_QueryInterface(IDWriteFontCollection
*iface
, REFIID riid
, void **obj
)
1625 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1626 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1628 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1629 IsEqualIID(riid
, &IID_IDWriteFontCollection
))
1632 IDWriteFontCollection_AddRef(iface
);
1638 if (This
->is_system
&& IsEqualIID(riid
, &IID_issystemcollection
))
1641 return E_NOINTERFACE
;
1644 static ULONG WINAPI
dwritefontcollection_AddRef(IDWriteFontCollection
*iface
)
1646 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1647 ULONG ref
= InterlockedIncrement(&This
->ref
);
1648 TRACE("(%p)->(%d)\n", This
, ref
);
1652 static ULONG WINAPI
dwritefontcollection_Release(IDWriteFontCollection
*iface
)
1655 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1656 ULONG ref
= InterlockedDecrement(&This
->ref
);
1657 TRACE("(%p)->(%d)\n", This
, ref
);
1660 for (i
= 0; i
< This
->family_count
; i
++)
1661 release_fontfamily_data(This
->family_data
[i
]);
1662 heap_free(This
->family_data
);
1669 static UINT32 WINAPI
dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection
*iface
)
1671 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1672 TRACE("(%p)\n", This
);
1673 return This
->family_count
;
1676 static HRESULT WINAPI
dwritefontcollection_GetFontFamily(IDWriteFontCollection
*iface
, UINT32 index
, IDWriteFontFamily
**family
)
1678 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1680 TRACE("(%p)->(%u %p)\n", This
, index
, family
);
1682 if (index
>= This
->family_count
) {
1687 return create_fontfamily(This
->family_data
[index
], iface
, family
);
1690 static UINT32
collection_find_family(struct dwrite_fontcollection
*collection
, const WCHAR
*name
)
1694 for (i
= 0; i
< collection
->family_count
; i
++) {
1695 IDWriteLocalizedStrings
*family_name
= collection
->family_data
[i
]->familyname
;
1696 UINT32 j
, count
= IDWriteLocalizedStrings_GetCount(family_name
);
1699 for (j
= 0; j
< count
; j
++) {
1701 hr
= IDWriteLocalizedStrings_GetString(family_name
, j
, buffer
, 255);
1702 if (SUCCEEDED(hr
) && !strcmpiW(buffer
, name
))
1710 static HRESULT WINAPI
dwritefontcollection_FindFamilyName(IDWriteFontCollection
*iface
, const WCHAR
*name
, UINT32
*index
, BOOL
*exists
)
1712 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1713 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_w(name
), index
, exists
);
1714 *index
= collection_find_family(This
, name
);
1715 *exists
= *index
!= ~0u;
1719 static BOOL
is_same_fontfile(IDWriteFontFile
*left
, IDWriteFontFile
*right
)
1721 UINT32 left_key_size
, right_key_size
;
1722 const void *left_key
, *right_key
;
1728 hr
= IDWriteFontFile_GetReferenceKey(left
, &left_key
, &left_key_size
);
1732 hr
= IDWriteFontFile_GetReferenceKey(right
, &right_key
, &right_key_size
);
1736 if (left_key_size
!= right_key_size
)
1739 return !memcmp(left_key
, right_key
, left_key_size
);
1742 static HRESULT WINAPI
dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection
*iface
, IDWriteFontFace
*face
, IDWriteFont
**font
)
1744 struct dwrite_fontcollection
*This
= impl_from_IDWriteFontCollection(iface
);
1745 struct dwrite_fontfamily_data
*found_family
= NULL
;
1746 struct dwrite_font_data
*found_font
= NULL
;
1747 DWRITE_FONT_SIMULATIONS simulations
;
1748 IDWriteFontFamily
*family
;
1749 UINT32 i
, j
, face_index
;
1750 IDWriteFontFile
*file
;
1753 TRACE("(%p)->(%p %p)\n", This
, face
, font
);
1758 return E_INVALIDARG
;
1761 hr
= IDWriteFontFace_GetFiles(face
, &i
, &file
);
1764 face_index
= IDWriteFontFace_GetIndex(face
);
1766 for (i
= 0; i
< This
->family_count
; i
++) {
1767 struct dwrite_fontfamily_data
*family_data
= This
->family_data
[i
];
1768 for (j
= 0; j
< family_data
->font_count
; j
++) {
1769 struct dwrite_font_data
*font_data
= family_data
->fonts
[j
];
1771 if (face_index
== font_data
->face_index
&& is_same_fontfile(file
, font_data
->file
)) {
1772 found_font
= font_data
;
1773 found_family
= family_data
;
1780 return DWRITE_E_NOFONT
;
1782 hr
= create_fontfamily(found_family
, iface
, &family
);
1786 simulations
= IDWriteFontFace_GetSimulations(face
);
1787 hr
= create_font(found_font
, family
, simulations
, font
);
1788 IDWriteFontFamily_Release(family
);
1792 static const IDWriteFontCollectionVtbl fontcollectionvtbl
= {
1793 dwritefontcollection_QueryInterface
,
1794 dwritefontcollection_AddRef
,
1795 dwritefontcollection_Release
,
1796 dwritefontcollection_GetFontFamilyCount
,
1797 dwritefontcollection_GetFontFamily
,
1798 dwritefontcollection_FindFamilyName
,
1799 dwritefontcollection_GetFontFromFontFace
1802 static HRESULT
fontfamily_add_font(struct dwrite_fontfamily_data
*family_data
, struct dwrite_font_data
*font_data
)
1804 if (family_data
->font_count
+ 1 >= family_data
->font_alloc
) {
1805 struct dwrite_font_data
**new_list
;
1808 new_alloc
= family_data
->font_alloc
* 2;
1809 new_list
= heap_realloc(family_data
->fonts
, sizeof(*family_data
->fonts
) * new_alloc
);
1811 return E_OUTOFMEMORY
;
1812 family_data
->fonts
= new_list
;
1813 family_data
->font_alloc
= new_alloc
;
1816 family_data
->fonts
[family_data
->font_count
] = font_data
;
1817 family_data
->font_count
++;
1821 static HRESULT
fontcollection_add_family(struct dwrite_fontcollection
*collection
, struct dwrite_fontfamily_data
*family
)
1823 if (collection
->family_alloc
< collection
->family_count
+ 1) {
1824 struct dwrite_fontfamily_data
**new_list
;
1827 new_alloc
= collection
->family_alloc
* 2;
1828 new_list
= heap_realloc(collection
->family_data
, sizeof(*new_list
) * new_alloc
);
1830 return E_OUTOFMEMORY
;
1832 collection
->family_alloc
= new_alloc
;
1833 collection
->family_data
= new_list
;
1836 collection
->family_data
[collection
->family_count
] = family
;
1837 collection
->family_count
++;
1842 static HRESULT
init_font_collection(struct dwrite_fontcollection
*collection
, BOOL is_system
)
1844 collection
->IDWriteFontCollection_iface
.lpVtbl
= &fontcollectionvtbl
;
1845 collection
->ref
= 1;
1846 collection
->family_count
= 0;
1847 collection
->family_alloc
= 2;
1848 collection
->is_system
= is_system
;
1850 collection
->family_data
= heap_alloc(sizeof(*collection
->family_data
)*2);
1851 if (!collection
->family_data
)
1852 return E_OUTOFMEMORY
;
1857 HRESULT
get_filestream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
1859 IDWriteFontFileLoader
*loader
;
1866 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
1870 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
1874 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
1875 IDWriteFontFileLoader_Release(loader
);
1882 static HRESULT
init_font_data(IDWriteFactory2
*factory
, IDWriteFontFile
*file
, UINT32 face_index
, DWRITE_FONT_FACE_TYPE face_type
,
1883 IDWriteFontFileStream
**stream
, struct dwrite_font_data
**ret
)
1885 void *os2_context
, *head_context
;
1886 const void *tt_os2
= NULL
, *tt_head
= NULL
;
1887 struct dwrite_font_props props
;
1888 struct dwrite_font_data
*data
;
1891 data
= heap_alloc_zero(sizeof(*data
));
1893 return E_OUTOFMEMORY
;
1895 hr
= get_filestream_from_file(file
, stream
);
1902 data
->factory
= factory
;
1904 data
->face_index
= face_index
;
1905 data
->face_type
= face_type
;
1906 IDWriteFontFile_AddRef(file
);
1907 IDWriteFactory2_AddRef(factory
);
1909 opentype_get_font_table(*stream
, face_type
, face_index
, MS_OS2_TAG
, &tt_os2
, &os2_context
, NULL
, NULL
);
1910 opentype_get_font_table(*stream
, face_type
, face_index
, MS_HEAD_TAG
, &tt_head
, &head_context
, NULL
, NULL
);
1912 opentype_get_font_properties(*stream
, face_type
, face_index
, &props
);
1913 opentype_get_font_metrics(*stream
, face_type
, face_index
, &data
->metrics
, NULL
);
1915 data
->style
= props
.style
;
1916 data
->stretch
= props
.stretch
;
1917 data
->weight
= props
.weight
;
1918 data
->panose
= props
.panose
;
1921 IDWriteFontFileStream_ReleaseFileFragment(*stream
, os2_context
);
1923 IDWriteFontFileStream_ReleaseFileFragment(*stream
, head_context
);
1929 static HRESULT
init_fontfamily_data(IDWriteLocalizedStrings
*familyname
, struct dwrite_fontfamily_data
**ret
)
1931 struct dwrite_fontfamily_data
*data
;
1933 data
= heap_alloc(sizeof(*data
));
1935 return E_OUTOFMEMORY
;
1938 data
->font_count
= 0;
1939 data
->font_alloc
= 2;
1941 data
->fonts
= heap_alloc(sizeof(*data
->fonts
)*data
->font_alloc
);
1944 return E_OUTOFMEMORY
;
1947 data
->familyname
= familyname
;
1948 IDWriteLocalizedStrings_AddRef(familyname
);
1954 HRESULT
create_font_collection(IDWriteFactory2
* factory
, IDWriteFontFileEnumerator
*enumerator
, BOOL is_system
, IDWriteFontCollection
**ret
)
1956 struct dwrite_fontcollection
*collection
;
1957 BOOL current
= FALSE
;
1962 collection
= heap_alloc(sizeof(struct dwrite_fontcollection
));
1963 if (!collection
) return E_OUTOFMEMORY
;
1965 hr
= init_font_collection(collection
, is_system
);
1967 heap_free(collection
);
1971 *ret
= &collection
->IDWriteFontCollection_iface
;
1973 TRACE("building font collection:\n");
1975 while (hr
== S_OK
) {
1976 DWRITE_FONT_FACE_TYPE face_type
;
1977 DWRITE_FONT_FILE_TYPE file_type
;
1978 IDWriteFontFile
*file
;
1984 hr
= IDWriteFontFileEnumerator_MoveNext(enumerator
, ¤t
);
1985 if (FAILED(hr
) || !current
)
1988 hr
= IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator
, &file
);
1992 /* failed font files are skipped */
1993 hr
= IDWriteFontFile_Analyze(file
, &supported
, &file_type
, &face_type
, &face_count
);
1994 if (FAILED(hr
) || !supported
|| face_count
== 0) {
1995 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file
, hr
, supported
, face_count
);
1996 IDWriteFontFile_Release(file
);
2001 for (i
= 0; i
< face_count
; i
++) {
2002 IDWriteLocalizedStrings
*family_name
= NULL
;
2003 struct dwrite_font_data
*font_data
;
2004 IDWriteFontFileStream
*stream
;
2008 /* alloc and init new font data structure */
2009 hr
= init_font_data(factory
, file
, i
, face_type
, &stream
, &font_data
);
2013 /* get family name from font file */
2014 hr
= get_family_names_from_stream(stream
, i
, face_type
, &family_name
);
2015 IDWriteFontFileStream_Release(stream
);
2017 WARN("unable to get family name from font\n");
2018 release_font_data(font_data
);
2023 IDWriteLocalizedStrings_GetString(family_name
, 0, buffer
, sizeof(buffer
)/sizeof(WCHAR
));
2025 index
= collection_find_family(collection
, buffer
);
2027 hr
= fontfamily_add_font(collection
->family_data
[index
], font_data
);
2029 struct dwrite_fontfamily_data
*family_data
;
2031 /* create and init new family */
2032 hr
= init_fontfamily_data(family_name
, &family_data
);
2034 /* add font to family, family - to collection */
2035 hr
= fontfamily_add_font(family_data
, font_data
);
2037 hr
= fontcollection_add_family(collection
, family_data
);
2040 release_fontfamily_data(family_data
);
2044 IDWriteLocalizedStrings_Release(family_name
);
2050 IDWriteFontFile_Release(file
);
2056 struct system_fontfile_enumerator
2058 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface
;
2061 IDWriteFactory2
*factory
;
2066 static inline struct system_fontfile_enumerator
*impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator
* iface
)
2068 return CONTAINING_RECORD(iface
, struct system_fontfile_enumerator
, IDWriteFontFileEnumerator_iface
);
2071 static HRESULT WINAPI
systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2075 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
2076 IDWriteFontFileEnumerator_AddRef(iface
);
2081 return E_NOINTERFACE
;
2084 static ULONG WINAPI
systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2086 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
2087 return InterlockedIncrement(&enumerator
->ref
);
2090 static ULONG WINAPI
systemfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2092 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
2093 ULONG ref
= InterlockedDecrement(&enumerator
->ref
);
2096 IDWriteFactory2_Release(enumerator
->factory
);
2097 RegCloseKey(enumerator
->hkey
);
2098 heap_free(enumerator
);
2104 static HRESULT WINAPI
systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2106 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
2107 DWORD ret
, type
, val_count
, count
;
2108 WCHAR
*value
, *filename
;
2113 if (enumerator
->index
< 0)
2116 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &val_count
, &count
, NULL
, NULL
);
2117 if (ret
!= ERROR_SUCCESS
)
2121 value
= heap_alloc( val_count
* sizeof(value
[0]) );
2122 filename
= heap_alloc(count
);
2123 if (!value
|| !filename
) {
2125 heap_free(filename
);
2126 return E_OUTOFMEMORY
;
2129 ret
= RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, (BYTE
*)filename
, &count
);
2132 heap_free(filename
);
2136 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
2137 if (!strchrW(filename
, '\\')) {
2138 static const WCHAR fontsW
[] = {'\\','f','o','n','t','s','\\',0};
2139 WCHAR fullpathW
[MAX_PATH
];
2141 GetWindowsDirectoryW(fullpathW
, sizeof(fullpathW
)/sizeof(WCHAR
));
2142 strcatW(fullpathW
, fontsW
);
2143 strcatW(fullpathW
, filename
);
2145 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, fullpathW
, NULL
, file
);
2148 hr
= IDWriteFactory2_CreateFontFileReference(enumerator
->factory
, filename
, NULL
, file
);
2151 heap_free(filename
);
2155 static HRESULT WINAPI
systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2157 struct system_fontfile_enumerator
*enumerator
= impl_from_IDWriteFontFileEnumerator(iface
);
2158 DWORD ret
, max_val_count
;
2162 enumerator
->index
++;
2164 ret
= RegQueryInfoKeyW(enumerator
->hkey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &max_val_count
, NULL
, NULL
, NULL
);
2165 if (ret
!= ERROR_SUCCESS
)
2169 if (!(value
= heap_alloc( max_val_count
* sizeof(value
[0]) )))
2170 return E_OUTOFMEMORY
;
2172 /* iterate until we find next string value */
2174 DWORD type
= 0, count
, val_count
;
2175 val_count
= max_val_count
;
2176 if (RegEnumValueW(enumerator
->hkey
, enumerator
->index
, value
, &val_count
, NULL
, &type
, NULL
, &count
))
2178 if (type
== REG_SZ
) {
2182 enumerator
->index
++;
2185 TRACE("index = %d, current = %d\n", enumerator
->index
, *current
);
2190 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl
=
2192 systemfontfileenumerator_QueryInterface
,
2193 systemfontfileenumerator_AddRef
,
2194 systemfontfileenumerator_Release
,
2195 systemfontfileenumerator_MoveNext
,
2196 systemfontfileenumerator_GetCurrentFontFile
2199 static HRESULT
create_system_fontfile_enumerator(IDWriteFactory2
*factory
, IDWriteFontFileEnumerator
**ret
)
2201 struct system_fontfile_enumerator
*enumerator
;
2202 static const WCHAR fontslistW
[] = {
2203 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
2204 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2205 'F','o','n','t','s',0
2210 enumerator
= heap_alloc(sizeof(*enumerator
));
2212 return E_OUTOFMEMORY
;
2214 enumerator
->IDWriteFontFileEnumerator_iface
.lpVtbl
= &systemfontfileenumeratorvtbl
;
2215 enumerator
->ref
= 1;
2216 enumerator
->factory
= factory
;
2217 enumerator
->index
= -1;
2218 IDWriteFactory2_AddRef(factory
);
2220 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fontslistW
, 0, GENERIC_READ
, &enumerator
->hkey
)) {
2221 ERR("failed to open fonts list key\n");
2222 IDWriteFactory2_Release(factory
);
2223 heap_free(enumerator
);
2227 *ret
= &enumerator
->IDWriteFontFileEnumerator_iface
;
2232 HRESULT
get_system_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
2234 IDWriteFontFileEnumerator
*enumerator
;
2239 hr
= create_system_fontfile_enumerator(factory
, &enumerator
);
2243 TRACE("building system font collection for factory %p\n", factory
);
2244 hr
= create_font_collection(factory
, enumerator
, TRUE
, collection
);
2245 IDWriteFontFileEnumerator_Release(enumerator
);
2249 static HRESULT WINAPI
eudcfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator
*iface
, REFIID riid
, void **obj
)
2253 if (IsEqualIID(riid
, &IID_IDWriteFontFileEnumerator
) || IsEqualIID(riid
, &IID_IUnknown
)) {
2254 IDWriteFontFileEnumerator_AddRef(iface
);
2259 return E_NOINTERFACE
;
2262 static ULONG WINAPI
eudcfontfileenumerator_AddRef(IDWriteFontFileEnumerator
*iface
)
2267 static ULONG WINAPI
eudcfontfileenumerator_Release(IDWriteFontFileEnumerator
*iface
)
2272 static HRESULT WINAPI
eudcfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator
*iface
, IDWriteFontFile
**file
)
2278 static HRESULT WINAPI
eudcfontfileenumerator_MoveNext(IDWriteFontFileEnumerator
*iface
, BOOL
*current
)
2284 static const struct IDWriteFontFileEnumeratorVtbl eudcfontfileenumeratorvtbl
=
2286 eudcfontfileenumerator_QueryInterface
,
2287 eudcfontfileenumerator_AddRef
,
2288 eudcfontfileenumerator_Release
,
2289 eudcfontfileenumerator_MoveNext
,
2290 eudcfontfileenumerator_GetCurrentFontFile
2293 static IDWriteFontFileEnumerator eudc_fontfile_enumerator
= { &eudcfontfileenumeratorvtbl
};
2295 HRESULT
get_eudc_fontcollection(IDWriteFactory2
*factory
, IDWriteFontCollection
**collection
)
2297 TRACE("building EUDC font collection for factory %p\n", factory
);
2298 return create_font_collection(factory
, &eudc_fontfile_enumerator
, FALSE
, collection
);
2301 static HRESULT WINAPI
dwritefontfile_QueryInterface(IDWriteFontFile
*iface
, REFIID riid
, void **obj
)
2303 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2305 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2307 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFile
))
2310 IDWriteFontFile_AddRef(iface
);
2315 return E_NOINTERFACE
;
2318 static ULONG WINAPI
dwritefontfile_AddRef(IDWriteFontFile
*iface
)
2320 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2321 ULONG ref
= InterlockedIncrement(&This
->ref
);
2322 TRACE("(%p)->(%d)\n", This
, ref
);
2326 static ULONG WINAPI
dwritefontfile_Release(IDWriteFontFile
*iface
)
2328 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2329 ULONG ref
= InterlockedDecrement(&This
->ref
);
2331 TRACE("(%p)->(%d)\n", This
, ref
);
2335 IDWriteFontFileLoader_Release(This
->loader
);
2336 if (This
->stream
) IDWriteFontFileStream_Release(This
->stream
);
2337 heap_free(This
->reference_key
);
2344 static HRESULT WINAPI
dwritefontfile_GetReferenceKey(IDWriteFontFile
*iface
, const void **fontFileReferenceKey
, UINT32
*fontFileReferenceKeySize
)
2346 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2347 TRACE("(%p)->(%p, %p)\n", This
, fontFileReferenceKey
, fontFileReferenceKeySize
);
2348 *fontFileReferenceKey
= This
->reference_key
;
2349 *fontFileReferenceKeySize
= This
->key_size
;
2354 static HRESULT WINAPI
dwritefontfile_GetLoader(IDWriteFontFile
*iface
, IDWriteFontFileLoader
**fontFileLoader
)
2356 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2357 TRACE("(%p)->(%p)\n", This
, fontFileLoader
);
2358 *fontFileLoader
= This
->loader
;
2359 IDWriteFontFileLoader_AddRef(This
->loader
);
2364 static HRESULT WINAPI
dwritefontfile_Analyze(IDWriteFontFile
*iface
, BOOL
*isSupportedFontType
, DWRITE_FONT_FILE_TYPE
*fontFileType
, DWRITE_FONT_FACE_TYPE
*fontFaceType
, UINT32
*numberOfFaces
)
2366 struct dwrite_fontfile
*This
= impl_from_IDWriteFontFile(iface
);
2367 IDWriteFontFileStream
*stream
;
2370 TRACE("(%p)->(%p, %p, %p, %p)\n", This
, isSupportedFontType
, fontFileType
, fontFaceType
, numberOfFaces
);
2372 *isSupportedFontType
= FALSE
;
2373 *fontFileType
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
2375 *fontFaceType
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
2378 hr
= IDWriteFontFileLoader_CreateStreamFromKey(This
->loader
, This
->reference_key
, This
->key_size
, &stream
);
2382 hr
= opentype_analyze_font(stream
, numberOfFaces
, fontFileType
, fontFaceType
, isSupportedFontType
);
2384 /* TODO: Further Analysis */
2385 IDWriteFontFileStream_Release(stream
);
2389 static const IDWriteFontFileVtbl dwritefontfilevtbl
= {
2390 dwritefontfile_QueryInterface
,
2391 dwritefontfile_AddRef
,
2392 dwritefontfile_Release
,
2393 dwritefontfile_GetReferenceKey
,
2394 dwritefontfile_GetLoader
,
2395 dwritefontfile_Analyze
,
2398 HRESULT
create_font_file(IDWriteFontFileLoader
*loader
, const void *reference_key
, UINT32 key_size
, IDWriteFontFile
**font_file
)
2400 struct dwrite_fontfile
*This
;
2402 This
= heap_alloc(sizeof(struct dwrite_fontfile
));
2403 if (!This
) return E_OUTOFMEMORY
;
2405 This
->IDWriteFontFile_iface
.lpVtbl
= &dwritefontfilevtbl
;
2407 IDWriteFontFileLoader_AddRef(loader
);
2408 This
->loader
= loader
;
2409 This
->stream
= NULL
;
2410 This
->reference_key
= heap_alloc(key_size
);
2411 memcpy(This
->reference_key
, reference_key
, key_size
);
2412 This
->key_size
= key_size
;
2414 *font_file
= &This
->IDWriteFontFile_iface
;
2419 static HRESULT
get_stream_from_file(IDWriteFontFile
*file
, IDWriteFontFileStream
**stream
)
2421 IDWriteFontFileLoader
*loader
;
2427 hr
= IDWriteFontFile_GetLoader(file
, &loader
);
2431 hr
= IDWriteFontFile_GetReferenceKey(file
, &key
, &key_size
);
2433 IDWriteFontFileLoader_Release(loader
);
2437 hr
= IDWriteFontFileLoader_CreateStreamFromKey(loader
, key
, key_size
, stream
);
2438 IDWriteFontFileLoader_Release(loader
);
2443 HRESULT
create_fontface(DWRITE_FONT_FACE_TYPE facetype
, UINT32 files_number
, IDWriteFontFile
* const* font_files
, UINT32 index
,
2444 DWRITE_FONT_SIMULATIONS simulations
, IDWriteFontFace2
**ret
)
2446 struct dwrite_fontface
*fontface
;
2452 fontface
= heap_alloc(sizeof(struct dwrite_fontface
));
2454 return E_OUTOFMEMORY
;
2456 fontface
->files
= heap_alloc_zero(sizeof(*fontface
->files
) * files_number
);
2457 fontface
->streams
= heap_alloc_zero(sizeof(*fontface
->streams
) * files_number
);
2459 if (!fontface
->files
|| !fontface
->streams
) {
2460 heap_free(fontface
->files
);
2461 heap_free(fontface
->streams
);
2462 heap_free(fontface
);
2463 return E_OUTOFMEMORY
;
2466 fontface
->IDWriteFontFace2_iface
.lpVtbl
= &dwritefontfacevtbl
;
2468 fontface
->type
= facetype
;
2469 fontface
->file_count
= files_number
;
2470 memset(&fontface
->cmap
, 0, sizeof(fontface
->cmap
));
2471 memset(&fontface
->vdmx
, 0, sizeof(fontface
->vdmx
));
2472 memset(&fontface
->gasp
, 0, sizeof(fontface
->gasp
));
2473 fontface
->cmap
.exists
= TRUE
;
2474 fontface
->vdmx
.exists
= TRUE
;
2475 fontface
->gasp
.exists
= TRUE
;
2476 fontface
->index
= index
;
2477 fontface
->simulations
= simulations
;
2478 memset(fontface
->glyphs
, 0, sizeof(fontface
->glyphs
));
2480 for (i
= 0; i
< fontface
->file_count
; i
++) {
2481 hr
= get_stream_from_file(font_files
[i
], &fontface
->streams
[i
]);
2483 IDWriteFontFace2_Release(&fontface
->IDWriteFontFace2_iface
);
2487 fontface
->files
[i
] = font_files
[i
];
2488 IDWriteFontFile_AddRef(font_files
[i
]);
2491 opentype_get_font_metrics(fontface
->streams
[0], facetype
, index
, &fontface
->metrics
, &fontface
->caret
);
2492 if (simulations
& DWRITE_FONT_SIMULATIONS_OBLIQUE
) {
2493 /* TODO: test what happens if caret is already slanted */
2494 if (fontface
->caret
.slopeRise
== 1) {
2495 fontface
->caret
.slopeRise
= fontface
->metrics
.designUnitsPerEm
;
2496 fontface
->caret
.slopeRun
= fontface
->caret
.slopeRise
/ 3;
2500 *ret
= &fontface
->IDWriteFontFace2_iface
;
2504 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
2511 struct local_cached_stream
2514 IDWriteFontFileStream
*stream
;
2515 struct local_refkey
*key
;
2519 struct dwrite_localfontfilestream
2521 IDWriteFontFileStream IDWriteFontFileStream_iface
;
2524 struct local_cached_stream
*entry
;
2525 const void *file_ptr
;
2529 struct dwrite_localfontfileloader
{
2530 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface
;
2533 struct list streams
;
2536 static inline struct dwrite_localfontfileloader
*impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader
*iface
)
2538 return CONTAINING_RECORD(iface
, struct dwrite_localfontfileloader
, IDWriteLocalFontFileLoader_iface
);
2541 static inline struct dwrite_localfontfilestream
*impl_from_IDWriteFontFileStream(IDWriteFontFileStream
*iface
)
2543 return CONTAINING_RECORD(iface
, struct dwrite_localfontfilestream
, IDWriteFontFileStream_iface
);
2546 static HRESULT WINAPI
localfontfilestream_QueryInterface(IDWriteFontFileStream
*iface
, REFIID riid
, void **obj
)
2548 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2549 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2550 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileStream
))
2553 IDWriteFontFileStream_AddRef(iface
);
2558 return E_NOINTERFACE
;
2561 static ULONG WINAPI
localfontfilestream_AddRef(IDWriteFontFileStream
*iface
)
2563 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2564 ULONG ref
= InterlockedIncrement(&This
->ref
);
2565 TRACE("(%p)->(%d)\n", This
, ref
);
2569 static inline void release_cached_stream(struct local_cached_stream
*stream
)
2571 list_remove(&stream
->entry
);
2572 heap_free(stream
->key
);
2576 static ULONG WINAPI
localfontfilestream_Release(IDWriteFontFileStream
*iface
)
2578 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2579 ULONG ref
= InterlockedDecrement(&This
->ref
);
2581 TRACE("(%p)->(%d)\n", This
, ref
);
2584 UnmapViewOfFile(This
->file_ptr
);
2585 release_cached_stream(This
->entry
);
2592 static HRESULT WINAPI
localfontfilestream_ReadFileFragment(IDWriteFontFileStream
*iface
, void const **fragment_start
, UINT64 offset
, UINT64 fragment_size
, void **fragment_context
)
2594 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2596 TRACE("(%p)->(%p, %s, %s, %p)\n",This
, fragment_start
,
2597 wine_dbgstr_longlong(offset
), wine_dbgstr_longlong(fragment_size
), fragment_context
);
2599 *fragment_context
= NULL
;
2601 if ((offset
>= This
->size
- 1) || (fragment_size
> This
->size
- offset
)) {
2602 *fragment_start
= NULL
;
2606 *fragment_start
= (char*)This
->file_ptr
+ offset
;
2610 static void WINAPI
localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream
*iface
, void *fragment_context
)
2612 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2613 TRACE("(%p)->(%p)\n", This
, fragment_context
);
2616 static HRESULT WINAPI
localfontfilestream_GetFileSize(IDWriteFontFileStream
*iface
, UINT64
*size
)
2618 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2619 TRACE("(%p)->(%p)\n", This
, size
);
2624 static HRESULT WINAPI
localfontfilestream_GetLastWriteTime(IDWriteFontFileStream
*iface
, UINT64
*last_writetime
)
2626 struct dwrite_localfontfilestream
*This
= impl_from_IDWriteFontFileStream(iface
);
2629 TRACE("(%p)->(%p)\n", This
, last_writetime
);
2631 li
.u
.LowPart
= This
->entry
->key
->writetime
.dwLowDateTime
;
2632 li
.u
.HighPart
= This
->entry
->key
->writetime
.dwHighDateTime
;
2633 *last_writetime
= li
.QuadPart
;
2638 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl
=
2640 localfontfilestream_QueryInterface
,
2641 localfontfilestream_AddRef
,
2642 localfontfilestream_Release
,
2643 localfontfilestream_ReadFileFragment
,
2644 localfontfilestream_ReleaseFileFragment
,
2645 localfontfilestream_GetFileSize
,
2646 localfontfilestream_GetLastWriteTime
2649 static HRESULT
create_localfontfilestream(const void *file_ptr
, UINT64 size
, struct local_cached_stream
*entry
, IDWriteFontFileStream
** iface
)
2651 struct dwrite_localfontfilestream
*This
= heap_alloc(sizeof(struct dwrite_localfontfilestream
));
2653 return E_OUTOFMEMORY
;
2655 This
->IDWriteFontFileStream_iface
.lpVtbl
= &localfontfilestreamvtbl
;
2658 This
->file_ptr
= file_ptr
;
2660 This
->entry
= entry
;
2662 *iface
= &This
->IDWriteFontFileStream_iface
;
2666 static HRESULT WINAPI
localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader
*iface
, REFIID riid
, void **obj
)
2668 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2670 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
2672 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDWriteFontFileLoader
) || IsEqualIID(riid
, &IID_IDWriteLocalFontFileLoader
))
2675 IDWriteLocalFontFileLoader_AddRef(iface
);
2680 return E_NOINTERFACE
;
2683 static ULONG WINAPI
localfontfileloader_AddRef(IDWriteLocalFontFileLoader
*iface
)
2685 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2686 ULONG ref
= InterlockedIncrement(&This
->ref
);
2687 TRACE("(%p)->(%d)\n", This
, ref
);
2691 static ULONG WINAPI
localfontfileloader_Release(IDWriteLocalFontFileLoader
*iface
)
2693 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2694 ULONG ref
= InterlockedDecrement(&This
->ref
);
2696 TRACE("(%p)->(%d)\n", This
, ref
);
2699 struct local_cached_stream
*stream
, *stream2
;
2701 /* This will detach all entries from cache. Entries are released together with streams,
2702 so stream controls its lifetime. */
2703 LIST_FOR_EACH_ENTRY_SAFE(stream
, stream2
, &This
->streams
, struct local_cached_stream
, entry
)
2704 list_init(&stream
->entry
);
2712 static HRESULT WINAPI
localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader
*iface
, const void *key
, UINT32 key_size
, IDWriteFontFileStream
**ret
)
2714 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2715 const struct local_refkey
*refkey
= key
;
2716 struct local_cached_stream
*stream
;
2717 IDWriteFontFileStream
*filestream
;
2718 HANDLE file
, mapping
;
2723 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, ret
);
2724 TRACE("name: %s\n", debugstr_w(refkey
->name
));
2726 /* search cache first */
2727 LIST_FOR_EACH_ENTRY(stream
, &This
->streams
, struct local_cached_stream
, entry
) {
2728 if (key_size
== stream
->key_size
&& !memcmp(stream
->key
, key
, key_size
)) {
2729 *ret
= stream
->stream
;
2730 IDWriteFontFileStream_AddRef(*ret
);
2737 file
= CreateFileW(refkey
->name
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2738 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2739 if (file
== INVALID_HANDLE_VALUE
)
2742 GetFileSizeEx(file
, &size
);
2743 mapping
= CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
2748 file_ptr
= MapViewOfFile(mapping
, FILE_MAP_READ
, 0, 0, 0);
2749 CloseHandle(mapping
);
2751 stream
= heap_alloc(sizeof(*stream
));
2753 UnmapViewOfFile(file_ptr
);
2754 return E_OUTOFMEMORY
;
2757 stream
->key
= heap_alloc(key_size
);
2759 UnmapViewOfFile(file_ptr
);
2761 return E_OUTOFMEMORY
;
2764 stream
->key_size
= key_size
;
2765 memcpy(stream
->key
, key
, key_size
);
2767 hr
= create_localfontfilestream(file_ptr
, size
.QuadPart
, stream
, &filestream
);
2769 UnmapViewOfFile(file_ptr
);
2770 heap_free(stream
->key
);
2775 stream
->stream
= filestream
;
2776 list_add_head(&This
->streams
, &stream
->entry
);
2778 *ret
= stream
->stream
;
2783 static HRESULT WINAPI
localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, UINT32
*length
)
2785 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2786 const struct local_refkey
*refkey
= key
;
2788 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, length
);
2790 *length
= strlenW(refkey
->name
);
2794 static HRESULT WINAPI
localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, WCHAR
*path
, UINT32 length
)
2796 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2797 const struct local_refkey
*refkey
= key
;
2799 TRACE("(%p)->(%p, %i, %p, %i)\n", This
, key
, key_size
, path
, length
);
2801 if (length
< strlenW(refkey
->name
))
2802 return E_INVALIDARG
;
2804 strcpyW(path
, refkey
->name
);
2808 static HRESULT WINAPI
localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader
*iface
, void const *key
, UINT32 key_size
, FILETIME
*writetime
)
2810 struct dwrite_localfontfileloader
*This
= impl_from_IDWriteLocalFontFileLoader(iface
);
2811 const struct local_refkey
*refkey
= key
;
2813 TRACE("(%p)->(%p, %i, %p)\n", This
, key
, key_size
, writetime
);
2815 *writetime
= refkey
->writetime
;
2819 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl
= {
2820 localfontfileloader_QueryInterface
,
2821 localfontfileloader_AddRef
,
2822 localfontfileloader_Release
,
2823 localfontfileloader_CreateStreamFromKey
,
2824 localfontfileloader_GetFilePathLengthFromKey
,
2825 localfontfileloader_GetFilePathFromKey
,
2826 localfontfileloader_GetLastWriteTimeFromKey
2829 HRESULT
create_localfontfileloader(IDWriteLocalFontFileLoader
** iface
)
2831 struct dwrite_localfontfileloader
*This
= heap_alloc(sizeof(struct dwrite_localfontfileloader
));
2833 return E_OUTOFMEMORY
;
2835 This
->IDWriteLocalFontFileLoader_iface
.lpVtbl
= &localfontfileloadervtbl
;
2837 list_init(&This
->streams
);
2839 *iface
= &This
->IDWriteLocalFontFileLoader_iface
;
2843 HRESULT
get_local_refkey(const WCHAR
*path
, const FILETIME
*writetime
, void **key
, UINT32
*size
)
2845 struct local_refkey
*refkey
;
2847 *size
= FIELD_OFFSET(struct local_refkey
, name
) + (strlenW(path
)+1)*sizeof(WCHAR
);
2850 refkey
= heap_alloc(*size
);
2852 return E_OUTOFMEMORY
;
2855 refkey
->writetime
= *writetime
;
2857 WIN32_FILE_ATTRIBUTE_DATA info
;
2859 if (GetFileAttributesExW(path
, GetFileExInfoStandard
, &info
))
2860 refkey
->writetime
= info
.ftLastWriteTime
;
2862 memset(&refkey
->writetime
, 0, sizeof(refkey
->writetime
));
2864 strcpyW(refkey
->name
, path
);
2871 /* IDWriteGlyphRunAnalysis */
2872 static HRESULT WINAPI
glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis
*iface
, REFIID riid
, void **ppv
)
2874 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2876 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppv
);
2878 if (IsEqualIID(riid
, &IID_IDWriteGlyphRunAnalysis
) ||
2879 IsEqualIID(riid
, &IID_IUnknown
))
2882 IDWriteGlyphRunAnalysis_AddRef(iface
);
2887 return E_NOINTERFACE
;
2890 static ULONG WINAPI
glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis
*iface
)
2892 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2893 ULONG ref
= InterlockedIncrement(&This
->ref
);
2894 TRACE("(%p)->(%u)\n", This
, ref
);
2898 static ULONG WINAPI
glyphrunanalysis_Release(IDWriteGlyphRunAnalysis
*iface
)
2900 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2901 ULONG ref
= InterlockedDecrement(&This
->ref
);
2903 TRACE("(%p)->(%u)\n", This
, ref
);
2906 IDWriteFontFace_Release(This
->run
.fontFace
);
2907 heap_free(This
->glyphs
);
2908 heap_free(This
->advances
);
2909 heap_free(This
->offsets
);
2916 static void glyphrunanalysis_get_texturebounds(struct dwrite_glyphrunanalysis
*analysis
, RECT
*bounds
)
2918 IDWriteFontFace2
*fontface2
;
2919 BOOL nohint
, is_rtl
;
2924 if (analysis
->ready
& RUNANALYSIS_BOUNDS
) {
2925 *bounds
= analysis
->bounds
;
2929 if (analysis
->run
.isSideways
)
2930 FIXME("sideways runs are not supported.\n");
2932 hr
= IDWriteFontFace_QueryInterface(analysis
->run
.fontFace
, &IID_IDWriteFontFace2
, (void**)&fontface2
);
2934 WARN("failed to get IDWriteFontFace2, 0x%08x\n", hr
);
2936 nohint
= analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL
|| analysis
->rendering_mode
== DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
;
2938 /* Start with empty bounds at (0,0) origin, returned bounds are not translated back to (0,0), e.g. for
2939 RTL run negative left bound is returned, same goes for vertical direction - top bound will be negative
2940 for any non-zero glyph ascender */
2942 is_rtl
= analysis
->run
.bidiLevel
& 1;
2943 for (i
= 0; i
< analysis
->run
.glyphCount
; i
++) {
2944 const DWRITE_GLYPH_OFFSET
*offset
= &analysis
->offsets
[i
];
2945 FLOAT advance
= analysis
->advances
[i
];
2948 freetype_get_glyph_bbox(fontface2
, analysis
->run
.fontEmSize
* analysis
->ppdip
, analysis
->run
.glyphIndices
[i
], nohint
, &bbox
);
2951 OffsetRect(&bbox
, origin_x
- offset
->advanceOffset
- advance
, -offset
->ascenderOffset
);
2953 OffsetRect(&bbox
, origin_x
+ offset
->advanceOffset
, offset
->ascenderOffset
);
2955 UnionRect(&analysis
->bounds
, &analysis
->bounds
, &bbox
);
2956 origin_x
+= is_rtl
? -advance
: advance
;
2959 IDWriteFontFace2_Release(fontface2
);
2961 /* translate to given run origin */
2962 OffsetRect(&analysis
->bounds
, analysis
->originX
, analysis
->originY
);
2964 analysis
->ready
|= RUNANALYSIS_BOUNDS
;
2965 *bounds
= analysis
->bounds
;
2968 static HRESULT WINAPI
glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
, RECT
*bounds
)
2970 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2972 TRACE("(%p)->(%d %p)\n", This
, type
, bounds
);
2974 if ((UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
) {
2975 memset(bounds
, 0, sizeof(*bounds
));
2976 return E_INVALIDARG
;
2979 if ((type
== DWRITE_TEXTURE_ALIASED_1x1
&& This
->rendering_mode
!= DWRITE_RENDERING_MODE_ALIASED
) ||
2980 (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
&& This
->rendering_mode
== DWRITE_RENDERING_MODE_ALIASED
)) {
2981 memset(bounds
, 0, sizeof(*bounds
));
2985 glyphrunanalysis_get_texturebounds(This
, bounds
);
2989 static HRESULT WINAPI
glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis
*iface
, DWRITE_TEXTURE_TYPE type
,
2990 RECT
const *bounds
, BYTE
*bitmap
, UINT32 size
)
2992 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
2996 FIXME("(%p)->(%d %s %p %u): stub\n", This
, type
, wine_dbgstr_rect(bounds
), bitmap
, size
);
2998 if (!bounds
|| !bitmap
|| (UINT32
)type
> DWRITE_TEXTURE_CLEARTYPE_3x1
)
2999 return E_INVALIDARG
;
3001 /* make sure buffer is large enough for requested texture type */
3002 required
= (bounds
->right
- bounds
->left
) * (bounds
->bottom
- bounds
->top
);
3003 if (type
== DWRITE_TEXTURE_CLEARTYPE_3x1
)
3006 if (size
< required
)
3007 return E_NOT_SUFFICIENT_BUFFER
;
3009 /* validate requested texture type with rendering mode */
3010 switch (This
->rendering_mode
)
3012 case DWRITE_RENDERING_MODE_ALIASED
:
3013 if (type
!= DWRITE_TEXTURE_ALIASED_1x1
)
3014 return DWRITE_E_UNSUPPORTEDOPERATION
;
3016 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
3017 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
3018 case DWRITE_RENDERING_MODE_NATURAL
:
3019 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
3020 if (type
!= DWRITE_TEXTURE_CLEARTYPE_3x1
)
3021 return DWRITE_E_UNSUPPORTEDOPERATION
;
3027 glyphrunanalysis_get_texturebounds(This
, &runbounds
);
3029 /* special case when there's nothing to return */
3030 if (!IntersectRect(&runbounds
, &runbounds
, bounds
)) {
3031 memset(bitmap
, 0, size
);
3038 static HRESULT WINAPI
glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis
*iface
, IDWriteRenderingParams
*params
,
3039 FLOAT
*gamma
, FLOAT
*contrast
, FLOAT
*cleartypelevel
)
3041 struct dwrite_glyphrunanalysis
*This
= impl_from_IDWriteGlyphRunAnalysis(iface
);
3043 TRACE("(%p)->(%p %p %p %p)\n", This
, params
, gamma
, contrast
, cleartypelevel
);
3046 return E_INVALIDARG
;
3048 switch (This
->rendering_mode
)
3050 case DWRITE_RENDERING_MODE_GDI_CLASSIC
:
3051 case DWRITE_RENDERING_MODE_GDI_NATURAL
:
3054 SystemParametersInfoW(SPI_GETFONTSMOOTHINGCONTRAST
, 0, &value
, 0);
3055 *gamma
= (FLOAT
)value
/ 1000.0f
;
3057 *cleartypelevel
= 1.0f
;
3060 case DWRITE_RENDERING_MODE_ALIASED
:
3061 case DWRITE_RENDERING_MODE_NATURAL
:
3062 case DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
:
3063 *gamma
= IDWriteRenderingParams_GetGamma(params
);
3064 *contrast
= IDWriteRenderingParams_GetEnhancedContrast(params
);
3065 *cleartypelevel
= IDWriteRenderingParams_GetClearTypeLevel(params
);
3074 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl
= {
3075 glyphrunanalysis_QueryInterface
,
3076 glyphrunanalysis_AddRef
,
3077 glyphrunanalysis_Release
,
3078 glyphrunanalysis_GetAlphaTextureBounds
,
3079 glyphrunanalysis_CreateAlphaTexture
,
3080 glyphrunanalysis_GetAlphaBlendParams
3083 HRESULT
create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode
, DWRITE_GLYPH_RUN
const *run
, FLOAT ppdip
,
3084 FLOAT originX
, FLOAT originY
, IDWriteGlyphRunAnalysis
**ret
)
3086 struct dwrite_glyphrunanalysis
*analysis
;
3090 /* check for valid rendering mode */
3091 if ((UINT32
)rendering_mode
>= DWRITE_RENDERING_MODE_OUTLINE
|| rendering_mode
== DWRITE_RENDERING_MODE_DEFAULT
)
3092 return E_INVALIDARG
;
3094 analysis
= heap_alloc(sizeof(*analysis
));
3096 return E_OUTOFMEMORY
;
3098 analysis
->IDWriteGlyphRunAnalysis_iface
.lpVtbl
= &glyphrunanalysisvtbl
;
3100 analysis
->rendering_mode
= rendering_mode
;
3101 analysis
->ready
= 0;
3102 analysis
->ppdip
= ppdip
;
3103 analysis
->originX
= originX
;
3104 analysis
->originY
= originY
;
3105 SetRectEmpty(&analysis
->bounds
);
3106 analysis
->run
= *run
;
3107 IDWriteFontFace_AddRef(analysis
->run
.fontFace
);
3108 analysis
->glyphs
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphIndices
));
3109 analysis
->advances
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphAdvances
));
3110 analysis
->offsets
= heap_alloc(run
->glyphCount
*sizeof(*run
->glyphOffsets
));
3111 if (!analysis
->glyphs
|| !analysis
->advances
|| !analysis
->offsets
) {
3112 heap_free(analysis
->glyphs
);
3113 heap_free(analysis
->advances
);
3114 heap_free(analysis
->offsets
);
3116 analysis
->glyphs
= NULL
;
3117 analysis
->advances
= NULL
;
3118 analysis
->offsets
= NULL
;
3120 IDWriteGlyphRunAnalysis_Release(&analysis
->IDWriteGlyphRunAnalysis_iface
);
3121 return E_OUTOFMEMORY
;
3124 analysis
->run
.glyphIndices
= analysis
->glyphs
;
3125 analysis
->run
.glyphAdvances
= analysis
->advances
;
3126 analysis
->run
.glyphOffsets
= analysis
->offsets
;
3128 memcpy(analysis
->glyphs
, run
->glyphIndices
, run
->glyphCount
*sizeof(*run
->glyphIndices
));
3129 memcpy(analysis
->advances
, run
->glyphAdvances
, run
->glyphCount
*sizeof(*run
->glyphAdvances
));
3130 memcpy(analysis
->offsets
, run
->glyphOffsets
, run
->glyphCount
*sizeof(*run
->glyphOffsets
));
3132 *ret
= &analysis
->IDWriteGlyphRunAnalysis_iface
;