2 * Methods for dealing with opentype font tables
4 * Copyright 2014 Aric Stewart 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
24 #include "dwrite_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dwrite
);
28 #define DWRITE_MAKE_OPENTYPE_TAG(ch0, ch1, ch2, ch3) \
29 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
30 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
32 #define MS_TTCF_TAG DWRITE_MAKE_OPENTYPE_TAG('t','t','c','f')
33 #define MS_OTTO_TAG DWRITE_MAKE_OPENTYPE_TAG('O','T','T','O')
35 #ifdef WORDS_BIGENDIAN
36 #define GET_BE_WORD(x) (x)
37 #define GET_BE_DWORD(x) (x)
39 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
40 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)))
65 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
)
67 /* TODO: Do font validation */
68 const char* tag
= font_data
;
71 *file_type
= DWRITE_FONT_FILE_TYPE_UNKNOWN
;
73 *face_type
= DWRITE_FONT_FACE_TYPE_UNKNOWN
;
76 if (DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]) == MS_TTCF_TAG
)
78 const TTC_Header_V1
*header
= font_data
;
79 *font_count
= GET_BE_DWORD(header
->numFonts
);
80 *file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION
;
82 *face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION
;
85 else if (GET_BE_DWORD(*(DWORD
*)font_data
) == 0x10000)
88 *file_type
= DWRITE_FONT_FILE_TYPE_TRUETYPE
;
90 *face_type
= DWRITE_FONT_FACE_TYPE_TRUETYPE
;
93 else if (DWRITE_MAKE_OPENTYPE_TAG(tag
[0], tag
[1], tag
[2], tag
[3]) == MS_OTTO_TAG
)
95 *file_type
= DWRITE_FONT_FILE_TYPE_CFF
;
100 HRESULT
find_font_table(IDWriteFontFileStream
*stream
, UINT32 font_index
, UINT32 tag
, const void** table_data
, void** table_context
, UINT32
*table_size
, BOOL
* found
)
102 const CHAR
*first_data
;
105 TTC_SFNT_V1
*font_header
= NULL
;
107 TT_TableRecord
*table_record
= NULL
;
108 void *table_record_context
;
111 int table_offset
= 0;
115 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&first_data
, 0, 4, &first_context
);
118 if (DWRITE_MAKE_OPENTYPE_TAG(first_data
[0], first_data
[1], first_data
[2], first_data
[3]) == MS_TTCF_TAG
)
120 const TTC_Header_V1
*ttc_header
;
122 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&ttc_header
, 0, sizeof(*ttc_header
), &ttc_context
);
125 table_offset
= GET_BE_DWORD(ttc_header
->OffsetTable
[0]);
126 if (font_index
>= GET_BE_DWORD(ttc_header
->numFonts
))
129 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&font_header
, table_offset
, sizeof(*font_header
), &sfnt_context
);
130 IDWriteFontFileStream_ReleaseFileFragment(stream
, ttc_context
);
138 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&font_header
, 0, sizeof(*font_header
), &sfnt_context
);
140 IDWriteFontFileStream_ReleaseFileFragment(stream
, first_context
);
145 table_count
= GET_BE_WORD(font_header
->numTables
);
146 table_offset
+= sizeof(*font_header
);
147 for (i
= 0; i
< table_count
; i
++)
149 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, (const void**)&table_record
, table_offset
, sizeof(*table_record
), &table_record_context
);
152 if (DWRITE_MAKE_OPENTYPE_TAG(table_record
->tag
[0], table_record
->tag
[1], table_record
->tag
[2], table_record
->tag
[3]) == tag
)
154 IDWriteFontFileStream_ReleaseFileFragment(stream
, table_record_context
);
155 table_offset
+= sizeof(*table_record
);
158 IDWriteFontFileStream_ReleaseFileFragment(stream
, sfnt_context
);
159 if (SUCCEEDED(hr
) && i
< table_count
)
161 int offset
= GET_BE_DWORD(table_record
->offset
);
162 int length
= GET_BE_DWORD(table_record
->length
);
163 IDWriteFontFileStream_ReleaseFileFragment(stream
, table_record_context
);
166 *table_size
= length
;
167 hr
= IDWriteFontFileStream_ReadFileFragment(stream
, table_data
, offset
, length
, table_context
);