diff --git a/dlls/dwrite/Makefile.in b/dlls/dwrite/Makefile.in index 9ee7181c3ca..c71441965ae 100644 --- a/dlls/dwrite/Makefile.in +++ b/dlls/dwrite/Makefile.in @@ -7,4 +7,5 @@ C_SRCS = \ font.c \ gdiinterop.c \ layout.c \ - main.c + main.c \ + opentype.c diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index fcc9b7fdf22..64f55e2789e 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -90,3 +90,6 @@ extern HRESULT get_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDE extern void release_system_fontcollection(void) DECLSPEC_HIDDEN; extern HRESULT get_textanalyzer(IDWriteTextAnalyzer**) DECLSPEC_HIDDEN; extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN; + +/* Opentype font table functions */ +extern HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index afeca276612..0c75271b085 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -1057,9 +1057,32 @@ static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFo static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces) { + HRESULT hr; + const void *font_data; + void *context; + IDWriteFontFileStream *stream; + struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface); FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces); - return E_NOTIMPL; + + *isSupportedFontType = FALSE; + *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN; + if (fontFaceType) + *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN; + *numberOfFaces = 0; + + hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream); + if (FAILED(hr)) + return S_OK; + hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, 28, &context); + if (SUCCEEDED(hr)) + { + hr = analyze_opentype_font(font_data, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType); + IDWriteFontFileStream_ReleaseFileFragment(stream, context); + } + /* TODO: Further Analysis */ + IDWriteFontFileStream_Release(stream); + return S_OK; } static const IDWriteFontFileVtbl dwritefontfilevtbl = { diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c new file mode 100644 index 00000000000..538db987efa --- /dev/null +++ b/dlls/dwrite/opentype.c @@ -0,0 +1,83 @@ +/* + * Methods for dealing with opentype font tables + * + * Copyright 2014 Aric Stewart for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dwrite.h" +#include "dwrite_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dwrite); + +#define DWRITE_MAKE_OPENTYPE_TAG(ch0, ch1, ch2, ch3) \ + ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ + ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24)) + +#define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f') +#define MS_OTTO_TAG DWRITE_MAKE_OPENTYPE_TAG('O','T','T','O') + +#ifdef WORDS_BIGENDIAN +#define GET_BE_WORD(x) (x) +#define GET_BE_DWORD(x) (x) +#else +#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x)) +#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x))) +#endif + +typedef struct { + CHAR TTCTag[4]; + DWORD Version; + DWORD numFonts; + DWORD OffsetTable[1]; +} TTC_Header_V1; + +HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported) +{ + /* TODO: Do font validation */ + const char* tag = font_data; + + *supported = FALSE; + *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN; + if (face_type) + *face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN; + *font_count = 0; + + if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_TTCF_TAG) + { + const TTC_Header_V1 *header = font_data; + *font_count = GET_BE_DWORD(header->numFonts); + *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION; + if (face_type) + *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION; + *supported = TRUE; + } + else if (GET_BE_DWORD(*(DWORD*)font_data) == 0x10000) + { + *font_count = 1; + *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE; + if (face_type) + *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE; + *supported = TRUE; + } + else if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_OTTO_TAG) + { + *file_type = DWRITE_FONT_FILE_TYPE_CFF; + } + return S_OK; +} diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 4368bcf9e01..44e7ee69b5f 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -763,6 +763,10 @@ static void test_FontLoader(void) IDWriteFontFileLoader floader2 = { &dwritefontfileloadervtbl }; IDWriteFontFileLoader floader3 = { &dwritefontfileloadervtbl }; IDWriteFontFile *ffile = NULL; + BOOL support = 1; + DWRITE_FONT_FILE_TYPE type = 1; + DWRITE_FONT_FACE_TYPE face = 1; + UINT32 count = 1; HRESULT hr; hr = IDWriteFactory_RegisterFontFileLoader(factory, NULL); @@ -789,6 +793,16 @@ static void test_FontLoader(void) if (SUCCEEDED(hr)) IDWriteFontFile_Release(ffile); + hr = IDWriteFactory_CreateCustomFontFileReference(factory, "test", 4, &floader, &ffile); + ok(hr == S_OK, "got 0x%08x\n", hr); + IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(support == FALSE, "got %i\n", support); + ok(type == DWRITE_FONT_FILE_TYPE_UNKNOWN, "got %i\n", type); + ok(face == DWRITE_FONT_FACE_TYPE_UNKNOWN, "got %i\n", face); + ok(count == 0, "got %i\n", count); + IDWriteFontFile_Release(ffile); + hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDWriteFactory_UnregisterFontFileLoader(factory, &floader);