dwrite: Remove a space before a '\n'.
[wine.git] / dlls / dwrite / font.c
blobc835ff4ce3a0bd731866494467b9fbd2b820eaf5
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')
128 struct dwrite_fontcollection {
129 IDWriteFontCollection IDWriteFontCollection_iface;
131 WCHAR **families;
132 UINT32 count;
133 int alloc;
136 static IDWriteFontCollection *system_collection;
138 struct dwrite_fontfamily {
139 IDWriteFontFamily IDWriteFontFamily_iface;
140 LONG ref;
142 WCHAR *familyname;
145 struct dwrite_font {
146 IDWriteFont IDWriteFont_iface;
147 LONG ref;
149 BOOL is_system;
150 IDWriteFontFamily *family;
151 IDWriteFontFace *face;
152 DWRITE_FONT_STYLE style;
153 DWRITE_FONT_STRETCH stretch;
154 DWRITE_FONT_WEIGHT weight;
155 DWRITE_FONT_METRICS metrics;
156 WCHAR *facename;
159 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
161 struct dwrite_fonttable {
162 UINT32 magic;
163 LPVOID context;
164 UINT32 file_index;
167 struct dwrite_fontface {
168 IDWriteFontFace IDWriteFontFace_iface;
169 LONG ref;
171 DWRITE_FONT_FACE_TYPE type;
172 UINT32 file_count;
173 IDWriteFontFile ** files;
174 DWRITE_FONT_SIMULATIONS simulations;
175 UINT32 index;
177 BOOL is_system;
178 LOGFONTW logfont;
181 struct dwrite_fontfile {
182 IDWriteFontFile IDWriteFontFile_iface;
183 LONG ref;
185 IDWriteFontFileLoader *loader;
186 void *reference_key;
187 UINT32 key_size;
188 IDWriteFontFileStream *stream;
191 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family);
193 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
195 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
198 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
200 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
203 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
205 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
208 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
210 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
213 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
215 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
218 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
220 HRESULT hr;
221 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
222 if (!This->stream)
224 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
225 if (FAILED(hr))
226 return hr;
228 if (This->stream)
230 IDWriteFontFileStream_AddRef(This->stream);
231 *stream = This->stream;
232 return S_OK;
234 return E_FAIL;
237 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
239 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
241 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
243 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
245 *obj = iface;
246 IDWriteFontFace_AddRef(iface);
247 return S_OK;
250 *obj = NULL;
251 return E_NOINTERFACE;
254 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
256 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
257 ULONG ref = InterlockedIncrement(&This->ref);
258 TRACE("(%p)->(%d)\n", This, ref);
259 return ref;
262 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
264 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
265 ULONG ref = InterlockedDecrement(&This->ref);
267 TRACE("(%p)->(%d)\n", This, ref);
269 if (!ref)
271 int i;
272 for (i = 0; i < This->file_count; i++)
273 IDWriteFontFile_Release(This->files[i]);
274 heap_free(This->files);
275 heap_free(This);
278 return ref;
281 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
283 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
284 TRACE("(%p)\n", This);
285 return This->type;
288 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
289 IDWriteFontFile **fontfiles)
291 int i;
292 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
293 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
294 if (fontfiles == NULL)
296 *number_of_files = This->file_count;
297 return S_OK;
299 if (*number_of_files < This->file_count)
300 return E_INVALIDARG;
302 for (i = 0; i < This->file_count; i++)
304 IDWriteFontFile_AddRef(This->files[i]);
305 fontfiles[i] = This->files[i];
308 return S_OK;
311 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
313 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
314 TRACE("(%p)\n", This);
315 return This->index;
318 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
320 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
321 TRACE("(%p)\n", This);
322 return This->simulations;
325 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
327 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
328 FIXME("(%p): stub\n", This);
329 return FALSE;
332 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
334 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
335 FIXME("(%p)->(%p): stub\n", This, metrics);
338 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
340 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
341 FIXME("(%p): stub\n", This);
342 return 0;
345 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
346 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
348 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
349 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
350 return E_NOTIMPL;
353 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
354 UINT32 count, UINT16 *glyph_indices)
356 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
357 if (This->is_system)
359 HFONT hfont;
360 WCHAR *str;
361 HDC hdc;
362 unsigned int i;
364 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
366 str = heap_alloc(count*sizeof(WCHAR));
367 if (!str) return E_OUTOFMEMORY;
369 for (i = 0; i < count; i++)
370 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
372 hdc = CreateCompatibleDC(0);
373 hfont = CreateFontIndirectW(&This->logfont);
374 SelectObject(hdc, hfont);
376 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
377 heap_free(str);
379 DeleteDC(hdc);
380 DeleteObject(hfont);
382 return S_OK;
384 else
386 FIXME("(%p)->(%p %u %p): Stub\n", This, codepoints, count, glyph_indices);
387 return E_NOTIMPL;
391 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
392 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
394 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
395 if (This->is_system)
397 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
398 return E_NOTIMPL;
400 else
402 HRESULT hr = S_OK;
403 int i;
404 struct dwrite_fonttable *table;
406 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
408 table = heap_alloc(sizeof(struct dwrite_fonttable));
409 table->magic = DWRITE_FONTTABLE_MAGIC;
410 if (!table)
411 return E_OUTOFMEMORY;
413 *exists = FALSE;
414 for (i = 0; i < This->file_count && !(*exists); i++)
416 IDWriteFontFileStream *stream;
417 hr = _dwritefontfile_GetFontFileStream(This->files[i], &stream);
418 if (FAILED(hr))
419 continue;
420 table->file_index = i;
422 hr = find_font_table(stream, This->index, table_tag, table_data, &table->context, table_size, exists);
424 IDWriteFontFileStream_Release(stream);
426 if (FAILED(hr) && !*exists)
427 heap_free(table);
428 else
429 *context = (LPVOID)table;
430 return hr;
434 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
436 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
437 struct dwrite_fonttable *table = (struct dwrite_fonttable *)table_context;
438 IDWriteFontFileStream *stream;
439 HRESULT hr;
440 TRACE("(%p)->(%p)\n", This, table_context);
442 if (table->magic != DWRITE_FONTTABLE_MAGIC)
444 TRACE("Invalid table magic\n");
445 return;
448 hr = _dwritefontfile_GetFontFileStream(This->files[table->file_index], &stream);
449 if (FAILED(hr))
450 return;
451 IDWriteFontFileStream_ReleaseFileFragment(stream, table->context);
452 IDWriteFontFileStream_Release(stream);
453 heap_free(table);
456 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
457 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
458 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
460 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
461 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
462 glyph_count, is_sideways, is_rtl, geometrysink);
463 return E_NOTIMPL;
466 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
467 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
469 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
470 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
471 return E_NOTIMPL;
474 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
475 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
477 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
478 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
479 return E_NOTIMPL;
482 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
483 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
484 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
486 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
487 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
488 glyph_count, metrics, is_sideways);
489 return E_NOTIMPL;
492 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
493 dwritefontface_QueryInterface,
494 dwritefontface_AddRef,
495 dwritefontface_Release,
496 dwritefontface_GetType,
497 dwritefontface_GetFiles,
498 dwritefontface_GetIndex,
499 dwritefontface_GetSimulations,
500 dwritefontface_IsSymbolFont,
501 dwritefontface_GetMetrics,
502 dwritefontface_GetGlyphCount,
503 dwritefontface_GetDesignGlyphMetrics,
504 dwritefontface_GetGlyphIndices,
505 dwritefontface_TryGetFontTable,
506 dwritefontface_ReleaseFontTable,
507 dwritefontface_GetGlyphRunOutline,
508 dwritefontface_GetRecommendedRenderingMode,
509 dwritefontface_GetGdiCompatibleMetrics,
510 dwritefontface_GetGdiCompatibleGlyphMetrics
513 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
515 struct dwrite_fontface *This;
517 *face = NULL;
519 This = heap_alloc(sizeof(struct dwrite_fontface));
520 if (!This) return E_OUTOFMEMORY;
522 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
523 This->ref = 1;
524 This->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
525 This->file_count = 0;
526 This->files = NULL;
527 This->index = 0;
528 This->simulations = DWRITE_FONT_SIMULATIONS_NONE;
530 This->is_system = TRUE;
531 memset(&This->logfont, 0, sizeof(This->logfont));
532 This->logfont.lfItalic = font->style == DWRITE_FONT_STYLE_ITALIC;
533 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
534 This->logfont.lfWeight = font->weight;
535 strcpyW(This->logfont.lfFaceName, font->facename);
537 *face = &This->IDWriteFontFace_iface;
539 return S_OK;
542 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
544 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace(face);
546 *logfont = fontface->logfont;
548 return S_OK;
551 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
553 struct dwrite_font *This = impl_from_IDWriteFont(iface);
555 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
557 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
559 *obj = iface;
560 IDWriteFont_AddRef(iface);
561 return S_OK;
564 *obj = NULL;
565 return E_NOINTERFACE;
568 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
570 struct dwrite_font *This = impl_from_IDWriteFont(iface);
571 ULONG ref = InterlockedIncrement(&This->ref);
572 TRACE("(%p)->(%d)\n", This, ref);
573 return ref;
576 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
578 struct dwrite_font *This = impl_from_IDWriteFont(iface);
579 ULONG ref = InterlockedDecrement(&This->ref);
581 TRACE("(%p)->(%d)\n", This, ref);
583 if (!ref)
585 if (This->face) IDWriteFontFace_Release(This->face);
586 IDWriteFontFamily_Release(This->family);
587 heap_free(This->facename);
588 heap_free(This);
591 return ref;
594 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
596 struct dwrite_font *This = impl_from_IDWriteFont(iface);
597 TRACE("(%p)->(%p)\n", This, family);
599 *family = This->family;
600 IDWriteFontFamily_AddRef(*family);
601 return S_OK;
604 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
606 struct dwrite_font *This = impl_from_IDWriteFont(iface);
607 TRACE("(%p)\n", This);
608 return This->weight;
611 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
613 struct dwrite_font *This = impl_from_IDWriteFont(iface);
614 TRACE("(%p)\n", This);
615 return This->stretch;
618 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
620 struct dwrite_font *This = impl_from_IDWriteFont(iface);
621 TRACE("(%p)\n", This);
622 return This->style;
625 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
627 struct dwrite_font *This = impl_from_IDWriteFont(iface);
628 FIXME("(%p): stub\n", This);
629 return FALSE;
632 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
634 struct dwrite_font *This = impl_from_IDWriteFont(iface);
635 FIXME("(%p)->(%p): stub\n", This, names);
636 return E_NOTIMPL;
639 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
640 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
642 struct dwrite_font *This = impl_from_IDWriteFont(iface);
643 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
644 return E_NOTIMPL;
647 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
649 struct dwrite_font *This = impl_from_IDWriteFont(iface);
650 FIXME("(%p): stub\n", This);
651 return DWRITE_FONT_SIMULATIONS_NONE;
654 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
656 struct dwrite_font *This = impl_from_IDWriteFont(iface);
658 TRACE("(%p)->(%p)\n", This, metrics);
659 *metrics = This->metrics;
662 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
664 struct dwrite_font *This = impl_from_IDWriteFont(iface);
665 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
666 return E_NOTIMPL;
669 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
671 struct dwrite_font *This = impl_from_IDWriteFont(iface);
673 if (This->is_system)
675 TRACE("(%p)->(%p)\n", This, face);
677 if (!This->face)
679 HRESULT hr = create_system_fontface(This, &This->face);
680 if (FAILED(hr)) return hr;
683 *face = This->face;
684 IDWriteFontFace_AddRef(*face);
686 return S_OK;
688 else
690 TRACE("(%p)->(%p)\n", This, face);
691 if (This->face)
693 *face = This->face;
694 IDWriteFontFace_AddRef(*face);
696 return S_OK;
700 static const IDWriteFontVtbl dwritefontvtbl = {
701 dwritefont_QueryInterface,
702 dwritefont_AddRef,
703 dwritefont_Release,
704 dwritefont_GetFontFamily,
705 dwritefont_GetWeight,
706 dwritefont_GetStretch,
707 dwritefont_GetStyle,
708 dwritefont_IsSymbolFont,
709 dwritefont_GetFaceNames,
710 dwritefont_GetInformationalStrings,
711 dwritefont_GetSimulations,
712 dwritefont_GetMetrics,
713 dwritefont_HasCharacter,
714 dwritefont_CreateFontFace
717 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
719 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
720 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
722 if (IsEqualIID(riid, &IID_IUnknown) ||
723 IsEqualIID(riid, &IID_IDWriteFontList) ||
724 IsEqualIID(riid, &IID_IDWriteFontFamily))
726 *obj = iface;
727 IDWriteFontFamily_AddRef(iface);
728 return S_OK;
731 *obj = NULL;
732 return E_NOINTERFACE;
735 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
737 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
738 ULONG ref = InterlockedIncrement(&This->ref);
739 TRACE("(%p)->(%d)\n", This, ref);
740 return ref;
743 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
745 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
746 ULONG ref = InterlockedDecrement(&This->ref);
748 TRACE("(%p)->(%d)\n", This, ref);
750 if (!ref)
752 heap_free(This->familyname);
753 heap_free(This);
756 return ref;
759 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
761 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
762 FIXME("(%p)->(%p): stub\n", This, collection);
763 return E_NOTIMPL;
766 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
768 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
769 FIXME("(%p): stub\n", This);
770 return 0;
773 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
775 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
776 FIXME("(%p)->(%u %p): stub\n", This, index, font);
777 return E_NOTIMPL;
780 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
782 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
783 static const WCHAR enusW[] = {'e','n','-','u','s',0};
784 HRESULT hr;
786 TRACE("(%p)->(%p)\n", This, names);
788 hr = create_localizedstrings(names);
789 if (FAILED(hr)) return hr;
791 return add_localizedstring(*names, enusW, This->familyname);
794 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
795 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
797 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
798 LOGFONTW lf;
800 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
802 memset(&lf, 0, sizeof(lf));
803 lf.lfWeight = weight;
804 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
805 strcpyW(lf.lfFaceName, This->familyname);
807 return create_font_from_logfont(&lf, font);
810 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
811 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
813 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
814 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
815 return E_NOTIMPL;
818 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
819 dwritefontfamily_QueryInterface,
820 dwritefontfamily_AddRef,
821 dwritefontfamily_Release,
822 dwritefontfamily_GetFontCollection,
823 dwritefontfamily_GetFontCount,
824 dwritefontfamily_GetFont,
825 dwritefontfamily_GetFamilyNames,
826 dwritefontfamily_GetFirstMatchingFont,
827 dwritefontfamily_GetMatchingFonts
830 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
832 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
833 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
835 if (IsEqualIID(riid, &IID_IUnknown) ||
836 IsEqualIID(riid, &IID_IDWriteFontCollection))
838 *obj = iface;
839 IDWriteFontCollection_AddRef(iface);
840 return S_OK;
843 *obj = NULL;
844 return E_NOINTERFACE;
847 static ULONG WINAPI dwritesysfontcollection_AddRef(IDWriteFontCollection *iface)
849 return 2;
852 static ULONG WINAPI dwritesysfontcollection_Release(IDWriteFontCollection *iface)
854 return 1;
857 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
859 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
860 TRACE("(%p)\n", This);
861 return This->count;
864 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
866 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
868 TRACE("(%p)->(%u %p)\n", This, index, family);
870 if (index >= This->count)
872 *family = NULL;
873 return E_FAIL;
876 return create_fontfamily(This->families[index], family);
879 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
881 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
882 UINT32 i;
884 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
886 for (i = 0; i < This->count; i++)
887 if (!strcmpW(This->families[i], name))
889 *index = i;
890 *exists = TRUE;
891 return S_OK;
894 *index = (UINT32)-1;
895 *exists = FALSE;
897 return S_OK;
900 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
902 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
903 FIXME("(%p)->(%p %p): stub\n", This, face, font);
904 return E_NOTIMPL;
907 static const IDWriteFontCollectionVtbl systemfontcollectionvtbl = {
908 dwritefontcollection_QueryInterface,
909 dwritesysfontcollection_AddRef,
910 dwritesysfontcollection_Release,
911 dwritefontcollection_GetFontFamilyCount,
912 dwritefontcollection_GetFontFamily,
913 dwritefontcollection_FindFamilyName,
914 dwritefontcollection_GetFontFromFontFace
917 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
919 /* check for duplicate family name */
920 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
922 /* double array length */
923 if (collection->count == collection->alloc)
925 collection->alloc *= 2;
926 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
929 collection->families[collection->count++] = heap_strdupW(family);
930 TRACE("family name %s\n", debugstr_w(family));
932 return S_OK;
935 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
937 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
938 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
941 static void release_font_collection(IDWriteFontCollection *iface)
943 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
944 unsigned int i;
946 for (i = 0; i < This->count; i++)
947 heap_free(This->families[i]);
948 heap_free(This->families);
949 heap_free(This);
952 void release_system_fontcollection(void)
954 if (system_collection)
955 release_font_collection(system_collection);
958 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
960 if (!system_collection)
962 struct dwrite_fontcollection *This;
963 LOGFONTW lf;
964 HDC hdc;
966 *collection = NULL;
968 This = heap_alloc(sizeof(struct dwrite_fontcollection));
969 if (!This) return E_OUTOFMEMORY;
971 This->IDWriteFontCollection_iface.lpVtbl = &systemfontcollectionvtbl;
972 This->alloc = 50;
973 This->count = 0;
974 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
976 TRACE("building system font collection:\n");
978 hdc = CreateCompatibleDC(0);
979 memset(&lf, 0, sizeof(lf));
980 lf.lfCharSet = DEFAULT_CHARSET;
981 lf.lfPitchAndFamily = DEFAULT_PITCH;
982 lf.lfFaceName[0] = 0;
983 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
984 DeleteDC(hdc);
986 if (InterlockedCompareExchangePointer((void**)&system_collection, &This->IDWriteFontCollection_iface, NULL))
987 release_font_collection(&This->IDWriteFontCollection_iface);
990 *collection = system_collection;
992 return S_OK;
995 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
997 struct dwrite_fontfamily *This;
999 *family = NULL;
1001 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1002 if (!This) return E_OUTOFMEMORY;
1004 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1005 This->ref = 1;
1006 This->familyname = heap_strdupW(familyname);
1008 *family = &This->IDWriteFontFamily_iface;
1010 return S_OK;
1013 static void get_font_properties(struct dwrite_font *font, HDC hdc)
1015 TT_OS2_V2 tt_os2;
1016 TT_HEAD tt_head;
1017 TT_POST tt_post;
1018 LONG size;
1020 /* default stretch and weight to normal */
1021 font->stretch = DWRITE_FONT_STRETCH_NORMAL;
1022 font->weight = DWRITE_FONT_WEIGHT_NORMAL;
1024 memset(&font->metrics, 0, sizeof(font->metrics));
1026 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1027 if (size != GDI_ERROR)
1029 if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
1031 memset(&tt_os2, 0, sizeof(tt_os2));
1032 if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return;
1034 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
1035 if (GET_BE_WORD(tt_os2.usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
1036 font->stretch = GET_BE_WORD(tt_os2.usWidthClass);
1038 font->weight = GET_BE_WORD(tt_os2.usWeightClass);
1039 TRACE("stretch=%d, weight=%d\n", font->stretch, font->weight);
1041 font->metrics.ascent = GET_BE_WORD(tt_os2.sTypoAscender);
1042 font->metrics.descent = GET_BE_WORD(tt_os2.sTypoDescender);
1043 font->metrics.lineGap = GET_BE_WORD(tt_os2.sTypoLineGap);
1044 font->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
1045 font->metrics.xHeight = GET_BE_WORD(tt_os2.sxHeight);
1046 font->metrics.strikethroughPosition = GET_BE_WORD(tt_os2.yStrikeoutPosition);
1047 font->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
1050 memset(&tt_head, 0, sizeof(tt_head));
1051 if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
1053 font->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
1056 memset(&tt_post, 0, sizeof(tt_post));
1057 if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
1059 font->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
1060 font->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
1064 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1066 const WCHAR* facename, *familyname;
1067 struct dwrite_font *This;
1068 IDWriteFontFamily *family;
1069 OUTLINETEXTMETRICW *otm;
1070 HRESULT hr;
1071 HFONT hfont;
1072 HDC hdc;
1073 int ret;
1075 *font = NULL;
1077 This = heap_alloc(sizeof(struct dwrite_font));
1078 if (!This) return E_OUTOFMEMORY;
1080 hfont = CreateFontIndirectW(logfont);
1081 if (!hfont)
1083 heap_free(This);
1084 return DWRITE_E_NOFONT;
1087 hdc = CreateCompatibleDC(0);
1088 SelectObject(hdc, hfont);
1090 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1091 otm = heap_alloc(ret);
1092 if (!otm)
1094 heap_free(This);
1095 DeleteDC(hdc);
1096 DeleteObject(hfont);
1097 return E_OUTOFMEMORY;
1099 otm->otmSize = ret;
1100 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1102 get_font_properties(This, hdc);
1104 DeleteDC(hdc);
1105 DeleteObject(hfont);
1107 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1108 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1109 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1111 hr = create_fontfamily(familyname, &family);
1112 heap_free(otm);
1113 if (hr != S_OK)
1115 heap_free(This);
1116 return hr;
1119 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
1120 This->ref = 1;
1121 This->face = NULL;
1122 This->is_system = TRUE;
1123 This->family = family;
1124 This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
1125 This->facename = heap_strdupW(logfont->lfFaceName);
1127 *font = &This->IDWriteFont_iface;
1129 return S_OK;
1132 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1134 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1136 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1138 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1140 *obj = iface;
1141 IDWriteFontFile_AddRef(iface);
1142 return S_OK;
1145 *obj = NULL;
1146 return E_NOINTERFACE;
1149 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1151 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1152 ULONG ref = InterlockedIncrement(&This->ref);
1153 TRACE("(%p)->(%d)\n", This, ref);
1154 return ref;
1157 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1159 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1160 ULONG ref = InterlockedDecrement(&This->ref);
1162 TRACE("(%p)->(%d)\n", This, ref);
1164 if (!ref)
1166 IDWriteFontFileLoader_Release(This->loader);
1167 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1168 heap_free(This->reference_key);
1169 heap_free(This);
1172 return ref;
1175 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1177 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1178 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1179 *fontFileReferenceKey = This->reference_key;
1180 *fontFileReferenceKeySize = This->key_size;
1182 return S_OK;
1185 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1187 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1188 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1189 *fontFileLoader = This->loader;
1190 IDWriteFontFileLoader_AddRef(This->loader);
1192 return S_OK;
1195 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1197 HRESULT hr;
1198 const void *font_data;
1199 void *context;
1200 IDWriteFontFileStream *stream;
1202 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1203 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1205 *isSupportedFontType = FALSE;
1206 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1207 if (fontFaceType)
1208 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1209 *numberOfFaces = 0;
1211 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1212 if (FAILED(hr))
1213 return S_OK;
1214 hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, 28, &context);
1215 if (SUCCEEDED(hr))
1217 hr = analyze_opentype_font(font_data, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1218 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1220 /* TODO: Further Analysis */
1221 IDWriteFontFileStream_Release(stream);
1222 return S_OK;
1225 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1226 dwritefontfile_QueryInterface,
1227 dwritefontfile_AddRef,
1228 dwritefontfile_Release,
1229 dwritefontfile_GetReferenceKey,
1230 dwritefontfile_GetLoader,
1231 dwritefontfile_Analyze,
1234 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1236 struct dwrite_fontfile *This;
1238 This = heap_alloc(sizeof(struct dwrite_fontfile));
1239 if (!This) return E_OUTOFMEMORY;
1241 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1242 This->ref = 1;
1243 IDWriteFontFileLoader_AddRef(loader);
1244 This->loader = loader;
1245 This->stream = NULL;
1246 This->reference_key = heap_alloc(key_size);
1247 memcpy(This->reference_key, reference_key, key_size);
1248 This->key_size = key_size;
1250 *font_file = &This->IDWriteFontFile_iface;
1252 return S_OK;
1255 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)
1257 int i;
1258 struct dwrite_fontface *This;
1259 HRESULT hr = S_OK;
1261 *font_face = NULL;
1263 This = heap_alloc(sizeof(struct dwrite_fontface));
1264 if (!This) return E_OUTOFMEMORY;
1266 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
1267 This->ref = 1;
1268 This->type = facetype;
1269 This->file_count = files_number;
1270 This->files = heap_alloc(sizeof(*This->files) * files_number);
1271 /* Verify font file streams */
1272 for (i = 0; i < This->file_count && SUCCEEDED(hr); i++)
1274 IDWriteFontFileStream *stream;
1275 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1276 if (SUCCEEDED(hr))
1277 IDWriteFontFileStream_Release(stream);
1279 if (FAILED(hr))
1281 heap_free(This->files);
1282 heap_free(This);
1283 return hr;
1285 for (i = 0; i < This->file_count; i++)
1287 This->files[i] = font_files[i];
1288 IDWriteFontFile_AddRef(font_files[i]);
1291 This->index = index;
1292 This->simulations = sim_flags;
1293 This->is_system = FALSE;
1295 *font_face = &This->IDWriteFontFace_iface;
1297 return S_OK;
1300 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1302 struct dwrite_localfontfilestream
1304 IDWriteFontFileStream IDWriteFontFileStream_iface;
1305 LONG ref;
1307 HANDLE handle;
1310 struct dwrite_localfontfileloader {
1311 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1312 LONG ref;
1315 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1317 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1320 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1322 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1325 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1327 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1328 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1329 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1331 *obj = iface;
1332 IDWriteFontFileStream_AddRef(iface);
1333 return S_OK;
1336 *obj = NULL;
1337 return E_NOINTERFACE;
1340 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1342 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1343 ULONG ref = InterlockedIncrement(&This->ref);
1344 TRACE("(%p)->(%d)\n", This, ref);
1345 return ref;
1348 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1350 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1351 ULONG ref = InterlockedDecrement(&This->ref);
1353 TRACE("(%p)->(%d)\n", This, ref);
1355 if (!ref)
1357 if (This->handle != INVALID_HANDLE_VALUE)
1358 CloseHandle(This->handle);
1359 heap_free(This);
1362 return ref;
1365 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1367 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1368 LARGE_INTEGER distance;
1369 DWORD bytes = fragment_size;
1370 DWORD read;
1372 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1373 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1375 *fragment_context = NULL;
1376 distance.QuadPart = offset;
1377 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1378 return E_FAIL;
1379 *fragment_start = *fragment_context = heap_alloc(bytes);
1380 if (!*fragment_context)
1381 return E_FAIL;
1382 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1384 heap_free(*fragment_context);
1385 return E_FAIL;
1388 return S_OK;
1391 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1393 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1394 TRACE("(%p)->(%p)\n", This, fragment_context);
1395 heap_free(fragment_context);
1398 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1400 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1401 LARGE_INTEGER li;
1402 TRACE("(%p)->(%p)\n",This, size);
1403 GetFileSizeEx(This->handle, &li);
1404 *size = li.QuadPart;
1405 return S_OK;
1408 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1410 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1411 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1412 *last_writetime = 0;
1413 return E_NOTIMPL;
1416 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1418 localfontfilestream_QueryInterface,
1419 localfontfilestream_AddRef,
1420 localfontfilestream_Release,
1421 localfontfilestream_ReadFileFragment,
1422 localfontfilestream_ReleaseFileFragment,
1423 localfontfilestream_GetFileSize,
1424 localfontfilestream_GetLastWriteTime
1427 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1429 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1430 if (!This)
1431 return E_OUTOFMEMORY;
1433 This->ref = 1;
1434 This->handle = handle;
1435 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1437 *iface = &This->IDWriteFontFileStream_iface;
1438 return S_OK;
1441 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1443 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1445 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1447 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1449 *obj = iface;
1450 IDWriteLocalFontFileLoader_AddRef(iface);
1451 return S_OK;
1454 *obj = NULL;
1455 return E_NOINTERFACE;
1458 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1460 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1461 ULONG ref = InterlockedIncrement(&This->ref);
1462 TRACE("(%p)->(%d)\n", This, ref);
1463 return ref;
1466 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1468 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1469 ULONG ref = InterlockedDecrement(&This->ref);
1471 TRACE("(%p)->(%d)\n", This, ref);
1473 if (!ref)
1474 heap_free(This);
1476 return ref;
1479 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1481 HANDLE handle;
1482 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1483 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1485 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1487 TRACE("name: %s\n",debugstr_w(name));
1488 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1489 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1491 if (handle == INVALID_HANDLE_VALUE)
1492 return E_FAIL;
1494 return create_localfontfilestream(handle, fontFileStream);
1497 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1499 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1500 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1501 *length = key_size;
1502 return S_OK;
1505 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1507 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1508 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1509 if (length < key_size)
1510 return E_INVALIDARG;
1511 lstrcpynW((WCHAR*)key, path, key_size);
1512 return S_OK;
1515 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1517 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1518 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1519 return E_NOTIMPL;
1522 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1523 localfontfileloader_QueryInterface,
1524 localfontfileloader_AddRef,
1525 localfontfileloader_Release,
1526 localfontfileloader_CreateStreamFromKey,
1527 localfontfileloader_GetFilePathLengthFromKey,
1528 localfontfileloader_GetFilePathFromKey,
1529 localfontfileloader_GetLastWriteTimeFromKey
1532 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1534 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1535 if (!This)
1536 return E_OUTOFMEMORY;
1538 This->ref = 1;
1539 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1541 *iface = &This->IDWriteLocalFontFileLoader_iface;
1542 return S_OK;