dwrite: Break out basic IDWriteFont creation from requiring a logfont.
[wine.git] / dlls / dwrite / font.c
blob00353b71ea0e34ceefb7a0a66ac1e60b0ee7c5bb
1 /*
2 * Font and collections
4 * Copyright 2012 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "dwrite.h"
24 #include "dwrite_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
28 /* PANOSE is 10 bytes in size, need to pack the structure properly */
29 #include "pshpack2.h"
30 typedef struct
32 ULONG version;
33 ULONG revision;
34 ULONG checksumadj;
35 ULONG magic;
36 USHORT flags;
37 USHORT unitsPerEm;
38 ULONGLONG created;
39 ULONGLONG modified;
40 SHORT xMin;
41 SHORT yMin;
42 SHORT xMax;
43 SHORT yMax;
44 USHORT macStyle;
45 USHORT lowestRecPPEM;
46 SHORT direction_hint;
47 SHORT index_format;
48 SHORT glyphdata_format;
49 } TT_HEAD;
51 typedef struct
53 ULONG Version;
54 ULONG italicAngle;
55 SHORT underlinePosition;
56 SHORT underlineThickness;
57 ULONG fixed_pitch;
58 ULONG minmemType42;
59 ULONG maxmemType42;
60 ULONG minmemType1;
61 ULONG maxmemType1;
62 } TT_POST;
64 typedef struct
66 USHORT version;
67 SHORT xAvgCharWidth;
68 USHORT usWeightClass;
69 USHORT usWidthClass;
70 SHORT fsType;
71 SHORT ySubscriptXSize;
72 SHORT ySubscriptYSize;
73 SHORT ySubscriptXOffset;
74 SHORT ySubscriptYOffset;
75 SHORT ySuperscriptXSize;
76 SHORT ySuperscriptYSize;
77 SHORT ySuperscriptXOffset;
78 SHORT ySuperscriptYOffset;
79 SHORT yStrikeoutSize;
80 SHORT yStrikeoutPosition;
81 SHORT sFamilyClass;
82 PANOSE panose;
83 ULONG ulUnicodeRange1;
84 ULONG ulUnicodeRange2;
85 ULONG ulUnicodeRange3;
86 ULONG ulUnicodeRange4;
87 CHAR achVendID[4];
88 USHORT fsSelection;
89 USHORT usFirstCharIndex;
90 USHORT usLastCharIndex;
91 /* According to the Apple spec, original version didn't have the below fields,
92 * version numbers were taken from the OpenType spec.
94 /* version 0 (TrueType 1.5) */
95 USHORT sTypoAscender;
96 USHORT sTypoDescender;
97 USHORT sTypoLineGap;
98 USHORT usWinAscent;
99 USHORT usWinDescent;
100 /* version 1 (TrueType 1.66) */
101 ULONG ulCodePageRange1;
102 ULONG ulCodePageRange2;
103 /* version 2 (OpenType 1.2) */
104 SHORT sxHeight;
105 SHORT sCapHeight;
106 USHORT usDefaultChar;
107 USHORT usBreakChar;
108 USHORT usMaxContext;
109 } TT_OS2_V2;
110 #include "poppack.h"
112 #ifdef WORDS_BIGENDIAN
113 #define GET_BE_WORD(x) (x)
114 #define GET_BE_DWORD(x) (x)
115 #else
116 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
117 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
118 #endif
120 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
121 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
122 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
124 #define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
125 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
126 #define MS_POST_TAG MS_MAKE_TAG('p','o','s','t')
127 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
129 struct dwrite_fontface_data {
130 LONG ref;
132 DWRITE_FONT_FACE_TYPE type;
133 UINT32 file_count;
134 IDWriteFontFile ** files;
135 DWRITE_FONT_SIMULATIONS simulations;
136 UINT32 index;
139 struct dwrite_font_data {
140 DWRITE_FONT_STYLE style;
141 DWRITE_FONT_STRETCH stretch;
142 DWRITE_FONT_WEIGHT weight;
143 DWRITE_FONT_SIMULATIONS simulations;
144 DWRITE_FONT_METRICS metrics;
146 struct dwrite_fontface_data *face_data;
148 WCHAR *facename;
151 struct dwrite_fontcollection {
152 IDWriteFontCollection IDWriteFontCollection_iface;
153 LONG ref;
155 WCHAR **families;
156 UINT32 count;
157 int alloc;
160 struct dwrite_fontfamily {
161 IDWriteFontFamily IDWriteFontFamily_iface;
162 LONG ref;
164 WCHAR *familyname;
167 struct dwrite_font {
168 IDWriteFont IDWriteFont_iface;
169 LONG ref;
171 BOOL is_system;
172 IDWriteFontFamily *family;
173 IDWriteFontFace *face;
175 struct dwrite_font_data *data;
178 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
180 struct dwrite_fonttable {
181 UINT32 magic;
182 LPVOID context;
183 UINT32 file_index;
186 struct dwrite_fontface {
187 IDWriteFontFace IDWriteFontFace_iface;
188 LONG ref;
190 struct dwrite_fontface_data *data;
192 LPVOID CMAP_table;
193 LPVOID CMAP_context;
194 DWORD CMAP_size;
196 BOOL is_system;
197 LOGFONTW logfont;
200 struct dwrite_fontfile {
201 IDWriteFontFile IDWriteFontFile_iface;
202 LONG ref;
204 IDWriteFontFileLoader *loader;
205 void *reference_key;
206 UINT32 key_size;
207 IDWriteFontFileStream *stream;
210 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family);
211 static HRESULT create_font_base(IDWriteFont **font);
213 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
215 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
218 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
220 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
223 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
225 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
228 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
230 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
233 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
235 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
238 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
240 HRESULT hr;
241 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
242 if (!This->stream)
244 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
245 if (FAILED(hr))
246 return hr;
248 if (This->stream)
250 IDWriteFontFileStream_AddRef(This->stream);
251 *stream = This->stream;
252 return S_OK;
254 return E_FAIL;
257 static VOID _free_fontface_data(struct dwrite_fontface_data *data)
259 int i;
260 if (!data)
261 return;
262 i = InterlockedDecrement(&data->ref);
263 if (i > 0)
264 return;
265 for (i = 0; i < data->file_count; i++)
266 IDWriteFontFile_Release(data->files[i]);
267 heap_free(data->files);
268 heap_free(data);
271 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
273 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
275 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
277 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
279 *obj = iface;
280 IDWriteFontFace_AddRef(iface);
281 return S_OK;
284 *obj = NULL;
285 return E_NOINTERFACE;
288 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
290 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
291 ULONG ref = InterlockedIncrement(&This->ref);
292 TRACE("(%p)->(%d)\n", This, ref);
293 return ref;
296 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
298 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
299 ULONG ref = InterlockedDecrement(&This->ref);
301 TRACE("(%p)->(%d)\n", This, ref);
303 if (!ref)
305 if (This->CMAP_context)
306 IDWriteFontFace_ReleaseFontTable(iface, This->CMAP_context);
307 _free_fontface_data(This->data);
308 heap_free(This);
311 return ref;
314 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
316 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
317 TRACE("(%p)\n", This);
318 return This->data->type;
321 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
322 IDWriteFontFile **fontfiles)
324 int i;
325 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
326 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
327 if (fontfiles == NULL)
329 *number_of_files = This->data->file_count;
330 return S_OK;
332 if (*number_of_files < This->data->file_count)
333 return E_INVALIDARG;
335 for (i = 0; i < This->data->file_count; i++)
337 IDWriteFontFile_AddRef(This->data->files[i]);
338 fontfiles[i] = This->data->files[i];
341 return S_OK;
344 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
346 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
347 TRACE("(%p)\n", This);
348 return This->data->index;
351 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
353 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
354 TRACE("(%p)\n", This);
355 return This->data->simulations;
358 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
360 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
361 FIXME("(%p): stub\n", This);
362 return FALSE;
365 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
367 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
368 FIXME("(%p)->(%p): stub\n", This, metrics);
371 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
373 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
374 FIXME("(%p): stub\n", This);
375 return 0;
378 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
379 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
381 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
382 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
383 return E_NOTIMPL;
386 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
387 UINT32 count, UINT16 *glyph_indices)
389 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
390 unsigned int i;
392 if (This->is_system)
394 HFONT hfont;
395 WCHAR *str;
396 HDC hdc;
398 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
400 str = heap_alloc(count*sizeof(WCHAR));
401 if (!str) return E_OUTOFMEMORY;
403 for (i = 0; i < count; i++)
404 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
406 hdc = CreateCompatibleDC(0);
407 hfont = CreateFontIndirectW(&This->logfont);
408 SelectObject(hdc, hfont);
410 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
411 heap_free(str);
413 DeleteDC(hdc);
414 DeleteObject(hfont);
416 return S_OK;
418 else
420 HRESULT hr;
421 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
422 if (!This->CMAP_table)
424 BOOL exists = FALSE;
425 hr = IDWriteFontFace_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->CMAP_table, &This->CMAP_size, &This->CMAP_context, &exists);
426 if (FAILED(hr) || !exists)
428 ERR("Font does not have a CMAP table\n");
429 return E_FAIL;
433 for (i = 0; i < count; i++)
435 OpenType_CMAP_GetGlyphIndex(This->CMAP_table, codepoints[i], &glyph_indices[i], 0);
437 return S_OK;
441 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
442 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
444 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
445 if (This->is_system)
447 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
448 return E_NOTIMPL;
450 else
452 HRESULT hr = S_OK;
453 int i;
454 struct dwrite_fonttable *table;
456 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
458 table = heap_alloc(sizeof(struct dwrite_fonttable));
459 table->magic = DWRITE_FONTTABLE_MAGIC;
460 if (!table)
461 return E_OUTOFMEMORY;
463 *exists = FALSE;
464 for (i = 0; i < This->data->file_count && !(*exists); i++)
466 IDWriteFontFileStream *stream;
467 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
468 if (FAILED(hr))
469 continue;
470 table->file_index = i;
472 hr = find_font_table(stream, This->data->index, table_tag, table_data, &table->context, table_size, exists);
474 IDWriteFontFileStream_Release(stream);
476 if (FAILED(hr) && !*exists)
477 heap_free(table);
478 else
479 *context = (LPVOID)table;
480 return hr;
484 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
486 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
487 struct dwrite_fonttable *table = (struct dwrite_fonttable *)table_context;
488 IDWriteFontFileStream *stream;
489 HRESULT hr;
490 TRACE("(%p)->(%p)\n", This, table_context);
492 if (table->magic != DWRITE_FONTTABLE_MAGIC)
494 TRACE("Invalid table magic\n");
495 return;
498 hr = _dwritefontfile_GetFontFileStream(This->data->files[table->file_index], &stream);
499 if (FAILED(hr))
500 return;
501 IDWriteFontFileStream_ReleaseFileFragment(stream, table->context);
502 IDWriteFontFileStream_Release(stream);
503 heap_free(table);
506 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
507 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
508 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
510 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
511 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
512 glyph_count, is_sideways, is_rtl, geometrysink);
513 return E_NOTIMPL;
516 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
517 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
519 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
520 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
521 return E_NOTIMPL;
524 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
525 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
527 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
528 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
529 return E_NOTIMPL;
532 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
533 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
534 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
536 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
537 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
538 glyph_count, metrics, is_sideways);
539 return E_NOTIMPL;
542 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
543 dwritefontface_QueryInterface,
544 dwritefontface_AddRef,
545 dwritefontface_Release,
546 dwritefontface_GetType,
547 dwritefontface_GetFiles,
548 dwritefontface_GetIndex,
549 dwritefontface_GetSimulations,
550 dwritefontface_IsSymbolFont,
551 dwritefontface_GetMetrics,
552 dwritefontface_GetGlyphCount,
553 dwritefontface_GetDesignGlyphMetrics,
554 dwritefontface_GetGlyphIndices,
555 dwritefontface_TryGetFontTable,
556 dwritefontface_ReleaseFontTable,
557 dwritefontface_GetGlyphRunOutline,
558 dwritefontface_GetRecommendedRenderingMode,
559 dwritefontface_GetGdiCompatibleMetrics,
560 dwritefontface_GetGdiCompatibleGlyphMetrics
563 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
565 struct dwrite_fontface *This;
567 *face = NULL;
569 This = heap_alloc(sizeof(struct dwrite_fontface));
570 if (!This) return E_OUTOFMEMORY;
571 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
572 if (!This->data)
574 heap_free(This);
575 return E_OUTOFMEMORY;
578 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
579 This->ref = 1;
580 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
581 This->data->file_count = 0;
582 This->data->files = NULL;
583 This->data->index = 0;
584 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
585 This->CMAP_table = NULL;
586 This->CMAP_context = NULL;
587 This->CMAP_size = 0;
589 This->is_system = TRUE;
590 memset(&This->logfont, 0, sizeof(This->logfont));
591 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
592 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
593 This->logfont.lfWeight = font->data->weight;
594 strcpyW(This->logfont.lfFaceName, font->data->facename);
596 *face = &This->IDWriteFontFace_iface;
598 return S_OK;
601 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
603 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace(face);
605 *logfont = fontface->logfont;
607 return S_OK;
610 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
612 struct dwrite_font *This = impl_from_IDWriteFont(iface);
614 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
616 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
618 *obj = iface;
619 IDWriteFont_AddRef(iface);
620 return S_OK;
623 *obj = NULL;
624 return E_NOINTERFACE;
627 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
629 struct dwrite_font *This = impl_from_IDWriteFont(iface);
630 ULONG ref = InterlockedIncrement(&This->ref);
631 TRACE("(%p)->(%d)\n", This, ref);
632 return ref;
635 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
637 struct dwrite_font *This = impl_from_IDWriteFont(iface);
638 ULONG ref = InterlockedDecrement(&This->ref);
640 TRACE("(%p)->(%d)\n", This, ref);
642 if (!ref)
644 if (This->face) IDWriteFontFace_Release(This->face);
645 IDWriteFontFamily_Release(This->family);
646 heap_free(This->data->facename);
647 _free_fontface_data(This->data->face_data);
648 heap_free(This->data);
649 heap_free(This);
652 return ref;
655 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
657 struct dwrite_font *This = impl_from_IDWriteFont(iface);
658 TRACE("(%p)->(%p)\n", This, family);
660 *family = This->family;
661 IDWriteFontFamily_AddRef(*family);
662 return S_OK;
665 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
667 struct dwrite_font *This = impl_from_IDWriteFont(iface);
668 TRACE("(%p)\n", This);
669 return This->data->weight;
672 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
674 struct dwrite_font *This = impl_from_IDWriteFont(iface);
675 TRACE("(%p)\n", This);
676 return This->data->stretch;
679 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
681 struct dwrite_font *This = impl_from_IDWriteFont(iface);
682 TRACE("(%p)\n", This);
683 return This->data->style;
686 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
688 struct dwrite_font *This = impl_from_IDWriteFont(iface);
689 FIXME("(%p): stub\n", This);
690 return FALSE;
693 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
695 struct dwrite_font *This = impl_from_IDWriteFont(iface);
696 FIXME("(%p)->(%p): stub\n", This, names);
697 return E_NOTIMPL;
700 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
701 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
703 struct dwrite_font *This = impl_from_IDWriteFont(iface);
704 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
705 return E_NOTIMPL;
708 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
710 struct dwrite_font *This = impl_from_IDWriteFont(iface);
711 TRACE("(%p)\n", This);
712 return This->data->simulations;
715 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
717 struct dwrite_font *This = impl_from_IDWriteFont(iface);
719 TRACE("(%p)->(%p)\n", This, metrics);
720 *metrics = This->data->metrics;
723 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
725 struct dwrite_font *This = impl_from_IDWriteFont(iface);
726 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
727 return E_NOTIMPL;
730 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
732 struct dwrite_font *This = impl_from_IDWriteFont(iface);
734 if (This->is_system)
736 TRACE("(%p)->(%p)\n", This, face);
738 if (!This->face)
740 HRESULT hr = create_system_fontface(This, &This->face);
741 if (FAILED(hr)) return hr;
744 *face = This->face;
745 IDWriteFontFace_AddRef(*face);
747 return S_OK;
749 else
751 TRACE("(%p)->(%p)\n", This, face);
753 if (!This->face)
755 HRESULT hr = font_create_fontface(NULL, This->data->face_data->type, This->data->face_data->file_count, This->data->face_data->files, This->data->face_data->index, This->data->face_data->simulations, &This->face);
756 if (FAILED(hr)) return hr;
759 *face = This->face;
760 IDWriteFontFace_AddRef(*face);
762 return S_OK;
766 static const IDWriteFontVtbl dwritefontvtbl = {
767 dwritefont_QueryInterface,
768 dwritefont_AddRef,
769 dwritefont_Release,
770 dwritefont_GetFontFamily,
771 dwritefont_GetWeight,
772 dwritefont_GetStretch,
773 dwritefont_GetStyle,
774 dwritefont_IsSymbolFont,
775 dwritefont_GetFaceNames,
776 dwritefont_GetInformationalStrings,
777 dwritefont_GetSimulations,
778 dwritefont_GetMetrics,
779 dwritefont_HasCharacter,
780 dwritefont_CreateFontFace
783 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
785 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
786 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
788 if (IsEqualIID(riid, &IID_IUnknown) ||
789 IsEqualIID(riid, &IID_IDWriteFontList) ||
790 IsEqualIID(riid, &IID_IDWriteFontFamily))
792 *obj = iface;
793 IDWriteFontFamily_AddRef(iface);
794 return S_OK;
797 *obj = NULL;
798 return E_NOINTERFACE;
801 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
803 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
804 ULONG ref = InterlockedIncrement(&This->ref);
805 TRACE("(%p)->(%d)\n", This, ref);
806 return ref;
809 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
811 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
812 ULONG ref = InterlockedDecrement(&This->ref);
814 TRACE("(%p)->(%d)\n", This, ref);
816 if (!ref)
818 heap_free(This->familyname);
819 heap_free(This);
822 return ref;
825 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
827 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
828 FIXME("(%p)->(%p): stub\n", This, collection);
829 return E_NOTIMPL;
832 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
834 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
835 FIXME("(%p): stub\n", This);
836 return 0;
839 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
841 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
842 FIXME("(%p)->(%u %p): stub\n", This, index, font);
843 return E_NOTIMPL;
846 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
848 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
849 static const WCHAR enusW[] = {'e','n','-','u','s',0};
850 HRESULT hr;
852 TRACE("(%p)->(%p)\n", This, names);
854 hr = create_localizedstrings(names);
855 if (FAILED(hr)) return hr;
857 return add_localizedstring(*names, enusW, This->familyname);
860 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
861 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
863 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
864 LOGFONTW lf;
866 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
868 memset(&lf, 0, sizeof(lf));
869 lf.lfWeight = weight;
870 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
871 strcpyW(lf.lfFaceName, This->familyname);
873 return create_font_from_logfont(&lf, font);
876 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
877 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
879 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
880 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
881 return E_NOTIMPL;
884 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
885 dwritefontfamily_QueryInterface,
886 dwritefontfamily_AddRef,
887 dwritefontfamily_Release,
888 dwritefontfamily_GetFontCollection,
889 dwritefontfamily_GetFontCount,
890 dwritefontfamily_GetFont,
891 dwritefontfamily_GetFamilyNames,
892 dwritefontfamily_GetFirstMatchingFont,
893 dwritefontfamily_GetMatchingFonts
896 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
898 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
899 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
901 if (IsEqualIID(riid, &IID_IUnknown) ||
902 IsEqualIID(riid, &IID_IDWriteFontCollection))
904 *obj = iface;
905 IDWriteFontCollection_AddRef(iface);
906 return S_OK;
909 *obj = NULL;
910 return E_NOINTERFACE;
913 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
915 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
916 ULONG ref = InterlockedIncrement(&This->ref);
917 TRACE("(%p)->(%d)\n", This, ref);
918 return ref;
921 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
923 unsigned int i;
924 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
925 ULONG ref = InterlockedDecrement(&This->ref);
926 TRACE("(%p)->(%d)\n", This, ref);
928 if (!ref)
930 for (i = 0; i < This->count; i++)
931 heap_free(This->families[i]);
932 heap_free(This->families);
933 heap_free(This);
936 return ref;
939 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
941 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
942 TRACE("(%p)\n", This);
943 return This->count;
946 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
948 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
950 TRACE("(%p)->(%u %p)\n", This, index, family);
952 if (index >= This->count)
954 *family = NULL;
955 return E_FAIL;
958 return create_fontfamily(This->families[index], family);
961 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
963 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
964 UINT32 i;
966 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
968 for (i = 0; i < This->count; i++)
969 if (!strcmpW(This->families[i], name))
971 *index = i;
972 *exists = TRUE;
973 return S_OK;
976 *index = (UINT32)-1;
977 *exists = FALSE;
979 return S_OK;
982 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
984 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
985 FIXME("(%p)->(%p %p): stub\n", This, face, font);
986 return E_NOTIMPL;
989 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
990 dwritefontcollection_QueryInterface,
991 dwritefontcollection_AddRef,
992 dwritefontcollection_Release,
993 dwritefontcollection_GetFontFamilyCount,
994 dwritefontcollection_GetFontFamily,
995 dwritefontcollection_FindFamilyName,
996 dwritefontcollection_GetFontFromFontFace
999 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
1001 /* check for duplicate family name */
1002 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
1004 /* double array length */
1005 if (collection->count == collection->alloc)
1007 collection->alloc *= 2;
1008 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
1011 collection->families[collection->count++] = heap_strdupW(family);
1012 TRACE("family name %s\n", debugstr_w(family));
1014 return S_OK;
1017 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1019 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1020 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1023 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1025 struct dwrite_fontcollection *This;
1026 LOGFONTW lf;
1027 HDC hdc;
1029 *collection = NULL;
1031 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1032 if (!This) return E_OUTOFMEMORY;
1034 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1035 This->ref = 1;
1036 This->alloc = 50;
1037 This->count = 0;
1038 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1040 TRACE("building system font collection:\n");
1042 hdc = CreateCompatibleDC(0);
1043 memset(&lf, 0, sizeof(lf));
1044 lf.lfCharSet = DEFAULT_CHARSET;
1045 lf.lfPitchAndFamily = DEFAULT_PITCH;
1046 lf.lfFaceName[0] = 0;
1047 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1048 DeleteDC(hdc);
1050 *collection = &This->IDWriteFontCollection_iface;
1052 return S_OK;
1055 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
1057 struct dwrite_fontfamily *This;
1059 *family = NULL;
1061 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1062 if (!This) return E_OUTOFMEMORY;
1064 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1065 This->ref = 1;
1066 This->familyname = heap_strdupW(familyname);
1068 *family = &This->IDWriteFontFamily_iface;
1070 return S_OK;
1073 static void get_font_properties(struct dwrite_font *font, HDC hdc)
1075 TT_OS2_V2 tt_os2;
1076 TT_HEAD tt_head;
1077 TT_POST tt_post;
1078 LONG size;
1080 /* default stretch and weight to normal */
1081 font->data->stretch = DWRITE_FONT_STRETCH_NORMAL;
1082 font->data->weight = DWRITE_FONT_WEIGHT_NORMAL;
1084 memset(&font->data->metrics, 0, sizeof(font->data->metrics));
1086 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1087 if (size != GDI_ERROR)
1089 if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
1091 memset(&tt_os2, 0, sizeof(tt_os2));
1092 if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return;
1094 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
1095 if (GET_BE_WORD(tt_os2.usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
1096 font->data->stretch = GET_BE_WORD(tt_os2.usWidthClass);
1098 font->data->weight = GET_BE_WORD(tt_os2.usWeightClass);
1099 TRACE("stretch=%d, weight=%d\n", font->data->stretch, font->data->weight);
1101 font->data->metrics.ascent = GET_BE_WORD(tt_os2.sTypoAscender);
1102 font->data->metrics.descent = GET_BE_WORD(tt_os2.sTypoDescender);
1103 font->data->metrics.lineGap = GET_BE_WORD(tt_os2.sTypoLineGap);
1104 font->data->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
1105 font->data->metrics.xHeight = GET_BE_WORD(tt_os2.sxHeight);
1106 font->data->metrics.strikethroughPosition = GET_BE_WORD(tt_os2.yStrikeoutPosition);
1107 font->data->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
1110 memset(&tt_head, 0, sizeof(tt_head));
1111 if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
1113 font->data->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
1116 memset(&tt_post, 0, sizeof(tt_post));
1117 if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
1119 font->data->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
1120 font->data->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
1124 static HRESULT create_font_base(IDWriteFont **font)
1126 struct dwrite_font *This;
1127 *font = NULL;
1129 This = heap_alloc(sizeof(struct dwrite_font));
1130 if (!This) return E_OUTOFMEMORY;
1131 This->data = heap_alloc(sizeof(struct dwrite_font_data));
1132 if (!This->data)
1134 heap_free(This);
1135 return E_OUTOFMEMORY;
1138 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
1139 This->ref = 1;
1140 This->data->face_data = NULL;
1141 This->face = NULL;
1142 This->family = NULL;
1143 This->is_system = FALSE;
1145 *font = &This->IDWriteFont_iface;
1147 return S_OK;
1150 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1152 const WCHAR* facename, *familyname;
1153 struct dwrite_font *This;
1154 IDWriteFontFamily *family;
1155 OUTLINETEXTMETRICW *otm;
1156 HRESULT hr;
1157 HFONT hfont;
1158 HDC hdc;
1159 int ret;
1161 hr = create_font_base(font);
1162 if (FAILED(hr))
1163 return hr;
1165 This = impl_from_IDWriteFont(*font);
1167 hfont = CreateFontIndirectW(logfont);
1168 if (!hfont)
1170 heap_free(This->data);
1171 heap_free(This);
1172 return DWRITE_E_NOFONT;
1175 hdc = CreateCompatibleDC(0);
1176 SelectObject(hdc, hfont);
1178 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1179 otm = heap_alloc(ret);
1180 if (!otm)
1182 heap_free(This->data);
1183 heap_free(This);
1184 DeleteDC(hdc);
1185 DeleteObject(hfont);
1186 return E_OUTOFMEMORY;
1188 otm->otmSize = ret;
1189 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1191 get_font_properties(This, hdc);
1193 DeleteDC(hdc);
1194 DeleteObject(hfont);
1196 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1197 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1198 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1200 hr = create_fontfamily(familyname, &family);
1201 heap_free(otm);
1202 if (hr != S_OK)
1204 heap_free(This->data);
1205 heap_free(This);
1206 return hr;
1209 This->is_system = TRUE;
1210 This->family = family;
1211 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1212 This->data->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
1213 This->data->facename = heap_strdupW(logfont->lfFaceName);
1215 return S_OK;
1218 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1220 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1222 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1224 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1226 *obj = iface;
1227 IDWriteFontFile_AddRef(iface);
1228 return S_OK;
1231 *obj = NULL;
1232 return E_NOINTERFACE;
1235 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1237 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1238 ULONG ref = InterlockedIncrement(&This->ref);
1239 TRACE("(%p)->(%d)\n", This, ref);
1240 return ref;
1243 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1245 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1246 ULONG ref = InterlockedDecrement(&This->ref);
1248 TRACE("(%p)->(%d)\n", This, ref);
1250 if (!ref)
1252 IDWriteFontFileLoader_Release(This->loader);
1253 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1254 heap_free(This->reference_key);
1255 heap_free(This);
1258 return ref;
1261 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1263 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1264 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1265 *fontFileReferenceKey = This->reference_key;
1266 *fontFileReferenceKeySize = This->key_size;
1268 return S_OK;
1271 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1273 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1274 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1275 *fontFileLoader = This->loader;
1276 IDWriteFontFileLoader_AddRef(This->loader);
1278 return S_OK;
1281 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1283 HRESULT hr;
1284 const void *font_data;
1285 void *context;
1286 IDWriteFontFileStream *stream;
1288 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1289 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1291 *isSupportedFontType = FALSE;
1292 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1293 if (fontFaceType)
1294 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1295 *numberOfFaces = 0;
1297 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1298 if (FAILED(hr))
1299 return S_OK;
1300 hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, 28, &context);
1301 if (SUCCEEDED(hr))
1303 hr = analyze_opentype_font(font_data, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1304 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1306 /* TODO: Further Analysis */
1307 IDWriteFontFileStream_Release(stream);
1308 return S_OK;
1311 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1312 dwritefontfile_QueryInterface,
1313 dwritefontfile_AddRef,
1314 dwritefontfile_Release,
1315 dwritefontfile_GetReferenceKey,
1316 dwritefontfile_GetLoader,
1317 dwritefontfile_Analyze,
1320 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1322 struct dwrite_fontfile *This;
1324 This = heap_alloc(sizeof(struct dwrite_fontfile));
1325 if (!This) return E_OUTOFMEMORY;
1327 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1328 This->ref = 1;
1329 IDWriteFontFileLoader_AddRef(loader);
1330 This->loader = loader;
1331 This->stream = NULL;
1332 This->reference_key = heap_alloc(key_size);
1333 memcpy(This->reference_key, reference_key, key_size);
1334 This->key_size = key_size;
1336 *font_file = &This->IDWriteFontFile_iface;
1338 return S_OK;
1341 HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS sim_flags, IDWriteFontFace **font_face)
1343 int i;
1344 struct dwrite_fontface *This;
1345 HRESULT hr = S_OK;
1347 *font_face = NULL;
1349 This = heap_alloc(sizeof(struct dwrite_fontface));
1350 if (!This) return E_OUTOFMEMORY;
1351 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1352 if (!This)
1354 heap_free(This);
1355 return E_OUTOFMEMORY;
1358 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
1359 This->ref = 1;
1360 This->data->ref = 1;
1361 This->data->type = facetype;
1362 This->data->file_count = files_number;
1363 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1364 This->CMAP_table = NULL;
1365 This->CMAP_context = NULL;
1366 This->CMAP_size = 0;
1367 /* Verify font file streams */
1368 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1370 IDWriteFontFileStream *stream;
1371 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1372 if (SUCCEEDED(hr))
1373 IDWriteFontFileStream_Release(stream);
1375 if (FAILED(hr))
1377 heap_free(This->data->files);
1378 heap_free(This->data);
1379 heap_free(This);
1380 return hr;
1382 for (i = 0; i < This->data->file_count; i++)
1384 This->data->files[i] = font_files[i];
1385 IDWriteFontFile_AddRef(font_files[i]);
1388 This->data->index = index;
1389 This->data->simulations = sim_flags;
1390 This->is_system = FALSE;
1392 *font_face = &This->IDWriteFontFace_iface;
1394 return S_OK;
1397 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1399 struct dwrite_localfontfilestream
1401 IDWriteFontFileStream IDWriteFontFileStream_iface;
1402 LONG ref;
1404 HANDLE handle;
1407 struct dwrite_localfontfileloader {
1408 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1409 LONG ref;
1412 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1414 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1417 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1419 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1422 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1424 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1425 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1426 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1428 *obj = iface;
1429 IDWriteFontFileStream_AddRef(iface);
1430 return S_OK;
1433 *obj = NULL;
1434 return E_NOINTERFACE;
1437 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1439 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1440 ULONG ref = InterlockedIncrement(&This->ref);
1441 TRACE("(%p)->(%d)\n", This, ref);
1442 return ref;
1445 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1447 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1448 ULONG ref = InterlockedDecrement(&This->ref);
1450 TRACE("(%p)->(%d)\n", This, ref);
1452 if (!ref)
1454 if (This->handle != INVALID_HANDLE_VALUE)
1455 CloseHandle(This->handle);
1456 heap_free(This);
1459 return ref;
1462 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1464 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1465 LARGE_INTEGER distance;
1466 DWORD bytes = fragment_size;
1467 DWORD read;
1469 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1470 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1472 *fragment_context = NULL;
1473 distance.QuadPart = offset;
1474 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1475 return E_FAIL;
1476 *fragment_start = *fragment_context = heap_alloc(bytes);
1477 if (!*fragment_context)
1478 return E_FAIL;
1479 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1481 heap_free(*fragment_context);
1482 return E_FAIL;
1485 return S_OK;
1488 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1490 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1491 TRACE("(%p)->(%p)\n", This, fragment_context);
1492 heap_free(fragment_context);
1495 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1497 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1498 LARGE_INTEGER li;
1499 TRACE("(%p)->(%p)\n",This, size);
1500 GetFileSizeEx(This->handle, &li);
1501 *size = li.QuadPart;
1502 return S_OK;
1505 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1507 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1508 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1509 *last_writetime = 0;
1510 return E_NOTIMPL;
1513 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1515 localfontfilestream_QueryInterface,
1516 localfontfilestream_AddRef,
1517 localfontfilestream_Release,
1518 localfontfilestream_ReadFileFragment,
1519 localfontfilestream_ReleaseFileFragment,
1520 localfontfilestream_GetFileSize,
1521 localfontfilestream_GetLastWriteTime
1524 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1526 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1527 if (!This)
1528 return E_OUTOFMEMORY;
1530 This->ref = 1;
1531 This->handle = handle;
1532 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1534 *iface = &This->IDWriteFontFileStream_iface;
1535 return S_OK;
1538 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1540 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1542 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1544 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1546 *obj = iface;
1547 IDWriteLocalFontFileLoader_AddRef(iface);
1548 return S_OK;
1551 *obj = NULL;
1552 return E_NOINTERFACE;
1555 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1557 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1558 ULONG ref = InterlockedIncrement(&This->ref);
1559 TRACE("(%p)->(%d)\n", This, ref);
1560 return ref;
1563 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1565 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1566 ULONG ref = InterlockedDecrement(&This->ref);
1568 TRACE("(%p)->(%d)\n", This, ref);
1570 if (!ref)
1571 heap_free(This);
1573 return ref;
1576 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1578 HANDLE handle;
1579 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1580 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1582 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1584 TRACE("name: %s\n",debugstr_w(name));
1585 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1586 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1588 if (handle == INVALID_HANDLE_VALUE)
1589 return E_FAIL;
1591 return create_localfontfilestream(handle, fontFileStream);
1594 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1596 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1597 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1598 *length = key_size;
1599 return S_OK;
1602 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1604 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1605 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1606 if (length < key_size)
1607 return E_INVALIDARG;
1608 lstrcpynW((WCHAR*)key, path, key_size);
1609 return S_OK;
1612 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1614 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1615 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1616 return E_NOTIMPL;
1619 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1620 localfontfileloader_QueryInterface,
1621 localfontfileloader_AddRef,
1622 localfontfileloader_Release,
1623 localfontfileloader_CreateStreamFromKey,
1624 localfontfileloader_GetFilePathLengthFromKey,
1625 localfontfileloader_GetFilePathFromKey,
1626 localfontfileloader_GetLastWriteTimeFromKey
1629 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1631 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1632 if (!This)
1633 return E_OUTOFMEMORY;
1635 This->ref = 1;
1636 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1638 *iface = &This->IDWriteLocalFontFileLoader_iface;
1639 return S_OK;