msvcirt: Add implementation of streambuf::sputbackc.
[wine.git] / dlls / dwrite / font.c
blob209186786071b3ecd73075c9865fb354edbfac61
1 /*
2 * Font and collections
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
22 #define COBJMACROS
24 #include "wine/list.h"
25 #include "dwrite_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
29 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
30 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
31 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
32 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
34 static const IID IID_issystemcollection = {0x14d88047,0x331f,0x4cd3,{0xbc,0xa8,0x3e,0x67,0x99,0xaf,0x34,0x75}};
36 struct dwrite_font_data {
37 LONG ref;
39 DWRITE_FONT_STYLE style;
40 DWRITE_FONT_STRETCH stretch;
41 DWRITE_FONT_WEIGHT weight;
42 DWRITE_FONT_METRICS1 metrics;
43 IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1];
45 /* data needed to create fontface instance */
46 IDWriteFactory2 *factory;
47 DWRITE_FONT_FACE_TYPE face_type;
48 IDWriteFontFile *file;
49 UINT32 face_index;
51 WCHAR *facename;
54 struct dwrite_fontfamily_data {
55 LONG ref;
57 IDWriteLocalizedStrings *familyname;
59 struct dwrite_font_data **fonts;
60 UINT32 font_count;
61 UINT32 font_alloc;
64 struct dwrite_fontcollection {
65 IDWriteFontCollection IDWriteFontCollection_iface;
66 LONG ref;
68 struct dwrite_fontfamily_data **family_data;
69 UINT32 family_count;
70 UINT32 family_alloc;
71 BOOL is_system;
74 struct dwrite_fontfamily {
75 IDWriteFontFamily IDWriteFontFamily_iface;
76 LONG ref;
78 struct dwrite_fontfamily_data *data;
80 IDWriteFontCollection* collection;
83 struct dwrite_font {
84 IDWriteFont2 IDWriteFont2_iface;
85 LONG ref;
87 IDWriteFontFamily *family;
89 USHORT simulations;
90 DWRITE_FONT_STYLE style;
91 struct dwrite_font_data *data;
94 struct dwrite_fonttable {
95 void *data;
96 void *context;
97 UINT32 size;
100 struct dwrite_glyphrunanalysis {
101 IDWriteGlyphRunAnalysis IDWriteGlyphRunAnalysis_iface;
102 LONG ref;
105 #define GLYPH_BLOCK_SHIFT 8
106 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
107 #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
108 #define GLYPH_MAX 65536
110 struct dwrite_fontface {
111 IDWriteFontFace2 IDWriteFontFace2_iface;
112 LONG ref;
114 IDWriteFontFileStream **streams;
115 IDWriteFontFile **files;
116 UINT32 file_count;
117 UINT32 index;
119 USHORT simulations;
120 DWRITE_FONT_FACE_TYPE type;
121 DWRITE_FONT_METRICS1 metrics;
122 DWRITE_CARET_METRICS caret;
124 struct dwrite_fonttable cmap;
125 DWRITE_GLYPH_METRICS *glyphs[GLYPH_MAX/GLYPH_BLOCK_SIZE];
128 struct dwrite_fontfile {
129 IDWriteFontFile IDWriteFontFile_iface;
130 LONG ref;
132 IDWriteFontFileLoader *loader;
133 void *reference_key;
134 UINT32 key_size;
135 IDWriteFontFileStream *stream;
138 static inline struct dwrite_fontface *impl_from_IDWriteFontFace2(IDWriteFontFace2 *iface)
140 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace2_iface);
143 static inline struct dwrite_font *impl_from_IDWriteFont2(IDWriteFont2 *iface)
145 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont2_iface);
148 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
150 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
153 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
155 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
158 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
160 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
163 static inline struct dwrite_glyphrunanalysis *impl_from_IDWriteGlyphRunAnalysis(IDWriteGlyphRunAnalysis *iface)
165 return CONTAINING_RECORD(iface, struct dwrite_glyphrunanalysis, IDWriteGlyphRunAnalysis_iface);
168 static HRESULT get_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
170 static const DWRITE_GLYPH_METRICS nil;
171 DWRITE_GLYPH_METRICS *block = fontface->glyphs[glyph >> GLYPH_BLOCK_SHIFT];
173 if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil, sizeof(DWRITE_GLYPH_METRICS))) return S_FALSE;
174 memcpy(metrics, &block[glyph & GLYPH_BLOCK_MASK], sizeof(*metrics));
175 return S_OK;
178 static HRESULT set_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
180 DWRITE_GLYPH_METRICS **block = &fontface->glyphs[glyph >> GLYPH_BLOCK_SHIFT];
182 if (!*block) {
183 /* start new block */
184 *block = heap_alloc_zero(sizeof(*metrics) * GLYPH_BLOCK_SIZE);
185 if (!*block)
186 return E_OUTOFMEMORY;
189 memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], metrics, sizeof(*metrics));
190 return S_OK;
193 static inline void* get_fontface_cmap(struct dwrite_fontface *fontface)
195 BOOL exists = FALSE;
196 HRESULT hr;
198 if (fontface->cmap.data)
199 return fontface->cmap.data;
201 hr = IDWriteFontFace2_TryGetFontTable(&fontface->IDWriteFontFace2_iface, MS_CMAP_TAG, (const void**)&fontface->cmap.data,
202 &fontface->cmap.size, &fontface->cmap.context, &exists);
203 if (FAILED(hr) || !exists) {
204 ERR("Font does not have a CMAP table\n");
205 return NULL;
208 return fontface->cmap.data;
211 static void release_font_data(struct dwrite_font_data *data)
213 int i;
215 if (InterlockedDecrement(&data->ref) > 0)
216 return;
218 for (i = DWRITE_INFORMATIONAL_STRING_NONE; i < sizeof(data->info_strings)/sizeof(data->info_strings[0]); i++) {
219 if (data->info_strings[i])
220 IDWriteLocalizedStrings_Release(data->info_strings[i]);
223 IDWriteFontFile_Release(data->file);
224 IDWriteFactory2_Release(data->factory);
225 heap_free(data->facename);
226 heap_free(data);
229 static void release_fontfamily_data(struct dwrite_fontfamily_data *data)
231 int i;
233 if (InterlockedDecrement(&data->ref) > 0)
234 return;
236 for (i = 0; i < data->font_count; i++)
237 release_font_data(data->fonts[i]);
238 heap_free(data->fonts);
239 IDWriteLocalizedStrings_Release(data->familyname);
240 heap_free(data);
243 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace2 *iface, REFIID riid, void **obj)
245 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
247 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
249 if (IsEqualIID(riid, &IID_IDWriteFontFace2) ||
250 IsEqualIID(riid, &IID_IDWriteFontFace1) ||
251 IsEqualIID(riid, &IID_IDWriteFontFace) ||
252 IsEqualIID(riid, &IID_IUnknown))
254 *obj = iface;
255 IDWriteFontFace2_AddRef(iface);
256 return S_OK;
259 *obj = NULL;
260 return E_NOINTERFACE;
263 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace2 *iface)
265 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
266 ULONG ref = InterlockedIncrement(&This->ref);
267 TRACE("(%p)->(%d)\n", This, ref);
268 return ref;
271 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace2 *iface)
273 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
274 ULONG ref = InterlockedDecrement(&This->ref);
276 TRACE("(%p)->(%d)\n", This, ref);
278 if (!ref) {
279 UINT32 i;
281 if (This->cmap.context)
282 IDWriteFontFace2_ReleaseFontTable(iface, This->cmap.context);
283 for (i = 0; i < This->file_count; i++) {
284 if (This->streams[i])
285 IDWriteFontFileStream_Release(This->streams[i]);
286 if (This->files[i])
287 IDWriteFontFile_Release(This->files[i]);
290 for (i = 0; i < sizeof(This->glyphs)/sizeof(This->glyphs[0]); i++)
291 heap_free(This->glyphs[i]);
293 freetype_notify_cacheremove(iface);
294 heap_free(This);
297 return ref;
300 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace2 *iface)
302 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
303 TRACE("(%p)\n", This);
304 return This->type;
307 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace2 *iface, UINT32 *number_of_files,
308 IDWriteFontFile **fontfiles)
310 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
311 int i;
313 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
314 if (fontfiles == NULL)
316 *number_of_files = This->file_count;
317 return S_OK;
319 if (*number_of_files < This->file_count)
320 return E_INVALIDARG;
322 for (i = 0; i < This->file_count; i++)
324 IDWriteFontFile_AddRef(This->files[i]);
325 fontfiles[i] = This->files[i];
328 return S_OK;
331 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace2 *iface)
333 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
334 TRACE("(%p)\n", This);
335 return This->index;
338 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace2 *iface)
340 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
341 TRACE("(%p)\n", This);
342 return This->simulations;
345 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace2 *iface)
347 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
348 FIXME("(%p): stub\n", This);
349 return FALSE;
352 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS *metrics)
354 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
355 TRACE("(%p)->(%p)\n", This, metrics);
356 memcpy(metrics, &This->metrics, sizeof(*metrics));
359 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace2 *iface)
361 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
362 TRACE("(%p)\n", This);
363 return freetype_get_glyphcount(iface);
366 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2 *iface,
367 UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways)
369 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
370 HRESULT hr;
371 UINT32 i;
373 TRACE("(%p)->(%p %u %p %d)\n", This, glyphs, glyph_count, ret, is_sideways);
375 if (!glyphs)
376 return E_INVALIDARG;
378 if (is_sideways)
379 FIXME("sideways metrics are not supported.\n");
381 for (i = 0; i < glyph_count; i++) {
382 DWRITE_GLYPH_METRICS metrics;
384 hr = get_cached_glyph_metrics(This, glyphs[i], &metrics);
385 if (hr != S_OK) {
386 freetype_get_design_glyph_metrics(iface, This->metrics.designUnitsPerEm, glyphs[i], &metrics);
387 hr = set_cached_glyph_metrics(This, glyphs[i], &metrics);
388 if (FAILED(hr))
389 return hr;
391 ret[i] = metrics;
394 return S_OK;
397 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UINT32 const *codepoints,
398 UINT32 count, UINT16 *glyph_indices)
400 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
401 UINT32 i;
403 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
405 if (!glyph_indices)
406 return E_INVALIDARG;
408 if (!codepoints) {
409 memset(glyph_indices, 0, count*sizeof(UINT16));
410 return E_INVALIDARG;
413 for (i = 0; i < count; i++)
414 glyph_indices[i] = freetype_get_glyphindex(iface, codepoints[i]);
416 return S_OK;
419 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace2 *iface, UINT32 table_tag,
420 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
422 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
424 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
426 return opentype_get_font_table(This->streams[0], This->type, This->index, table_tag, table_data, context, table_size, exists);
429 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace2 *iface, void *table_context)
431 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
433 TRACE("(%p)->(%p)\n", This, table_context);
435 IDWriteFontFileStream_ReleaseFileFragment(This->streams[0], table_context);
438 HRESULT new_glyph_outline(UINT32 count, struct glyph_outline **ret)
440 struct glyph_outline *outline;
441 D2D1_POINT_2F *points;
442 UINT8 *tags;
444 *ret = NULL;
446 outline = heap_alloc(sizeof(*outline));
447 if (!outline)
448 return E_OUTOFMEMORY;
450 points = heap_alloc(count*sizeof(D2D1_POINT_2F));
451 tags = heap_alloc_zero(count*sizeof(UINT8));
452 if (!points || !tags) {
453 heap_free(points);
454 heap_free(tags);
455 heap_free(outline);
456 return E_OUTOFMEMORY;
459 outline->points = points;
460 outline->tags = tags;
461 outline->count = count;
462 outline->advance = 0.0;
464 *ret = outline;
465 return S_OK;
468 static void free_glyph_outline(struct glyph_outline *outline)
470 heap_free(outline->points);
471 heap_free(outline->tags);
472 heap_free(outline);
475 static void report_glyph_outline(const struct glyph_outline *outline, IDWriteGeometrySink *sink)
477 UINT16 p;
479 for (p = 0; p < outline->count; p++) {
480 if (outline->tags[p] & OUTLINE_POINT_START) {
481 ID2D1SimplifiedGeometrySink_BeginFigure(sink, outline->points[p], D2D1_FIGURE_BEGIN_FILLED);
482 continue;
485 if (outline->tags[p] & OUTLINE_POINT_LINE)
486 ID2D1SimplifiedGeometrySink_AddLines(sink, outline->points+p, 1);
487 else if (outline->tags[p] & OUTLINE_POINT_BEZIER) {
488 static const UINT16 segment_length = 3;
489 ID2D1SimplifiedGeometrySink_AddBeziers(sink, (D2D1_BEZIER_SEGMENT*)&outline->points[p], 1);
490 p += segment_length - 1;
493 if (outline->tags[p] & OUTLINE_POINT_END)
494 ID2D1SimplifiedGeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
498 static inline void translate_glyph_outline(struct glyph_outline *outline, FLOAT xoffset, FLOAT yoffset)
500 UINT16 p;
502 for (p = 0; p < outline->count; p++) {
503 outline->points[p].x += xoffset;
504 outline->points[p].y += yoffset;
508 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace2 *iface, FLOAT emSize,
509 UINT16 const *glyphs, FLOAT const* advances, DWRITE_GLYPH_OFFSET const *offsets,
510 UINT32 count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *sink)
512 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
513 FLOAT advance = 0.0;
514 HRESULT hr;
515 UINT32 g;
517 TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This, emSize, glyphs, advances, offsets,
518 count, is_sideways, is_rtl, sink);
520 if (!glyphs || !sink)
521 return E_INVALIDARG;
523 if (is_sideways)
524 FIXME("sideways mode is not supported.\n");
526 if (count)
527 ID2D1SimplifiedGeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
529 for (g = 0; g < count; g++) {
530 FLOAT xoffset = 0.0, yoffset = 0.0;
531 struct glyph_outline *outline;
533 /* FIXME: cache outlines */
535 hr = freetype_get_glyph_outline(iface, emSize, glyphs[g], This->simulations, &outline);
536 if (FAILED(hr))
537 return hr;
539 /* glyph offsets act as current glyph adjustment */
540 if (offsets) {
541 xoffset += is_rtl ? -offsets[g].advanceOffset : offsets[g].advanceOffset;
542 yoffset -= offsets[g].ascenderOffset;
545 if (g == 0)
546 advance = is_rtl ? -outline->advance : 0.0;
548 xoffset += advance;
549 translate_glyph_outline(outline, xoffset, yoffset);
551 /* update advance to next glyph */
552 if (advances)
553 advance += is_rtl ? -advances[g] : advances[g];
554 else
555 advance += is_rtl ? -outline->advance : outline->advance;
557 report_glyph_outline(outline, sink);
558 free_glyph_outline(outline);
561 return S_OK;
564 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
565 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
567 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
568 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
569 return E_NOTIMPL;
572 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
573 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
575 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
576 DWRITE_FONT_METRICS1 metrics1;
577 HRESULT hr;
579 TRACE("(%p)->(%.2f %.2f %p %p)\n", This, emSize, pixels_per_dip, transform, metrics);
581 hr = IDWriteFontFace2_GetGdiCompatibleMetrics(iface, emSize, pixels_per_dip, transform, &metrics1);
582 if (FAILED(hr))
583 return hr;
585 memcpy(metrics, &metrics1, sizeof(*metrics));
586 return hr;
589 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
590 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
591 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
593 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
594 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
595 glyph_count, metrics, is_sideways);
596 return E_NOTIMPL;
599 static void WINAPI dwritefontface1_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS1 *metrics)
601 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
602 TRACE("(%p)->(%p)\n", This, metrics);
603 *metrics = This->metrics;
606 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT em_size, FLOAT pixels_per_dip,
607 const DWRITE_MATRIX *transform, DWRITE_FONT_METRICS1 *metrics)
609 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
610 FIXME("(%p)->(%f %f %p %p): stub\n", This, em_size, pixels_per_dip, transform, metrics);
611 return E_NOTIMPL;
614 static void WINAPI dwritefontface1_GetCaretMetrics(IDWriteFontFace2 *iface, DWRITE_CARET_METRICS *metrics)
616 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
617 TRACE("(%p)->(%p)\n", This, metrics);
618 *metrics = This->caret;
621 static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace2 *iface, UINT32 max_count,
622 DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
624 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
626 TRACE("(%p)->(%u %p %p)\n", This, max_count, ranges, count);
628 *count = 0;
629 if (max_count && !ranges)
630 return E_INVALIDARG;
632 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This), max_count, ranges, count);
635 static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace2 *iface)
637 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
638 TRACE("(%p)\n", This);
639 return freetype_is_monospaced(iface);
642 static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2 *iface,
643 UINT32 glyph_count, UINT16 const *glyphs, INT32 *advances, BOOL is_sideways)
645 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
646 UINT32 i;
648 TRACE("(%p)->(%u %p %p %d)\n", This, glyph_count, glyphs, advances, is_sideways);
650 for (i = 0; i < glyph_count; i++) {
651 DWRITE_GLYPH_METRICS metrics = { 0 };
652 HRESULT hr;
654 hr = IDWriteFontFace2_GetDesignGlyphMetrics(iface, glyphs + i, 1, &metrics, is_sideways);
655 if (FAILED(hr))
656 return hr;
658 advances[i] = is_sideways ? metrics.advanceHeight : metrics.advanceWidth;
661 return S_OK;
664 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2 *iface,
665 FLOAT em_size, FLOAT pixels_per_dip, const DWRITE_MATRIX *transform, BOOL use_gdi_natural,
666 BOOL is_sideways, UINT32 glyph_count, UINT16 const *indices, INT32 *advances)
668 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
669 FIXME("(%p)->(%f %f %p %d %d %u %p %p): stub\n", This, em_size, pixels_per_dip, transform,
670 use_gdi_natural, is_sideways, glyph_count, indices, advances);
671 return E_NOTIMPL;
674 static HRESULT WINAPI dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2 *iface, UINT32 count,
675 const UINT16 *indices, INT32 *adjustments)
677 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
678 UINT32 i;
680 TRACE("(%p)->(%u %p %p)\n", This, count, indices, adjustments);
682 if (!(indices || adjustments) || !count)
683 return E_INVALIDARG;
685 if (!indices || count == 1) {
686 memset(adjustments, 0, count*sizeof(INT32));
687 return E_INVALIDARG;
690 for (i = 0; i < count-1; i++)
691 adjustments[i] = freetype_get_kerning_pair_adjustment(iface, indices[i], indices[i+1]);
692 adjustments[count-1] = 0;
694 return S_OK;
697 static BOOL WINAPI dwritefontface1_HasKerningPairs(IDWriteFontFace2 *iface)
699 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
700 TRACE("(%p)\n", This);
701 return freetype_has_kerning_pairs(iface);
704 static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2 *iface,
705 FLOAT font_emsize, FLOAT dpiX, FLOAT dpiY, const DWRITE_MATRIX *transform, BOOL is_sideways,
706 DWRITE_OUTLINE_THRESHOLD threshold, DWRITE_MEASURING_MODE measuring_mode, DWRITE_RENDERING_MODE *rendering_mode)
708 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
709 DWRITE_GRID_FIT_MODE gridfitmode;
710 TRACE("(%p)->(%.2f %.2f %.2f %p %d %d %d %p)\n", This, font_emsize, dpiX, dpiY, transform, is_sideways,
711 threshold, measuring_mode, rendering_mode);
712 return IDWriteFontFace2_GetRecommendedRenderingMode(iface, font_emsize, dpiX, dpiY, transform, is_sideways,
713 threshold, measuring_mode, NULL, rendering_mode, &gridfitmode);
716 static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2 *iface, UINT32 glyph_count,
717 const UINT16 *nominal_indices, UINT16 *vertical_indices)
719 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
720 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, nominal_indices, vertical_indices);
721 return E_NOTIMPL;
724 static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2 *iface)
726 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
727 FIXME("(%p): stub\n", This);
728 return FALSE;
731 static BOOL WINAPI dwritefontface2_IsColorFont(IDWriteFontFace2 *iface)
733 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
734 FIXME("(%p): stub\n", This);
735 return FALSE;
738 static UINT32 WINAPI dwritefontface2_GetColorPaletteCount(IDWriteFontFace2 *iface)
740 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
741 FIXME("(%p): stub\n", This);
742 return 0;
745 static UINT32 WINAPI dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2 *iface)
747 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
748 FIXME("(%p): stub\n", This);
749 return 0;
752 static HRESULT WINAPI dwritefontface2_GetPaletteEntries(IDWriteFontFace2 *iface, UINT32 palette_index,
753 UINT32 first_entry_index, UINT32 entry_count, DWRITE_COLOR_F *entries)
755 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
756 FIXME("(%p)->(%u %u %u %p): stub\n", This, palette_index, first_entry_index, entry_count, entries);
757 return E_NOTIMPL;
760 static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT fontEmSize,
761 FLOAT dpiX, FLOAT dpiY, DWRITE_MATRIX const *transform, BOOL is_sideways, DWRITE_OUTLINE_THRESHOLD threshold,
762 DWRITE_MEASURING_MODE measuringmode, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *renderingmode,
763 DWRITE_GRID_FIT_MODE *gridfitmode)
765 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
766 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This, fontEmSize, dpiX, dpiY, transform, is_sideways, threshold,
767 measuringmode, params, renderingmode, gridfitmode);
768 return E_NOTIMPL;
771 static const IDWriteFontFace2Vtbl dwritefontfacevtbl = {
772 dwritefontface_QueryInterface,
773 dwritefontface_AddRef,
774 dwritefontface_Release,
775 dwritefontface_GetType,
776 dwritefontface_GetFiles,
777 dwritefontface_GetIndex,
778 dwritefontface_GetSimulations,
779 dwritefontface_IsSymbolFont,
780 dwritefontface_GetMetrics,
781 dwritefontface_GetGlyphCount,
782 dwritefontface_GetDesignGlyphMetrics,
783 dwritefontface_GetGlyphIndices,
784 dwritefontface_TryGetFontTable,
785 dwritefontface_ReleaseFontTable,
786 dwritefontface_GetGlyphRunOutline,
787 dwritefontface_GetRecommendedRenderingMode,
788 dwritefontface_GetGdiCompatibleMetrics,
789 dwritefontface_GetGdiCompatibleGlyphMetrics,
790 dwritefontface1_GetMetrics,
791 dwritefontface1_GetGdiCompatibleMetrics,
792 dwritefontface1_GetCaretMetrics,
793 dwritefontface1_GetUnicodeRanges,
794 dwritefontface1_IsMonospacedFont,
795 dwritefontface1_GetDesignGlyphAdvances,
796 dwritefontface1_GetGdiCompatibleGlyphAdvances,
797 dwritefontface1_GetKerningPairAdjustments,
798 dwritefontface1_HasKerningPairs,
799 dwritefontface1_GetRecommendedRenderingMode,
800 dwritefontface1_GetVerticalGlyphVariants,
801 dwritefontface1_HasVerticalGlyphVariants,
802 dwritefontface2_IsColorFont,
803 dwritefontface2_GetColorPaletteCount,
804 dwritefontface2_GetPaletteEntryCount,
805 dwritefontface2_GetPaletteEntries,
806 dwritefontface2_GetRecommendedRenderingMode
809 HRESULT get_family_names_from_stream(IDWriteFontFileStream *stream, UINT32 index, DWRITE_FONT_FACE_TYPE facetype,
810 IDWriteLocalizedStrings **names)
812 const void *name_table = NULL;
813 void *name_context;
814 HRESULT hr = E_FAIL;
816 opentype_get_font_table(stream, facetype, index, MS_NAME_TAG, &name_table, &name_context, NULL, NULL);
817 if (name_table) {
818 hr = opentype_get_font_strings_from_id(name_table, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, names);
819 IDWriteFontFileStream_ReleaseFileFragment(stream, name_context);
821 else
822 *names = NULL;
824 return hr;
827 static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace2 **fontface)
829 struct dwrite_font_data *data = font->data;
830 IDWriteFontFace *face;
831 HRESULT hr;
833 *fontface = NULL;
835 hr = IDWriteFactory2_CreateFontFace(data->factory, data->face_type, 1, &data->file,
836 data->face_index, font->simulations, &face);
837 if (FAILED(hr))
838 return hr;
840 hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace2, (void**)fontface);
841 IDWriteFontFace_Release(face);
843 return hr;
846 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont2 *iface, REFIID riid, void **obj)
848 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
850 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
852 if (IsEqualIID(riid, &IID_IDWriteFont2) ||
853 IsEqualIID(riid, &IID_IDWriteFont1) ||
854 IsEqualIID(riid, &IID_IDWriteFont) ||
855 IsEqualIID(riid, &IID_IUnknown))
857 *obj = iface;
858 IDWriteFont2_AddRef(iface);
859 return S_OK;
862 *obj = NULL;
863 return E_NOINTERFACE;
866 static ULONG WINAPI dwritefont_AddRef(IDWriteFont2 *iface)
868 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
869 ULONG ref = InterlockedIncrement(&This->ref);
870 TRACE("(%p)->(%d)\n", This, ref);
871 return ref;
874 static ULONG WINAPI dwritefont_Release(IDWriteFont2 *iface)
876 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
877 ULONG ref = InterlockedDecrement(&This->ref);
879 TRACE("(%p)->(%d)\n", This, ref);
881 if (!ref) {
882 IDWriteFontFamily_Release(This->family);
883 release_font_data(This->data);
884 heap_free(This);
887 return ref;
890 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont2 *iface, IDWriteFontFamily **family)
892 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
893 TRACE("(%p)->(%p)\n", This, family);
895 *family = This->family;
896 IDWriteFontFamily_AddRef(*family);
897 return S_OK;
900 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont2 *iface)
902 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
903 TRACE("(%p)\n", This);
904 return This->data->weight;
907 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont2 *iface)
909 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
910 TRACE("(%p)\n", This);
911 return This->data->stretch;
914 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont2 *iface)
916 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
917 TRACE("(%p)\n", This);
918 return This->style;
921 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont2 *iface)
923 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
924 IDWriteFontFace2 *fontface;
925 HRESULT hr;
927 TRACE("(%p)\n", This);
929 hr = get_fontface_from_font(This, &fontface);
930 if (FAILED(hr))
931 return hr;
933 return IDWriteFontFace2_IsSymbolFont(fontface);
936 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont2 *iface, IDWriteLocalizedStrings **names)
938 static const WCHAR boldobliqueW[] = {'B','o','l','d',' ','O','b','l','i','q','u','e',0};
939 static const WCHAR obliqueW[] = {'O','b','l','i','q','u','e',0};
940 static const WCHAR boldW[] = {'B','o','l','d',0};
941 static const WCHAR enusW[] = {'e','n','-','u','s',0};
943 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
944 IDWriteLocalizedStrings *strings;
945 const WCHAR *name;
946 HRESULT hr;
948 TRACE("(%p)->(%p)\n", This, names);
950 *names = NULL;
952 if (This->simulations == DWRITE_FONT_SIMULATIONS_NONE) {
953 BOOL exists;
954 return IDWriteFont2_GetInformationalStrings(iface, DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES,
955 names, &exists);
958 switch (This->simulations) {
959 case DWRITE_FONT_SIMULATIONS_BOLD|DWRITE_FONT_SIMULATIONS_OBLIQUE:
960 name = boldobliqueW;
961 break;
962 case DWRITE_FONT_SIMULATIONS_BOLD:
963 name = boldW;
964 break;
965 case DWRITE_FONT_SIMULATIONS_OBLIQUE:
966 name = obliqueW;
967 break;
968 default:
969 ERR("unknown simulations %d\n", This->simulations);
970 return E_FAIL;
973 hr = create_localizedstrings(&strings);
974 if (FAILED(hr)) return hr;
976 hr = add_localizedstring(strings, enusW, name);
977 if (FAILED(hr)) {
978 IDWriteLocalizedStrings_Release(strings);
979 return hr;
982 *names = strings;
984 return S_OK;
987 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont2 *iface,
988 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
990 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
991 struct dwrite_font_data *data = This->data;
992 HRESULT hr;
994 TRACE("(%p)->(%d %p %p)\n", This, stringid, strings, exists);
996 *exists = FALSE;
997 *strings = NULL;
999 if (stringid > DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME || stringid == DWRITE_INFORMATIONAL_STRING_NONE)
1000 return S_OK;
1002 if (!data->info_strings[stringid]) {
1003 IDWriteFontFace2 *fontface;
1004 const void *table_data;
1005 BOOL table_exists;
1006 void *context;
1007 UINT32 size;
1009 hr = get_fontface_from_font(This, &fontface);
1010 if (FAILED(hr))
1011 return hr;
1013 table_exists = FALSE;
1014 hr = IDWriteFontFace2_TryGetFontTable(fontface, MS_NAME_TAG, &table_data, &size, &context, &table_exists);
1015 if (FAILED(hr) || !table_exists)
1016 WARN("no NAME table found.\n");
1018 if (table_exists) {
1019 hr = opentype_get_font_strings_from_id(table_data, stringid, &data->info_strings[stringid]);
1020 if (FAILED(hr) || !data->info_strings[stringid])
1021 return hr;
1022 IDWriteFontFace2_ReleaseFontTable(fontface, context);
1026 hr = clone_localizedstring(data->info_strings[stringid], strings);
1027 if (FAILED(hr))
1028 return hr;
1030 *exists = TRUE;
1031 return S_OK;
1034 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont2 *iface)
1036 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1037 TRACE("(%p)\n", This);
1038 return This->simulations;
1041 static void WINAPI dwritefont_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS *metrics)
1043 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1045 TRACE("(%p)->(%p)\n", This, metrics);
1046 memcpy(metrics, &This->data->metrics, sizeof(*metrics));
1049 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont2 *iface, UINT32 value, BOOL *exists)
1051 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1052 IDWriteFontFace2 *fontface;
1053 UINT16 index;
1054 HRESULT hr;
1056 TRACE("(%p)->(0x%08x %p)\n", This, value, exists);
1058 *exists = FALSE;
1060 hr = get_fontface_from_font(This, &fontface);
1061 if (FAILED(hr))
1062 return hr;
1064 index = 0;
1065 hr = IDWriteFontFace2_GetGlyphIndices(fontface, &value, 1, &index);
1066 if (FAILED(hr))
1067 return hr;
1069 *exists = index != 0;
1070 return S_OK;
1073 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont2 *iface, IDWriteFontFace **face)
1075 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1076 HRESULT hr;
1078 TRACE("(%p)->(%p)\n", This, face);
1080 hr = get_fontface_from_font(This, (IDWriteFontFace2**)face);
1081 if (hr == S_OK)
1082 IDWriteFontFace_AddRef(*face);
1084 return hr;
1087 static void WINAPI dwritefont1_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS1 *metrics)
1089 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1090 TRACE("(%p)->(%p)\n", This, metrics);
1091 *metrics = This->data->metrics;
1094 static void WINAPI dwritefont1_GetPanose(IDWriteFont2 *iface, DWRITE_PANOSE *panose)
1096 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1097 FIXME("(%p)->(%p): stub\n", This, panose);
1100 static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont2 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
1102 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1103 IDWriteFontFace2 *fontface;
1104 HRESULT hr;
1106 TRACE("(%p)->(%u %p %p)\n", This, max_count, ranges, count);
1108 hr = get_fontface_from_font(This, &fontface);
1109 if (FAILED(hr))
1110 return hr;
1112 return IDWriteFontFace2_GetUnicodeRanges(fontface, max_count, ranges, count);
1115 static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont2 *iface)
1117 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1118 IDWriteFontFace2 *fontface;
1119 HRESULT hr;
1121 TRACE("(%p)\n", This);
1123 hr = get_fontface_from_font(This, &fontface);
1124 if (FAILED(hr))
1125 return hr;
1127 return IDWriteFontFace2_IsMonospacedFont(fontface);
1130 static HRESULT WINAPI dwritefont2_IsColorFont(IDWriteFont2 *iface)
1132 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1133 IDWriteFontFace2 *fontface;
1134 HRESULT hr;
1136 TRACE("(%p)\n", This);
1138 hr = get_fontface_from_font(This, &fontface);
1139 if (FAILED(hr))
1140 return hr;
1142 return IDWriteFontFace2_IsColorFont(fontface);
1145 static const IDWriteFont2Vtbl dwritefontvtbl = {
1146 dwritefont_QueryInterface,
1147 dwritefont_AddRef,
1148 dwritefont_Release,
1149 dwritefont_GetFontFamily,
1150 dwritefont_GetWeight,
1151 dwritefont_GetStretch,
1152 dwritefont_GetStyle,
1153 dwritefont_IsSymbolFont,
1154 dwritefont_GetFaceNames,
1155 dwritefont_GetInformationalStrings,
1156 dwritefont_GetSimulations,
1157 dwritefont_GetMetrics,
1158 dwritefont_HasCharacter,
1159 dwritefont_CreateFontFace,
1160 dwritefont1_GetMetrics,
1161 dwritefont1_GetPanose,
1162 dwritefont1_GetUnicodeRanges,
1163 dwritefont1_IsMonospacedFont,
1164 dwritefont2_IsColorFont
1167 static HRESULT create_font(struct dwrite_font_data *data, IDWriteFontFamily *family, DWRITE_FONT_SIMULATIONS simulations,
1168 IDWriteFont **font)
1170 struct dwrite_font *This;
1171 *font = NULL;
1173 This = heap_alloc(sizeof(struct dwrite_font));
1174 if (!This) return E_OUTOFMEMORY;
1176 This->IDWriteFont2_iface.lpVtbl = &dwritefontvtbl;
1177 This->ref = 1;
1178 This->family = family;
1179 IDWriteFontFamily_AddRef(family);
1180 This->simulations = simulations;
1181 This->style = data->style;
1182 This->data = data;
1183 InterlockedIncrement(&This->data->ref);
1185 /* set oblique style from requested simulation */
1186 if ((simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) && data->style == DWRITE_FONT_STYLE_NORMAL)
1187 This->style = DWRITE_FONT_STYLE_OBLIQUE;
1189 *font = (IDWriteFont*)&This->IDWriteFont2_iface;
1191 return S_OK;
1194 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
1196 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1197 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1199 if (IsEqualIID(riid, &IID_IUnknown) ||
1200 IsEqualIID(riid, &IID_IDWriteFontList) ||
1201 IsEqualIID(riid, &IID_IDWriteFontFamily))
1203 *obj = iface;
1204 IDWriteFontFamily_AddRef(iface);
1205 return S_OK;
1208 *obj = NULL;
1209 return E_NOINTERFACE;
1212 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
1214 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1215 ULONG ref = InterlockedIncrement(&This->ref);
1216 TRACE("(%p)->(%d)\n", This, ref);
1217 return ref;
1220 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
1222 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1223 ULONG ref = InterlockedDecrement(&This->ref);
1225 TRACE("(%p)->(%d)\n", This, ref);
1227 if (!ref)
1229 IDWriteFontCollection_Release(This->collection);
1230 release_fontfamily_data(This->data);
1231 heap_free(This);
1234 return ref;
1237 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
1239 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1240 TRACE("(%p)->(%p)\n", This, collection);
1242 *collection = This->collection;
1243 IDWriteFontCollection_AddRef(This->collection);
1244 return S_OK;
1247 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
1249 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1250 TRACE("(%p)\n", This);
1251 return This->data->font_count;
1254 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
1256 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1258 TRACE("(%p)->(%u %p)\n", This, index, font);
1260 *font = NULL;
1262 if (This->data->font_count == 0)
1263 return S_FALSE;
1265 if (index >= This->data->font_count)
1266 return E_INVALIDARG;
1268 return create_font(This->data->fonts[index], iface, DWRITE_FONT_SIMULATIONS_NONE, font);
1271 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
1273 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1274 return clone_localizedstring(This->data->familyname, names);
1277 static inline BOOL is_matching_font_style(DWRITE_FONT_STYLE style, DWRITE_FONT_STYLE font_style)
1279 if (style == font_style)
1280 return TRUE;
1282 if (((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE)) && font_style == DWRITE_FONT_STYLE_NORMAL)
1283 return TRUE;
1285 return FALSE;
1288 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1289 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
1291 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1292 UINT32 min_weight_diff = ~0u;
1293 int found = -1, i;
1295 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
1297 for (i = 0; i < This->data->font_count; i++) {
1298 if (is_matching_font_style(style, This->data->fonts[i]->style) && stretch == This->data->fonts[i]->stretch) {
1299 DWRITE_FONT_WEIGHT font_weight = This->data->fonts[i]->weight;
1300 UINT32 weight_diff = abs(font_weight - weight);
1301 if (weight_diff < min_weight_diff) {
1302 min_weight_diff = weight_diff;
1303 found = i;
1308 if (found != -1) {
1309 DWRITE_FONT_SIMULATIONS simulations = DWRITE_FONT_SIMULATIONS_NONE;
1311 if (((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE)) &&
1312 This->data->fonts[found]->style == DWRITE_FONT_STYLE_NORMAL) {
1313 simulations = DWRITE_FONT_SIMULATIONS_OBLIQUE;
1315 return create_font(This->data->fonts[found], iface, simulations, font);
1317 else {
1318 *font = NULL;
1319 return DWRITE_E_NOFONT;
1323 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1324 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
1326 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1327 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
1328 return E_NOTIMPL;
1331 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
1332 dwritefontfamily_QueryInterface,
1333 dwritefontfamily_AddRef,
1334 dwritefontfamily_Release,
1335 dwritefontfamily_GetFontCollection,
1336 dwritefontfamily_GetFontCount,
1337 dwritefontfamily_GetFont,
1338 dwritefontfamily_GetFamilyNames,
1339 dwritefontfamily_GetFirstMatchingFont,
1340 dwritefontfamily_GetMatchingFonts
1343 static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family)
1345 struct dwrite_fontfamily *This;
1347 *family = NULL;
1349 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1350 if (!This) return E_OUTOFMEMORY;
1352 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1353 This->ref = 1;
1354 This->collection = collection;
1355 IDWriteFontCollection_AddRef(collection);
1356 This->data = data;
1357 InterlockedIncrement(&This->data->ref);
1359 *family = &This->IDWriteFontFamily_iface;
1361 return S_OK;
1364 BOOL is_system_collection(IDWriteFontCollection *collection)
1366 void *obj;
1367 return IDWriteFontCollection_QueryInterface(collection, &IID_issystemcollection, (void**)&obj) == S_OK;
1370 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
1372 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1373 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1375 if (IsEqualIID(riid, &IID_IUnknown) ||
1376 IsEqualIID(riid, &IID_IDWriteFontCollection))
1378 *obj = iface;
1379 IDWriteFontCollection_AddRef(iface);
1380 return S_OK;
1383 *obj = NULL;
1385 if (This->is_system && IsEqualIID(riid, &IID_issystemcollection))
1386 return S_OK;
1388 return E_NOINTERFACE;
1391 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
1393 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1394 ULONG ref = InterlockedIncrement(&This->ref);
1395 TRACE("(%p)->(%d)\n", This, ref);
1396 return ref;
1399 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
1401 unsigned int i;
1402 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1403 ULONG ref = InterlockedDecrement(&This->ref);
1404 TRACE("(%p)->(%d)\n", This, ref);
1406 if (!ref) {
1407 for (i = 0; i < This->family_count; i++)
1408 release_fontfamily_data(This->family_data[i]);
1409 heap_free(This->family_data);
1410 heap_free(This);
1413 return ref;
1416 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
1418 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1419 TRACE("(%p)\n", This);
1420 return This->family_count;
1423 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
1425 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1427 TRACE("(%p)->(%u %p)\n", This, index, family);
1429 if (index >= This->family_count) {
1430 *family = NULL;
1431 return E_FAIL;
1434 return create_fontfamily(This->family_data[index], iface, family);
1437 static UINT32 collection_find_family(struct dwrite_fontcollection *collection, const WCHAR *name)
1439 UINT32 i;
1441 for (i = 0; i < collection->family_count; i++) {
1442 IDWriteLocalizedStrings *family_name = collection->family_data[i]->familyname;
1443 UINT32 j, count = IDWriteLocalizedStrings_GetCount(family_name);
1444 HRESULT hr;
1446 for (j = 0; j < count; j++) {
1447 WCHAR buffer[255];
1448 hr = IDWriteLocalizedStrings_GetString(family_name, j, buffer, 255);
1449 if (SUCCEEDED(hr) && !strcmpiW(buffer, name))
1450 return i;
1454 return ~0u;
1457 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
1459 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1460 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
1461 *index = collection_find_family(This, name);
1462 *exists = *index != ~0u;
1463 return S_OK;
1466 static BOOL is_same_fontfile(IDWriteFontFile *left, IDWriteFontFile *right)
1468 UINT32 left_key_size, right_key_size;
1469 const void *left_key, *right_key;
1470 HRESULT hr;
1472 if (left == right)
1473 return TRUE;
1475 hr = IDWriteFontFile_GetReferenceKey(left, &left_key, &left_key_size);
1476 if (FAILED(hr))
1477 return FALSE;
1479 hr = IDWriteFontFile_GetReferenceKey(right, &right_key, &right_key_size);
1480 if (FAILED(hr))
1481 return FALSE;
1483 if (left_key_size != right_key_size)
1484 return FALSE;
1486 return !memcmp(left_key, right_key, left_key_size);
1489 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
1491 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1492 struct dwrite_fontfamily_data *found_family = NULL;
1493 struct dwrite_font_data *found_font = NULL;
1494 DWRITE_FONT_SIMULATIONS simulations;
1495 IDWriteFontFamily *family;
1496 UINT32 i, j, face_index;
1497 IDWriteFontFile *file;
1498 HRESULT hr;
1500 TRACE("(%p)->(%p %p)\n", This, face, font);
1502 *font = NULL;
1504 if (!face)
1505 return E_INVALIDARG;
1507 i = 1;
1508 hr = IDWriteFontFace_GetFiles(face, &i, &file);
1509 if (FAILED(hr))
1510 return hr;
1511 face_index = IDWriteFontFace_GetIndex(face);
1513 for (i = 0; i < This->family_count; i++) {
1514 struct dwrite_fontfamily_data *family_data = This->family_data[i];
1515 for (j = 0; j < family_data->font_count; j++) {
1516 struct dwrite_font_data *font_data = family_data->fonts[j];
1518 if (face_index == font_data->face_index && is_same_fontfile(file, font_data->file)) {
1519 found_font = font_data;
1520 found_family = family_data;
1521 break;
1526 if (!found_font)
1527 return DWRITE_E_NOFONT;
1529 hr = create_fontfamily(found_family, iface, &family);
1530 if (FAILED(hr))
1531 return hr;
1533 simulations = IDWriteFontFace_GetSimulations(face);
1534 hr = create_font(found_font, family, simulations, font);
1535 IDWriteFontFamily_Release(family);
1536 return hr;
1539 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
1540 dwritefontcollection_QueryInterface,
1541 dwritefontcollection_AddRef,
1542 dwritefontcollection_Release,
1543 dwritefontcollection_GetFontFamilyCount,
1544 dwritefontcollection_GetFontFamily,
1545 dwritefontcollection_FindFamilyName,
1546 dwritefontcollection_GetFontFromFontFace
1549 static HRESULT fontfamily_add_font(struct dwrite_fontfamily_data *family_data, struct dwrite_font_data *font_data)
1551 if (family_data->font_count + 1 >= family_data->font_alloc) {
1552 struct dwrite_font_data **new_list;
1553 UINT32 new_alloc;
1555 new_alloc = family_data->font_alloc * 2;
1556 new_list = heap_realloc(family_data->fonts, sizeof(*family_data->fonts) * new_alloc);
1557 if (!new_list)
1558 return E_OUTOFMEMORY;
1559 family_data->fonts = new_list;
1560 family_data->font_alloc = new_alloc;
1563 family_data->fonts[family_data->font_count] = font_data;
1564 family_data->font_count++;
1565 return S_OK;
1568 static HRESULT fontcollection_add_family(struct dwrite_fontcollection *collection, struct dwrite_fontfamily_data *family)
1570 if (collection->family_alloc < collection->family_count + 1) {
1571 struct dwrite_fontfamily_data **new_list;
1572 UINT32 new_alloc;
1574 new_alloc = collection->family_alloc * 2;
1575 new_list = heap_realloc(collection->family_data, sizeof(*new_list) * new_alloc);
1576 if (!new_list)
1577 return E_OUTOFMEMORY;
1579 collection->family_alloc = new_alloc;
1580 collection->family_data = new_list;
1583 collection->family_data[collection->family_count] = family;
1584 collection->family_count++;
1586 return S_OK;
1589 static HRESULT init_font_collection(struct dwrite_fontcollection *collection, BOOL is_system)
1591 collection->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1592 collection->ref = 1;
1593 collection->family_count = 0;
1594 collection->family_alloc = 2;
1595 collection->is_system = is_system;
1597 collection->family_data = heap_alloc(sizeof(*collection->family_data)*2);
1598 if (!collection->family_data)
1599 return E_OUTOFMEMORY;
1601 return S_OK;
1604 HRESULT get_filestream_from_file(IDWriteFontFile *file, IDWriteFontFileStream **stream)
1606 IDWriteFontFileLoader *loader;
1607 const void *key;
1608 UINT32 key_size;
1609 HRESULT hr;
1611 *stream = NULL;
1613 hr = IDWriteFontFile_GetReferenceKey(file, &key, &key_size);
1614 if (FAILED(hr))
1615 return hr;
1617 hr = IDWriteFontFile_GetLoader(file, &loader);
1618 if (FAILED(hr))
1619 return hr;
1621 hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, key, key_size, stream);
1622 IDWriteFontFileLoader_Release(loader);
1623 if (FAILED(hr))
1624 return hr;
1626 return hr;
1629 static HRESULT init_font_data(IDWriteFactory2 *factory, IDWriteFontFile *file, UINT32 face_index, DWRITE_FONT_FACE_TYPE face_type,
1630 IDWriteFontFileStream **stream, struct dwrite_font_data **ret)
1632 void *os2_context, *head_context;
1633 const void *tt_os2 = NULL, *tt_head = NULL;
1634 struct dwrite_font_data *data;
1635 HRESULT hr;
1637 data = heap_alloc_zero(sizeof(*data));
1638 if (!data)
1639 return E_OUTOFMEMORY;
1641 hr = get_filestream_from_file(file, stream);
1642 if (FAILED(hr)) {
1643 heap_free(data);
1644 return hr;
1647 data->ref = 1;
1648 data->factory = factory;
1649 data->file = file;
1650 data->face_index = face_index;
1651 data->face_type = face_type;
1652 IDWriteFontFile_AddRef(file);
1653 IDWriteFactory2_AddRef(factory);
1655 opentype_get_font_table(*stream, face_type, face_index, MS_OS2_TAG, &tt_os2, &os2_context, NULL, NULL);
1656 opentype_get_font_table(*stream, face_type, face_index, MS_HEAD_TAG, &tt_head, &head_context, NULL, NULL);
1658 opentype_get_font_properties(*stream, face_type, face_index, &data->stretch, &data->weight, &data->style);
1659 opentype_get_font_metrics(*stream, face_type, face_index, &data->metrics, NULL);
1661 if (tt_os2)
1662 IDWriteFontFileStream_ReleaseFileFragment(*stream, os2_context);
1663 if (tt_head)
1664 IDWriteFontFileStream_ReleaseFileFragment(*stream, head_context);
1666 *ret = data;
1667 return S_OK;
1670 static HRESULT init_fontfamily_data(IDWriteLocalizedStrings *familyname, struct dwrite_fontfamily_data **ret)
1672 struct dwrite_fontfamily_data *data;
1674 data = heap_alloc(sizeof(*data));
1675 if (!data)
1676 return E_OUTOFMEMORY;
1678 data->ref = 1;
1679 data->font_count = 0;
1680 data->font_alloc = 2;
1682 data->fonts = heap_alloc(sizeof(*data->fonts)*data->font_alloc);
1683 if (!data->fonts) {
1684 heap_free(data);
1685 return E_OUTOFMEMORY;
1688 data->familyname = familyname;
1689 IDWriteLocalizedStrings_AddRef(familyname);
1691 *ret = data;
1692 return S_OK;
1695 HRESULT create_font_collection(IDWriteFactory2* factory, IDWriteFontFileEnumerator *enumerator, BOOL is_system, IDWriteFontCollection **ret)
1697 struct dwrite_fontcollection *collection;
1698 BOOL current = FALSE;
1699 HRESULT hr = S_OK;
1701 *ret = NULL;
1703 collection = heap_alloc(sizeof(struct dwrite_fontcollection));
1704 if (!collection) return E_OUTOFMEMORY;
1706 hr = init_font_collection(collection, is_system);
1707 if (FAILED(hr)) {
1708 heap_free(collection);
1709 return hr;
1712 *ret = &collection->IDWriteFontCollection_iface;
1714 TRACE("building font collection:\n");
1716 while (hr == S_OK) {
1717 DWRITE_FONT_FACE_TYPE face_type;
1718 DWRITE_FONT_FILE_TYPE file_type;
1719 IDWriteFontFile *file;
1720 UINT32 face_count;
1721 BOOL supported;
1722 int i;
1724 current = FALSE;
1725 hr = IDWriteFontFileEnumerator_MoveNext(enumerator, &current);
1726 if (FAILED(hr) || !current)
1727 break;
1729 hr = IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator, &file);
1730 if (FAILED(hr))
1731 break;
1733 /* failed font files are skipped */
1734 hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &face_count);
1735 if (FAILED(hr) || !supported || face_count == 0) {
1736 TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file, hr, supported, face_count);
1737 IDWriteFontFile_Release(file);
1738 hr = S_OK;
1739 continue;
1742 for (i = 0; i < face_count; i++) {
1743 IDWriteLocalizedStrings *family_name = NULL;
1744 struct dwrite_font_data *font_data;
1745 IDWriteFontFileStream *stream;
1746 WCHAR buffer[255];
1747 UINT32 index;
1749 /* alloc and init new font data structure */
1750 hr = init_font_data(factory, file, i, face_type, &stream, &font_data);
1751 if (FAILED(hr))
1752 break;
1754 /* get family name from font file */
1755 hr = get_family_names_from_stream(stream, i, face_type, &family_name);
1756 IDWriteFontFileStream_Release(stream);
1757 if (FAILED(hr)) {
1758 WARN("unable to get family name from font\n");
1759 release_font_data(font_data);
1760 continue;
1763 buffer[0] = 0;
1764 IDWriteLocalizedStrings_GetString(family_name, 0, buffer, sizeof(buffer)/sizeof(WCHAR));
1766 index = collection_find_family(collection, buffer);
1767 if (index != ~0u)
1768 hr = fontfamily_add_font(collection->family_data[index], font_data);
1769 else {
1770 struct dwrite_fontfamily_data *family_data;
1772 /* create and init new family */
1773 hr = init_fontfamily_data(family_name, &family_data);
1774 if (hr == S_OK) {
1775 /* add font to family, family - to collection */
1776 hr = fontfamily_add_font(family_data, font_data);
1777 if (hr == S_OK)
1778 hr = fontcollection_add_family(collection, family_data);
1780 if (FAILED(hr))
1781 release_fontfamily_data(family_data);
1785 IDWriteLocalizedStrings_Release(family_name);
1787 if (FAILED(hr))
1788 break;
1791 IDWriteFontFile_Release(file);
1794 return hr;
1797 struct system_fontfile_enumerator
1799 IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
1800 LONG ref;
1802 IDWriteFactory2 *factory;
1803 HKEY hkey;
1804 int index;
1807 static inline struct system_fontfile_enumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface)
1809 return CONTAINING_RECORD(iface, struct system_fontfile_enumerator, IDWriteFontFileEnumerator_iface);
1812 static HRESULT WINAPI systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
1814 *obj = NULL;
1816 if (IsEqualIID(riid, &IID_IDWriteFontFileEnumerator) || IsEqualIID(riid, &IID_IUnknown)) {
1817 IDWriteFontFileEnumerator_AddRef(iface);
1818 *obj = iface;
1819 return S_OK;
1822 return E_NOINTERFACE;
1825 static ULONG WINAPI systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
1827 struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
1828 return InterlockedIncrement(&enumerator->ref);
1831 static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
1833 struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
1834 ULONG ref = InterlockedDecrement(&enumerator->ref);
1836 if (!ref) {
1837 IDWriteFactory2_Release(enumerator->factory);
1838 RegCloseKey(enumerator->hkey);
1839 heap_free(enumerator);
1842 return ref;
1845 static HRESULT WINAPI systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
1847 struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
1848 DWORD ret, type, count;
1849 WCHAR *filename;
1850 HRESULT hr;
1852 *file = NULL;
1854 if (enumerator->index < 0)
1855 return E_FAIL;
1857 if (RegEnumValueW(enumerator->hkey, enumerator->index, NULL, NULL, NULL, &type, NULL, &count))
1858 return E_FAIL;
1860 if (!(filename = heap_alloc(count)))
1861 return E_OUTOFMEMORY;
1863 ret = RegEnumValueW(enumerator->hkey, enumerator->index, NULL, NULL, NULL, &type, (BYTE*)filename, &count);
1864 if (ret) {
1865 heap_free(filename);
1866 return E_FAIL;
1869 /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
1870 if (!strchrW(filename, '\\')) {
1871 static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\\',0};
1872 WCHAR fullpathW[MAX_PATH];
1874 GetWindowsDirectoryW(fullpathW, sizeof(fullpathW)/sizeof(WCHAR));
1875 strcatW(fullpathW, fontsW);
1876 strcatW(fullpathW, filename);
1878 hr = IDWriteFactory2_CreateFontFileReference(enumerator->factory, fullpathW, NULL, file);
1880 else
1881 hr = IDWriteFactory2_CreateFontFileReference(enumerator->factory, filename, NULL, file);
1883 heap_free(filename);
1884 return hr;
1887 static HRESULT WINAPI systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
1889 struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
1891 *current = FALSE;
1892 enumerator->index++;
1894 /* iterate until we find next string value */
1895 while (1) {
1896 DWORD type = 0, count;
1897 if (RegEnumValueW(enumerator->hkey, enumerator->index, NULL, NULL, NULL, &type, NULL, &count))
1898 break;
1899 if (type == REG_SZ) {
1900 *current = TRUE;
1901 break;
1903 enumerator->index++;
1906 TRACE("index = %d, current = %d\n", enumerator->index, *current);
1907 return S_OK;
1910 static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl =
1912 systemfontfileenumerator_QueryInterface,
1913 systemfontfileenumerator_AddRef,
1914 systemfontfileenumerator_Release,
1915 systemfontfileenumerator_MoveNext,
1916 systemfontfileenumerator_GetCurrentFontFile
1919 static HRESULT create_system_fontfile_enumerator(IDWriteFactory2 *factory, IDWriteFontFileEnumerator **ret)
1921 struct system_fontfile_enumerator *enumerator;
1922 static const WCHAR fontslistW[] = {
1923 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
1924 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1925 'F','o','n','t','s',0
1928 *ret = NULL;
1930 enumerator = heap_alloc(sizeof(*enumerator));
1931 if (!enumerator)
1932 return E_OUTOFMEMORY;
1934 enumerator->IDWriteFontFileEnumerator_iface.lpVtbl = &systemfontfileenumeratorvtbl;
1935 enumerator->ref = 1;
1936 enumerator->factory = factory;
1937 enumerator->index = -1;
1938 IDWriteFactory2_AddRef(factory);
1940 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, fontslistW, 0, GENERIC_READ, &enumerator->hkey)) {
1941 ERR("failed to open fonts list key\n");
1942 IDWriteFactory2_Release(factory);
1943 heap_free(enumerator);
1944 return E_FAIL;
1947 *ret = &enumerator->IDWriteFontFileEnumerator_iface;
1949 return S_OK;
1952 HRESULT get_system_fontcollection(IDWriteFactory2 *factory, IDWriteFontCollection **collection)
1954 IDWriteFontFileEnumerator *enumerator;
1955 HRESULT hr;
1957 *collection = NULL;
1959 hr = create_system_fontfile_enumerator(factory, &enumerator);
1960 if (FAILED(hr))
1961 return hr;
1963 TRACE("building system font collection for factory %p\n", factory);
1964 hr = create_font_collection(factory, enumerator, TRUE, collection);
1965 IDWriteFontFileEnumerator_Release(enumerator);
1966 return hr;
1969 static HRESULT WINAPI eudcfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
1971 *obj = NULL;
1973 if (IsEqualIID(riid, &IID_IDWriteFontFileEnumerator) || IsEqualIID(riid, &IID_IUnknown)) {
1974 IDWriteFontFileEnumerator_AddRef(iface);
1975 *obj = iface;
1976 return S_OK;
1979 return E_NOINTERFACE;
1982 static ULONG WINAPI eudcfontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
1984 return 2;
1987 static ULONG WINAPI eudcfontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
1989 return 1;
1992 static HRESULT WINAPI eudcfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
1994 *file = NULL;
1995 return E_FAIL;
1998 static HRESULT WINAPI eudcfontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
2000 *current = FALSE;
2001 return S_OK;
2004 static const struct IDWriteFontFileEnumeratorVtbl eudcfontfileenumeratorvtbl =
2006 eudcfontfileenumerator_QueryInterface,
2007 eudcfontfileenumerator_AddRef,
2008 eudcfontfileenumerator_Release,
2009 eudcfontfileenumerator_MoveNext,
2010 eudcfontfileenumerator_GetCurrentFontFile
2013 static IDWriteFontFileEnumerator eudc_fontfile_enumerator = { &eudcfontfileenumeratorvtbl };
2015 HRESULT get_eudc_fontcollection(IDWriteFactory2 *factory, IDWriteFontCollection **collection)
2017 TRACE("building EUDC font collection for factory %p\n", factory);
2018 return create_font_collection(factory, &eudc_fontfile_enumerator, FALSE, collection);
2021 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
2023 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
2025 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2027 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
2029 *obj = iface;
2030 IDWriteFontFile_AddRef(iface);
2031 return S_OK;
2034 *obj = NULL;
2035 return E_NOINTERFACE;
2038 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
2040 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
2041 ULONG ref = InterlockedIncrement(&This->ref);
2042 TRACE("(%p)->(%d)\n", This, ref);
2043 return ref;
2046 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
2048 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
2049 ULONG ref = InterlockedDecrement(&This->ref);
2051 TRACE("(%p)->(%d)\n", This, ref);
2053 if (!ref)
2055 IDWriteFontFileLoader_Release(This->loader);
2056 if (This->stream) IDWriteFontFileStream_Release(This->stream);
2057 heap_free(This->reference_key);
2058 heap_free(This);
2061 return ref;
2064 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
2066 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
2067 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
2068 *fontFileReferenceKey = This->reference_key;
2069 *fontFileReferenceKeySize = This->key_size;
2071 return S_OK;
2074 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
2076 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
2077 TRACE("(%p)->(%p)\n", This, fontFileLoader);
2078 *fontFileLoader = This->loader;
2079 IDWriteFontFileLoader_AddRef(This->loader);
2081 return S_OK;
2084 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
2086 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
2087 IDWriteFontFileStream *stream;
2088 HRESULT hr;
2090 TRACE("(%p)->(%p, %p, %p, %p)\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
2092 *isSupportedFontType = FALSE;
2093 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
2094 if (fontFaceType)
2095 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
2096 *numberOfFaces = 0;
2098 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
2099 if (FAILED(hr))
2100 return hr;
2102 hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
2104 /* TODO: Further Analysis */
2105 IDWriteFontFileStream_Release(stream);
2106 return S_OK;
2109 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
2110 dwritefontfile_QueryInterface,
2111 dwritefontfile_AddRef,
2112 dwritefontfile_Release,
2113 dwritefontfile_GetReferenceKey,
2114 dwritefontfile_GetLoader,
2115 dwritefontfile_Analyze,
2118 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
2120 struct dwrite_fontfile *This;
2122 This = heap_alloc(sizeof(struct dwrite_fontfile));
2123 if (!This) return E_OUTOFMEMORY;
2125 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
2126 This->ref = 1;
2127 IDWriteFontFileLoader_AddRef(loader);
2128 This->loader = loader;
2129 This->stream = NULL;
2130 This->reference_key = heap_alloc(key_size);
2131 memcpy(This->reference_key, reference_key, key_size);
2132 This->key_size = key_size;
2134 *font_file = &This->IDWriteFontFile_iface;
2136 return S_OK;
2139 static HRESULT get_stream_from_file(IDWriteFontFile *file, IDWriteFontFileStream **stream)
2141 IDWriteFontFileLoader *loader;
2142 UINT32 key_size;
2143 const void *key;
2144 HRESULT hr;
2146 *stream = NULL;
2147 hr = IDWriteFontFile_GetLoader(file, &loader);
2148 if (FAILED(hr))
2149 return hr;
2151 hr = IDWriteFontFile_GetReferenceKey(file, &key, &key_size);
2152 if (FAILED(hr)) {
2153 IDWriteFontFileLoader_Release(loader);
2154 return hr;
2157 hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, key, key_size, stream);
2158 IDWriteFontFileLoader_Release(loader);
2160 return hr;
2163 HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index,
2164 DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace2 **ret)
2166 struct dwrite_fontface *fontface;
2167 HRESULT hr = S_OK;
2168 int i;
2170 *ret = NULL;
2172 fontface = heap_alloc(sizeof(struct dwrite_fontface));
2173 if (!fontface)
2174 return E_OUTOFMEMORY;
2176 fontface->files = heap_alloc_zero(sizeof(*fontface->files) * files_number);
2177 fontface->streams = heap_alloc_zero(sizeof(*fontface->streams) * files_number);
2179 if (!fontface->files || !fontface->streams) {
2180 heap_free(fontface->files);
2181 heap_free(fontface->streams);
2182 heap_free(fontface);
2183 return E_OUTOFMEMORY;
2186 fontface->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
2187 fontface->ref = 1;
2188 fontface->type = facetype;
2189 fontface->file_count = files_number;
2190 fontface->cmap.data = NULL;
2191 fontface->cmap.context = NULL;
2192 fontface->cmap.size = 0;
2193 fontface->index = index;
2194 fontface->simulations = simulations;
2195 memset(fontface->glyphs, 0, sizeof(fontface->glyphs));
2197 for (i = 0; i < fontface->file_count; i++) {
2198 hr = get_stream_from_file(font_files[i], &fontface->streams[i]);
2199 if (FAILED(hr)) {
2200 IDWriteFontFace2_Release(&fontface->IDWriteFontFace2_iface);
2201 return hr;
2204 fontface->files[i] = font_files[i];
2205 IDWriteFontFile_AddRef(font_files[i]);
2208 opentype_get_font_metrics(fontface->streams[0], facetype, index, &fontface->metrics, &fontface->caret);
2209 if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE) {
2210 /* TODO: test what happens if caret is already slanted */
2211 if (fontface->caret.slopeRise == 1) {
2212 fontface->caret.slopeRise = fontface->metrics.designUnitsPerEm;
2213 fontface->caret.slopeRun = fontface->caret.slopeRise / 3;
2217 *ret = &fontface->IDWriteFontFace2_iface;
2218 return S_OK;
2221 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
2222 struct local_refkey
2224 FILETIME writetime;
2225 WCHAR name[1];
2228 struct local_cached_stream
2230 struct list entry;
2231 IDWriteFontFileStream *stream;
2232 struct local_refkey *key;
2233 UINT32 key_size;
2236 struct dwrite_localfontfilestream
2238 IDWriteFontFileStream IDWriteFontFileStream_iface;
2239 LONG ref;
2241 struct local_cached_stream *entry;
2242 const void *file_ptr;
2243 UINT64 size;
2246 struct dwrite_localfontfileloader {
2247 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
2248 LONG ref;
2250 struct list streams;
2253 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
2255 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
2258 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
2260 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
2263 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
2265 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2266 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2267 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
2269 *obj = iface;
2270 IDWriteFontFileStream_AddRef(iface);
2271 return S_OK;
2274 *obj = NULL;
2275 return E_NOINTERFACE;
2278 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
2280 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2281 ULONG ref = InterlockedIncrement(&This->ref);
2282 TRACE("(%p)->(%d)\n", This, ref);
2283 return ref;
2286 static inline void release_cached_stream(struct local_cached_stream *stream)
2288 list_remove(&stream->entry);
2289 heap_free(stream->key);
2290 heap_free(stream);
2293 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
2295 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2296 ULONG ref = InterlockedDecrement(&This->ref);
2298 TRACE("(%p)->(%d)\n", This, ref);
2300 if (!ref) {
2301 UnmapViewOfFile(This->file_ptr);
2302 release_cached_stream(This->entry);
2303 heap_free(This);
2306 return ref;
2309 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
2311 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2313 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
2314 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
2316 *fragment_context = NULL;
2318 if ((offset >= This->size - 1) || (fragment_size > This->size - offset)) {
2319 *fragment_start = NULL;
2320 return E_FAIL;
2323 *fragment_start = (char*)This->file_ptr + offset;
2324 return S_OK;
2327 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
2329 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2330 TRACE("(%p)->(%p)\n", This, fragment_context);
2333 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
2335 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2336 TRACE("(%p)->(%p)\n", This, size);
2337 *size = This->size;
2338 return S_OK;
2341 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
2343 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2344 ULARGE_INTEGER li;
2346 TRACE("(%p)->(%p)\n", This, last_writetime);
2348 li.u.LowPart = This->entry->key->writetime.dwLowDateTime;
2349 li.u.HighPart = This->entry->key->writetime.dwHighDateTime;
2350 *last_writetime = li.QuadPart;
2352 return S_OK;
2355 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
2357 localfontfilestream_QueryInterface,
2358 localfontfilestream_AddRef,
2359 localfontfilestream_Release,
2360 localfontfilestream_ReadFileFragment,
2361 localfontfilestream_ReleaseFileFragment,
2362 localfontfilestream_GetFileSize,
2363 localfontfilestream_GetLastWriteTime
2366 static HRESULT create_localfontfilestream(const void *file_ptr, UINT64 size, struct local_cached_stream *entry, IDWriteFontFileStream** iface)
2368 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
2369 if (!This)
2370 return E_OUTOFMEMORY;
2372 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
2373 This->ref = 1;
2375 This->file_ptr = file_ptr;
2376 This->size = size;
2377 This->entry = entry;
2379 *iface = &This->IDWriteFontFileStream_iface;
2380 return S_OK;
2383 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
2385 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2387 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2389 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
2391 *obj = iface;
2392 IDWriteLocalFontFileLoader_AddRef(iface);
2393 return S_OK;
2396 *obj = NULL;
2397 return E_NOINTERFACE;
2400 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
2402 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2403 ULONG ref = InterlockedIncrement(&This->ref);
2404 TRACE("(%p)->(%d)\n", This, ref);
2405 return ref;
2408 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
2410 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2411 ULONG ref = InterlockedDecrement(&This->ref);
2413 TRACE("(%p)->(%d)\n", This, ref);
2415 if (!ref) {
2416 struct local_cached_stream *stream, *stream2;
2418 /* This will detach all entries from cache. Entries are released together with streams,
2419 so stream controls its lifetime. */
2420 LIST_FOR_EACH_ENTRY_SAFE(stream, stream2, &This->streams, struct local_cached_stream, entry)
2421 list_init(&stream->entry);
2423 heap_free(This);
2426 return ref;
2429 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *key, UINT32 key_size, IDWriteFontFileStream **ret)
2431 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2432 const struct local_refkey *refkey = key;
2433 struct local_cached_stream *stream;
2434 IDWriteFontFileStream *filestream;
2435 HANDLE file, mapping;
2436 LARGE_INTEGER size;
2437 void *file_ptr;
2438 HRESULT hr;
2440 TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, ret);
2441 TRACE("name: %s\n", debugstr_w(refkey->name));
2443 /* search cache first */
2444 LIST_FOR_EACH_ENTRY(stream, &This->streams, struct local_cached_stream, entry) {
2445 if (key_size == stream->key_size && !memcmp(stream->key, key, key_size)) {
2446 *ret = stream->stream;
2447 IDWriteFontFileStream_AddRef(*ret);
2448 return S_OK;
2452 *ret = NULL;
2454 file = CreateFileW(refkey->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
2455 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2456 if (file == INVALID_HANDLE_VALUE)
2457 return E_FAIL;
2459 GetFileSizeEx(file, &size);
2460 mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
2461 CloseHandle(file);
2462 if (!mapping)
2463 return E_FAIL;
2465 file_ptr = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
2466 CloseHandle(mapping);
2468 stream = heap_alloc(sizeof(*stream));
2469 if (!stream) {
2470 UnmapViewOfFile(file_ptr);
2471 return E_OUTOFMEMORY;
2474 stream->key = heap_alloc(key_size);
2475 if (!stream->key) {
2476 UnmapViewOfFile(file_ptr);
2477 heap_free(stream);
2478 return E_OUTOFMEMORY;
2481 stream->key_size = key_size;
2482 memcpy(stream->key, key, key_size);
2484 hr = create_localfontfilestream(file_ptr, size.QuadPart, stream, &filestream);
2485 if (FAILED(hr)) {
2486 UnmapViewOfFile(file_ptr);
2487 heap_free(stream->key);
2488 heap_free(stream);
2489 return hr;
2492 stream->stream = filestream;
2493 list_add_head(&This->streams, &stream->entry);
2495 *ret = stream->stream;
2497 return S_OK;
2500 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
2502 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2503 const struct local_refkey *refkey = key;
2505 TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, length);
2507 *length = strlenW(refkey->name);
2508 return S_OK;
2511 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
2513 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2514 const struct local_refkey *refkey = key;
2516 TRACE("(%p)->(%p, %i, %p, %i)\n", This, key, key_size, path, length);
2518 if (length < strlenW(refkey->name))
2519 return E_INVALIDARG;
2521 strcpyW(path, refkey->name);
2522 return S_OK;
2525 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
2527 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2528 const struct local_refkey *refkey = key;
2530 TRACE("(%p)->(%p, %i, %p)\n", This, key, key_size, writetime);
2532 *writetime = refkey->writetime;
2533 return S_OK;
2536 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
2537 localfontfileloader_QueryInterface,
2538 localfontfileloader_AddRef,
2539 localfontfileloader_Release,
2540 localfontfileloader_CreateStreamFromKey,
2541 localfontfileloader_GetFilePathLengthFromKey,
2542 localfontfileloader_GetFilePathFromKey,
2543 localfontfileloader_GetLastWriteTimeFromKey
2546 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
2548 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
2549 if (!This)
2550 return E_OUTOFMEMORY;
2552 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
2553 This->ref = 1;
2554 list_init(&This->streams);
2556 *iface = &This->IDWriteLocalFontFileLoader_iface;
2557 return S_OK;
2560 HRESULT get_local_refkey(const WCHAR *path, const FILETIME *writetime, void **key, UINT32 *size)
2562 struct local_refkey *refkey;
2564 *size = FIELD_OFFSET(struct local_refkey, name) + (strlenW(path)+1)*sizeof(WCHAR);
2565 *key = NULL;
2567 refkey = heap_alloc(*size);
2568 if (!refkey)
2569 return E_OUTOFMEMORY;
2571 if (writetime)
2572 refkey->writetime = *writetime;
2573 else {
2574 WIN32_FILE_ATTRIBUTE_DATA info;
2576 if (GetFileAttributesExW(path, GetFileExInfoStandard, &info))
2577 refkey->writetime = info.ftLastWriteTime;
2578 else
2579 memset(&refkey->writetime, 0, sizeof(refkey->writetime));
2581 strcpyW(refkey->name, path);
2583 *key = refkey;
2585 return S_OK;
2588 /* IDWriteGlyphRunAnalysis */
2589 static HRESULT WINAPI glyphrunanalysis_QueryInterface(IDWriteGlyphRunAnalysis *iface, REFIID riid, void **ppv)
2591 struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
2593 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2595 if (IsEqualIID(riid, &IID_IDWriteGlyphRunAnalysis) ||
2596 IsEqualIID(riid, &IID_IUnknown))
2598 *ppv = iface;
2599 IDWriteGlyphRunAnalysis_AddRef(iface);
2600 return S_OK;
2603 *ppv = NULL;
2604 return E_NOINTERFACE;
2607 static ULONG WINAPI glyphrunanalysis_AddRef(IDWriteGlyphRunAnalysis *iface)
2609 struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
2610 ULONG ref = InterlockedIncrement(&This->ref);
2611 TRACE("(%p)->(%u)\n", This, ref);
2612 return ref;
2615 static ULONG WINAPI glyphrunanalysis_Release(IDWriteGlyphRunAnalysis *iface)
2617 struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
2618 ULONG ref = InterlockedDecrement(&This->ref);
2620 TRACE("(%p)->(%u)\n", This, ref);
2622 if (!ref) {
2623 heap_free(This);
2626 return ref;
2629 static HRESULT WINAPI glyphrunanalysis_GetAlphaTextureBounds(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type, RECT* bounds)
2631 struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
2632 FIXME("(%p)->(%d %p): stub\n", This, type, bounds);
2633 return E_NOTIMPL;
2636 static HRESULT WINAPI glyphrunanalysis_CreateAlphaTexture(IDWriteGlyphRunAnalysis *iface, DWRITE_TEXTURE_TYPE type,
2637 RECT const* bounds, BYTE* alphaValues, UINT32 bufferSize)
2639 struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
2640 FIXME("(%p)->(%d %p %p %u): stub\n", This, type, bounds, alphaValues, bufferSize);
2641 return E_NOTIMPL;
2644 static HRESULT WINAPI glyphrunanalysis_GetAlphaBlendParams(IDWriteGlyphRunAnalysis *iface, IDWriteRenderingParams *params,
2645 FLOAT *blendGamma, FLOAT *blendEnhancedContrast, FLOAT *blendClearTypeLevel)
2647 struct dwrite_glyphrunanalysis *This = impl_from_IDWriteGlyphRunAnalysis(iface);
2648 FIXME("(%p)->(%p %p %p %p): stub\n", This, params, blendGamma, blendEnhancedContrast, blendClearTypeLevel);
2649 return E_NOTIMPL;
2652 static const struct IDWriteGlyphRunAnalysisVtbl glyphrunanalysisvtbl = {
2653 glyphrunanalysis_QueryInterface,
2654 glyphrunanalysis_AddRef,
2655 glyphrunanalysis_Release,
2656 glyphrunanalysis_GetAlphaTextureBounds,
2657 glyphrunanalysis_CreateAlphaTexture,
2658 glyphrunanalysis_GetAlphaBlendParams
2661 HRESULT create_glyphrunanalysis(DWRITE_RENDERING_MODE rendering_mode, IDWriteGlyphRunAnalysis **ret)
2663 struct dwrite_glyphrunanalysis *analysis;
2665 *ret = NULL;
2667 /* check for valid rendering mode */
2668 if ((UINT32)rendering_mode >= DWRITE_RENDERING_MODE_OUTLINE || rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2669 return E_INVALIDARG;
2671 analysis = heap_alloc(sizeof(*analysis));
2672 if (!analysis)
2673 return E_OUTOFMEMORY;
2675 analysis->IDWriteGlyphRunAnalysis_iface.lpVtbl = &glyphrunanalysisvtbl;
2676 analysis->ref = 1;
2678 *ret = &analysis->IDWriteGlyphRunAnalysis_iface;
2679 return S_OK;