blob: 908a8c1ec6649838973d32507a45ab33b5b3cb8e [file] [log] [blame]
Werner Lemberg9ac90602018-06-03 09:01:17 +02001/****************************************************************************
2 *
3 * sfobjs.c
4 *
5 * SFNT object management (base).
6 *
Werner Lemberg75859972019-02-23 10:07:09 +01007 * Copyright (C) 1996-2019 by
Werner Lemberg9ac90602018-06-03 09:01:17 +02008 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
Werner Lemberg4e6dd852000-06-05 05:26:15 +000017
Werner Lembergcc069be2000-12-08 16:17:16 +000018
19#include <ft2build.h>
David Turner8d3a4012001-03-20 11:14:24 +000020#include "sfobjs.h"
21#include "ttload.h"
Werner Lemberg4b8397c2004-08-29 16:50:09 +000022#include "ttcmap.h"
David Turnere5680272005-02-26 00:12:04 +000023#include "ttkern.h"
Nikhil Ramakrishnan7b275a52019-05-30 23:57:34 +053024#include "sfwoff.h"
Werner Lembergcc069be2000-12-08 16:17:16 +000025#include FT_INTERNAL_SFNT_H
Werner Lemberg52254022006-02-15 06:05:52 +000026#include FT_INTERNAL_DEBUG_H
David Turner6ce03ef2001-03-20 14:50:04 +000027#include FT_TRUETYPE_IDS_H
Werner Lembergcc069be2000-12-08 16:17:16 +000028#include FT_TRUETYPE_TAGS_H
David Turner77605952003-10-29 21:43:52 +000029#include FT_SERVICE_POSTSCRIPT_CMAPS_H
suzuki toshiya75852ed2010-01-29 23:18:34 +090030#include FT_SFNT_NAMES_H
Werner Lembergc628a7d2016-12-14 19:31:42 +010031
32#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
33#include FT_SERVICE_MULTIPLE_MASTERS_H
Werner Lemberg09183252016-12-14 20:44:11 +010034#include FT_SERVICE_METRICS_VARIATIONS_H
Werner Lembergc628a7d2016-12-14 19:31:42 +010035#endif
36
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000037#include "sferrors.h"
David Turner241e1512000-05-28 17:15:37 +000038
David Turner89a2a4b2005-12-14 20:38:15 +000039#ifdef TT_CONFIG_OPTION_BDF
40#include "ttbdf.h"
41#endif
Werner Lemberg4e6dd852000-06-05 05:26:15 +000042
Werner Lembergb79b5132005-12-20 12:01:58 +000043
Werner Lemberg9ac90602018-06-03 09:01:17 +020044 /**************************************************************************
45 *
46 * The macro FT_COMPONENT is used in trace mode. It is an implicit
47 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
48 * messages during execution.
49 */
Werner Lemberg78575dc2000-06-12 19:36:41 +000050#undef FT_COMPONENT
Werner Lemberga0dd16f2018-08-15 18:13:17 +020051#define FT_COMPONENT sfobjs
Werner Lemberg78575dc2000-06-12 19:36:41 +000052
53
David Turner56054f32002-03-30 16:32:47 +000054
Werner Lembergb7b163c2002-03-31 18:48:24 +000055 /* convert a UTF-16 name entry to ASCII */
David Turner56054f32002-03-30 16:32:47 +000056 static FT_String*
Werner Lembergf4e56962017-01-25 15:08:41 +010057 tt_name_ascii_from_utf16( TT_Name entry,
58 FT_Memory memory )
David Turner56054f32002-03-30 16:32:47 +000059 {
Werner Lembergc8f5b982010-07-12 21:13:22 +020060 FT_String* string = NULL;
David Turner56054f32002-03-30 16:32:47 +000061 FT_UInt len, code, n;
Werner Lembergc8f5b982010-07-12 21:13:22 +020062 FT_Byte* read = (FT_Byte*)entry->string;
Werner Lembergbe3c9812006-01-27 14:16:16 +000063 FT_Error error;
Werner Lembergb7b163c2002-03-31 18:48:24 +000064
65
66 len = (FT_UInt)entry->stringLength / 2;
67
David Turner6a681fa2006-01-27 12:11:22 +000068 if ( FT_NEW_ARRAY( string, len + 1 ) )
David Turner56054f32002-03-30 16:32:47 +000069 return NULL;
Werner Lembergb7b163c2002-03-31 18:48:24 +000070
David Turner56054f32002-03-30 16:32:47 +000071 for ( n = 0; n < len; n++ )
72 {
Werner Lembergb7b163c2002-03-31 18:48:24 +000073 code = FT_NEXT_USHORT( read );
Huw Davies3650f802012-03-14 18:29:57 +010074
75 if ( code == 0 )
76 break;
77
78 if ( code < 32 || code > 127 )
David Turner56054f32002-03-30 16:32:47 +000079 code = '?';
Werner Lembergb7b163c2002-03-31 18:48:24 +000080
David Turner56054f32002-03-30 16:32:47 +000081 string[n] = (char)code;
82 }
83
Huw Davies3650f802012-03-14 18:29:57 +010084 string[n] = 0;
Werner Lembergb7b163c2002-03-31 18:48:24 +000085
David Turner56054f32002-03-30 16:32:47 +000086 return string;
Werner Lembergb7b163c2002-03-31 18:48:24 +000087 }
David Turner56054f32002-03-30 16:32:47 +000088
89
Werner Lembergb7b163c2002-03-31 18:48:24 +000090 /* convert an Apple Roman or symbol name entry to ASCII */
David Turner56054f32002-03-30 16:32:47 +000091 static FT_String*
Werner Lembergf4e56962017-01-25 15:08:41 +010092 tt_name_ascii_from_other( TT_Name entry,
93 FT_Memory memory )
David Turner56054f32002-03-30 16:32:47 +000094 {
Werner Lembergc8f5b982010-07-12 21:13:22 +020095 FT_String* string = NULL;
David Turner56054f32002-03-30 16:32:47 +000096 FT_UInt len, code, n;
Werner Lembergc8f5b982010-07-12 21:13:22 +020097 FT_Byte* read = (FT_Byte*)entry->string;
Werner Lembergbe3c9812006-01-27 14:16:16 +000098 FT_Error error;
Werner Lembergb7b163c2002-03-31 18:48:24 +000099
100
101 len = (FT_UInt)entry->stringLength;
102
David Turner6a681fa2006-01-27 12:11:22 +0000103 if ( FT_NEW_ARRAY( string, len + 1 ) )
David Turner56054f32002-03-30 16:32:47 +0000104 return NULL;
Werner Lembergb7b163c2002-03-31 18:48:24 +0000105
David Turner56054f32002-03-30 16:32:47 +0000106 for ( n = 0; n < len; n++ )
107 {
108 code = *read++;
Huw Davies3650f802012-03-14 18:29:57 +0100109
110 if ( code == 0 )
111 break;
112
113 if ( code < 32 || code > 127 )
David Turner56054f32002-03-30 16:32:47 +0000114 code = '?';
Werner Lembergb7b163c2002-03-31 18:48:24 +0000115
David Turner56054f32002-03-30 16:32:47 +0000116 string[n] = (char)code;
117 }
118
Huw Davies3650f802012-03-14 18:29:57 +0100119 string[n] = 0;
Werner Lembergb7b163c2002-03-31 18:48:24 +0000120
David Turner56054f32002-03-30 16:32:47 +0000121 return string;
Werner Lembergb7b163c2002-03-31 18:48:24 +0000122 }
David Turner56054f32002-03-30 16:32:47 +0000123
124
Werner Lembergf4e56962017-01-25 15:08:41 +0100125 typedef FT_String* (*TT_Name_ConvertFunc)( TT_Name entry,
126 FT_Memory memory );
David Turner791d83a2002-05-27 23:52:01 +0000127
Werner Lemberg877ff672002-05-28 06:03:10 +0000128
Werner Lemberg1cdac102015-07-07 14:04:44 +0200129 /* documentation is in sfnt.h */
130
131 FT_LOCAL_DEF( FT_Error )
Werner Lemberg95120922008-11-08 07:20:25 +0000132 tt_face_get_name( TT_Face face,
133 FT_UShort nameid,
134 FT_String** name )
David Turner241e1512000-05-28 17:15:37 +0000135 {
Werner Lembergf4e56962017-01-25 15:08:41 +0100136 FT_Memory memory = face->root.memory;
137 FT_Error error = FT_Err_Ok;
138 FT_String* result = NULL;
139 FT_UShort n;
140 TT_Name rec;
David Turner241e1512000-05-28 17:15:37 +0000141
Werner Lembergf4e56962017-01-25 15:08:41 +0100142 FT_Int found_apple = -1;
143 FT_Int found_apple_roman = -1;
144 FT_Int found_apple_english = -1;
145 FT_Int found_win = -1;
146 FT_Int found_unicode = -1;
Werner Lemberge9920c62004-06-02 21:22:32 +0000147
Werner Lembergf4e56962017-01-25 15:08:41 +0100148 FT_Bool is_english = 0;
149
150 TT_Name_ConvertFunc convert;
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000151
Werner Lemberg877ff672002-05-28 06:03:10 +0000152
Werner Lemberg95120922008-11-08 07:20:25 +0000153 FT_ASSERT( name );
154
David Turner241e1512000-05-28 17:15:37 +0000155 rec = face->name_table.names;
David Turnerdf689c22002-05-01 08:36:12 +0000156 for ( n = 0; n < face->num_names; n++, rec++ )
David Turner241e1512000-05-28 17:15:37 +0000157 {
Werner Lembergb7b163c2002-03-31 18:48:24 +0000158 /* According to the OpenType 1.3 specification, only Microsoft or */
159 /* Apple platform IDs might be used in the `name' table. The */
160 /* `Unicode' platform is reserved for the `cmap' table, and the */
suzuki toshiya1e2a4462010-07-09 12:25:59 +0900161 /* `ISO' one is deprecated. */
Werner Lembergb7b163c2002-03-31 18:48:24 +0000162 /* */
163 /* However, the Apple TrueType specification doesn't say the same */
164 /* thing and goes to suggest that all Unicode `name' table entries */
165 /* should be coded in UTF-16 (in big-endian format I suppose). */
David Turner56054f32002-03-30 16:32:47 +0000166 /* */
David Turner791d83a2002-05-27 23:52:01 +0000167 if ( rec->nameID == nameid && rec->stringLength > 0 )
David Turner241e1512000-05-28 17:15:37 +0000168 {
David Turner28ea6f62002-03-05 16:12:57 +0000169 switch ( rec->platformID )
David Turner241e1512000-05-28 17:15:37 +0000170 {
Werner Lembergb7b163c2002-03-31 18:48:24 +0000171 case TT_PLATFORM_APPLE_UNICODE:
172 case TT_PLATFORM_ISO:
173 /* there is `languageID' to check there. We should use this */
174 /* field only as a last solution when nothing else is */
175 /* available. */
176 /* */
177 found_unicode = n;
178 break;
David Turner56054f32002-03-30 16:32:47 +0000179
Werner Lembergb7b163c2002-03-31 18:48:24 +0000180 case TT_PLATFORM_MACINTOSH:
Werner Lembergf9644552006-09-12 13:48:10 +0000181 /* This is a bit special because some fonts will use either */
182 /* an English language id, or a Roman encoding id, to indicate */
183 /* the English version of its font name. */
184 /* */
Werner Lembergb7b163c2002-03-31 18:48:24 +0000185 if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
David Turnerf3050052006-09-11 12:00:32 +0000186 found_apple_english = n;
187 else if ( rec->encodingID == TT_MAC_ID_ROMAN )
188 found_apple_roman = n;
Werner Lembergb7b163c2002-03-31 18:48:24 +0000189 break;
190
191 case TT_PLATFORM_MICROSOFT:
192 /* we only take a non-English name when there is nothing */
193 /* else available in the font */
194 /* */
195 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
196 {
197 switch ( rec->encodingID )
David Turner28ea6f62002-03-05 16:12:57 +0000198 {
Werner Lembergb7b163c2002-03-31 18:48:24 +0000199 case TT_MS_ID_SYMBOL_CS:
200 case TT_MS_ID_UNICODE_CS:
201 case TT_MS_ID_UCS_4:
Werner Lemberg22ad9ef2005-05-09 22:11:36 +0000202 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
Werner Lemberge9920c62004-06-02 21:22:32 +0000203 found_win = n;
David Turner28ea6f62002-03-05 16:12:57 +0000204 break;
Werner Lembergb7b163c2002-03-31 18:48:24 +0000205
206 default:
207 ;
David Turner28ea6f62002-03-05 16:12:57 +0000208 }
Werner Lembergb7b163c2002-03-31 18:48:24 +0000209 }
210 break;
211
212 default:
213 ;
David Turner241e1512000-05-28 17:15:37 +0000214 }
215 }
216 }
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000217
David Turnerf3050052006-09-11 12:00:32 +0000218 found_apple = found_apple_roman;
219 if ( found_apple_english >= 0 )
220 found_apple = found_apple_english;
221
Werner Lembergb7b163c2002-03-31 18:48:24 +0000222 /* some fonts contain invalid Unicode or Macintosh formatted entries; */
223 /* we will thus favor names encoded in Windows formats if available */
Werner Lemberge9920c62004-06-02 21:22:32 +0000224 /* (provided it is an English name) */
Werner Lembergb7b163c2002-03-31 18:48:24 +0000225 /* */
David Turner791d83a2002-05-27 23:52:01 +0000226 convert = NULL;
Werner Lemberge9920c62004-06-02 21:22:32 +0000227 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
David Turner28ea6f62002-03-05 16:12:57 +0000228 {
David Turner56054f32002-03-30 16:32:47 +0000229 rec = face->name_table.names + found_win;
230 switch ( rec->encodingID )
231 {
Werner Lemberg960ba592006-12-01 08:20:47 +0000232 /* all Unicode strings are encoded using UTF-16BE */
Werner Lembergb7b163c2002-03-31 18:48:24 +0000233 case TT_MS_ID_UNICODE_CS:
234 case TT_MS_ID_SYMBOL_CS:
Werner Lembergf4e56962017-01-25 15:08:41 +0100235 convert = tt_name_ascii_from_utf16;
David Turner9207e002007-01-02 16:58:13 +0000236 break;
237
Werner Lembergb7b163c2002-03-31 18:48:24 +0000238 case TT_MS_ID_UCS_4:
Werner Lemberg6b87e6f2007-01-02 19:20:08 +0000239 /* Apparently, if this value is found in a name table entry, it is */
240 /* documented as `full Unicode repertoire'. Experience with the */
241 /* MsGothic font shipped with Windows Vista shows that this really */
242 /* means UTF-16 encoded names (UCS-4 values are only used within */
243 /* charmaps). */
Werner Lembergf4e56962017-01-25 15:08:41 +0100244 convert = tt_name_ascii_from_utf16;
Werner Lembergb7b163c2002-03-31 18:48:24 +0000245 break;
246
247 default:
248 ;
David Turner56054f32002-03-30 16:32:47 +0000249 }
David Turner28ea6f62002-03-05 16:12:57 +0000250 }
David Turner56054f32002-03-30 16:32:47 +0000251 else if ( found_apple >= 0 )
David Turner28ea6f62002-03-05 16:12:57 +0000252 {
David Turner791d83a2002-05-27 23:52:01 +0000253 rec = face->name_table.names + found_apple;
Werner Lembergf4e56962017-01-25 15:08:41 +0100254 convert = tt_name_ascii_from_other;
David Turner28ea6f62002-03-05 16:12:57 +0000255 }
David Turner56054f32002-03-30 16:32:47 +0000256 else if ( found_unicode >= 0 )
257 {
David Turner791d83a2002-05-27 23:52:01 +0000258 rec = face->name_table.names + found_unicode;
Werner Lembergf4e56962017-01-25 15:08:41 +0100259 convert = tt_name_ascii_from_utf16;
David Turner56054f32002-03-30 16:32:47 +0000260 }
Werner Lembergb7b163c2002-03-31 18:48:24 +0000261
David Turner791d83a2002-05-27 23:52:01 +0000262 if ( rec && convert )
263 {
Werner Lemberg4441f7b2016-12-26 17:08:17 +0100264 if ( !rec->string )
David Turner791d83a2002-05-27 23:52:01 +0000265 {
David Turner791d83a2002-05-27 23:52:01 +0000266 FT_Stream stream = face->name_table.stream;
267
268
David Turner5290d2f2004-06-23 15:44:03 +0000269 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
David Turner791d83a2002-05-27 23:52:01 +0000270 FT_STREAM_SEEK( rec->stringOffset ) ||
271 FT_STREAM_READ( rec->string, rec->stringLength ) )
272 {
273 FT_FREE( rec->string );
274 rec->stringLength = 0;
275 result = NULL;
276 goto Exit;
277 }
278 }
279
280 result = convert( rec, memory );
281 }
282
283 Exit:
Werner Lemberg95120922008-11-08 07:20:25 +0000284 *name = result;
285 return error;
David Turner241e1512000-05-28 17:15:37 +0000286 }
287
288
Werner Lemberg52005c32001-06-27 23:25:46 +0000289 static FT_Encoding
David Turnerfd88e7c2002-03-22 15:02:38 +0000290 sfnt_find_encoding( int platform_id,
291 int encoding_id )
David Turner241e1512000-05-28 17:15:37 +0000292 {
Werner Lemberg2b0b4222008-05-28 22:17:28 +0000293 typedef struct TEncoding_
David Turner241e1512000-05-28 17:15:37 +0000294 {
295 int platform_id;
296 int encoding_id;
297 FT_Encoding encoding;
298
299 } TEncoding;
300
Werner Lemberga8bbc262000-07-01 14:06:46 +0000301 static
302 const TEncoding tt_encodings[] =
David Turner241e1512000-05-28 17:15:37 +0000303 {
David Turnerb08fe2d2002-08-27 20:20:29 +0000304 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE },
David Turner241e1512000-05-28 17:15:37 +0000305
David Turnerb08fe2d2002-08-27 20:20:29 +0000306 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE },
David Turner241e1512000-05-28 17:15:37 +0000307
David Turnerb08fe2d2002-08-27 20:20:29 +0000308 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN },
David Turner241e1512000-05-28 17:15:37 +0000309
David Turnerb08fe2d2002-08-27 20:20:29 +0000310 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL },
311 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE },
312 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
Werner Lemberged2a8df2003-09-01 07:06:06 +0000313 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS },
Werner Lemberg464b16b2017-01-27 08:45:46 +0100314 { TT_PLATFORM_MICROSOFT, TT_MS_ID_PRC, FT_ENCODING_PRC },
Werner Lemberged2a8df2003-09-01 07:06:06 +0000315 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 },
316 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG },
317 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB }
David Turner241e1512000-05-28 17:15:37 +0000318 };
319
320 const TEncoding *cur, *limit;
321
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000322
David Turner241e1512000-05-28 17:15:37 +0000323 cur = tt_encodings;
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000324 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
David Turner241e1512000-05-28 17:15:37 +0000325
326 for ( ; cur < limit; cur++ )
327 {
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000328 if ( cur->platform_id == platform_id )
David Turner241e1512000-05-28 17:15:37 +0000329 {
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000330 if ( cur->encoding_id == encoding_id ||
331 cur->encoding_id == -1 )
David Turner241e1512000-05-28 17:15:37 +0000332 return cur->encoding;
333 }
334 }
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000335
David Turnerb08fe2d2002-08-27 20:20:29 +0000336 return FT_ENCODING_NONE;
David Turner241e1512000-05-28 17:15:37 +0000337 }
338
339
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000340 /* Fill in face->ttc_header. If the font is not a TTC, it is */
341 /* synthesized into a TTC with one offset table. */
342 static FT_Error
343 sfnt_open_font( FT_Stream stream,
344 TT_Face face )
345 {
346 FT_Memory memory = stream->memory;
347 FT_Error error;
348 FT_ULong tag, offset;
349
350 static const FT_Frame_Field ttc_header_fields[] =
351 {
352#undef FT_STRUCTURE
353#define FT_STRUCTURE TTC_HeaderRec
354
355 FT_FRAME_START( 8 ),
356 FT_FRAME_LONG( version ),
Werner Lembergaf7b8b12011-03-20 07:51:57 +0100357 FT_FRAME_LONG( count ), /* this is ULong in the specs */
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000358 FT_FRAME_END
359 };
360
361
362 face->ttc_header.tag = 0;
363 face->ttc_header.version = 0;
364 face->ttc_header.count = 0;
365
Werner Lembergd689d1c2013-08-29 17:53:40 +0200366 retry:
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000367 offset = FT_STREAM_POS();
368
369 if ( FT_READ_ULONG( tag ) )
370 return error;
371
Werner Lembergd689d1c2013-08-29 17:53:40 +0200372 if ( tag == TTAG_wOFF )
373 {
374 FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
375
376 if ( FT_STREAM_SEEK( offset ) )
377 return error;
378
379 error = woff_open_font( stream, face );
380 if ( error )
381 return error;
382
383 /* Swap out stream and retry! */
384 stream = face->root.stream;
385 goto retry;
386 }
387
Werner Lemberg570b1fd2008-10-05 06:08:40 +0000388 if ( tag != 0x00010000UL &&
389 tag != TTAG_ttcf &&
390 tag != TTAG_OTTO &&
391 tag != TTAG_true &&
392 tag != TTAG_typ1 &&
suzuki toshiya5c4e40d2017-09-09 00:59:33 +0900393 tag != TTAG_0xA5kbd &&
394 tag != TTAG_0xA5lst &&
Werner Lemberg570b1fd2008-10-05 06:08:40 +0000395 tag != 0x00020000UL )
Werner Lemberg70cf8c52011-11-26 20:09:39 +0100396 {
397 FT_TRACE2(( " not a font using the SFNT container format\n" ));
Werner Lemberg059bc332013-03-14 10:27:35 +0100398 return FT_THROW( Unknown_File_Format );
Werner Lemberg70cf8c52011-11-26 20:09:39 +0100399 }
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000400
401 face->ttc_header.tag = TTAG_ttcf;
402
403 if ( tag == TTAG_ttcf )
404 {
405 FT_Int n;
406
407
408 FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
409
410 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
411 return error;
412
Werner Lemberg3b125e92016-12-17 10:02:19 +0100413 FT_TRACE3(( " with %ld subfonts\n",
414 face->ttc_header.count ));
415
Werner Lembergaf7b8b12011-03-20 07:51:57 +0100416 if ( face->ttc_header.count == 0 )
Werner Lemberg059bc332013-03-14 10:27:35 +0100417 return FT_THROW( Invalid_Table );
Werner Lembergaf7b8b12011-03-20 07:51:57 +0100418
419 /* a rough size estimate: let's conservatively assume that there */
420 /* is just a single table info in each subfont header (12 + 16*1 = */
421 /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */
422 /* size of the TTC header plus `28*count' bytes for all subfont */
423 /* headers */
424 if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
Werner Lemberg059bc332013-03-14 10:27:35 +0100425 return FT_THROW( Array_Too_Large );
Werner Lembergaf7b8b12011-03-20 07:51:57 +0100426
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000427 /* now read the offsets of each font in the file */
428 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
429 return error;
430
431 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
432 return error;
433
434 for ( n = 0; n < face->ttc_header.count; n++ )
435 face->ttc_header.offsets[n] = FT_GET_ULONG();
436
437 FT_FRAME_EXIT();
438 }
439 else
440 {
441 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
442
443 face->ttc_header.version = 1 << 16;
444 face->ttc_header.count = 1;
445
Werner Lembergc2cabd42009-02-09 22:20:27 +0000446 if ( FT_NEW( face->ttc_header.offsets ) )
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000447 return error;
448
449 face->ttc_header.offsets[0] = offset;
450 }
451
452 return error;
453 }
454
455
David Turnerbc82f1b2002-03-01 02:26:22 +0000456 FT_LOCAL_DEF( FT_Error )
David Turnerb08fe2d2002-08-27 20:20:29 +0000457 sfnt_init_face( FT_Stream stream,
Werner Lemberg52005c32001-06-27 23:25:46 +0000458 TT_Face face,
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200459 FT_Int face_instance_index,
Werner Lemberg52005c32001-06-27 23:25:46 +0000460 FT_Int num_params,
461 FT_Parameter* params )
David Turner241e1512000-05-28 17:15:37 +0000462 {
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200463 FT_Error error;
464 FT_Library library = face->root.driver->root.library;
465 SFNT_Service sfnt;
466 FT_Int face_index;
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000467
David Turner241e1512000-05-28 17:15:37 +0000468
469 /* for now, parameters are unused */
David Turnerc6a92202000-07-04 18:12:13 +0000470 FT_UNUSED( num_params );
471 FT_UNUSED( params );
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000472
Werner Lembergb7b163c2002-03-31 18:48:24 +0000473
David Turner4e7eeee2002-02-28 16:10:29 +0000474 sfnt = (SFNT_Service)face->sfnt;
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000475 if ( !sfnt )
David Turner241e1512000-05-28 17:15:37 +0000476 {
David Turner4e7eeee2002-02-28 16:10:29 +0000477 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000478 if ( !sfnt )
Werner Lemberg930e9bf2011-11-26 13:38:26 +0100479 {
480 FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" ));
Werner Lemberg059bc332013-03-14 10:27:35 +0100481 return FT_THROW( Missing_Module );
Werner Lemberg930e9bf2011-11-26 13:38:26 +0100482 }
David Turner241e1512000-05-28 17:15:37 +0000483
484 face->sfnt = sfnt;
485 face->goto_table = sfnt->goto_table;
486 }
487
David Turner77605952003-10-29 21:43:52 +0000488 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
David Turner241e1512000-05-28 17:15:37 +0000489
Werner Lembergc628a7d2016-12-14 19:31:42 +0100490#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
491 if ( !face->mm )
492 {
493 /* we want the MM interface from the `truetype' module only */
494 FT_Module tt_module = FT_Get_Module( library, "truetype" );
495
496
497 face->mm = ft_module_get_service( tt_module,
498 FT_SERVICE_ID_MULTI_MASTERS,
499 0 );
500 }
Werner Lemberg09183252016-12-14 20:44:11 +0100501
Seigo Nonaka14844ef2023-05-02 10:01:38 +0900502 if ( !face->tt_var )
Werner Lembergfa437d82017-01-31 23:06:38 +0100503 {
504 /* we want the metrics variations interface */
505 /* from the `truetype' module only */
506 FT_Module tt_module = FT_Get_Module( library, "truetype" );
507
508
Seigo Nonaka14844ef2023-05-02 10:01:38 +0900509 face->tt_var = ft_module_get_service( tt_module,
510 FT_SERVICE_ID_METRICS_VARIATIONS,
511 0 );
Werner Lembergfa437d82017-01-31 23:06:38 +0100512 }
Seigo Nonaka14844ef2023-05-02 10:01:38 +0900513
514 if ( !face->face_var )
515 face->face_var = ft_module_get_service(
516 &face->root.driver->root,
517 FT_SERVICE_ID_METRICS_VARIATIONS,
518 0 );
Werner Lembergc628a7d2016-12-14 19:31:42 +0100519#endif
520
Werner Lemberg70cf8c52011-11-26 20:09:39 +0100521 FT_TRACE2(( "SFNT driver\n" ));
522
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000523 error = sfnt_open_font( stream, face );
524 if ( error )
525 return error;
526
Werner Lembergd689d1c2013-08-29 17:53:40 +0200527 /* Stream may have changed in sfnt_open_font. */
528 stream = face->root.stream;
529
Werner Lemberg8ed53462018-07-25 22:07:22 +0200530 FT_TRACE2(( "sfnt_init_face: %08p (index %d)\n",
531 face,
532 face_instance_index ));
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000533
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200534 face_index = FT_ABS( face_instance_index ) & 0xFFFF;
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000535
Werner Lemberg63765a82017-01-01 10:43:41 +0100536 /* value -(N+1) requests information on index N */
537 if ( face_instance_index < 0 )
538 face_index--;
539
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000540 if ( face_index >= face->ttc_header.count )
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200541 {
542 if ( face_instance_index >= 0 )
543 return FT_THROW( Invalid_Argument );
544 else
545 face_index = 0;
546 }
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000547
548 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
549 return error;
550
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200551 /* check whether we have a valid TrueType file */
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000552 error = sfnt->load_font_dir( face, stream );
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000553 if ( error )
Wu, Chia-I (吳佳一)65863a52006-02-14 07:01:29 +0000554 return error;
David Turner241e1512000-05-28 17:15:37 +0000555
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200556#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
557 {
Werner Lembergd5bfa052017-03-17 21:47:54 +0100558 FT_Memory memory = face->root.memory;
559
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200560 FT_ULong fvar_len;
561
562 FT_ULong version;
563 FT_ULong offset;
564
565 FT_UShort num_axes;
566 FT_UShort axis_size;
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200567 FT_UShort num_instances;
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200568 FT_UShort instance_size;
569
570 FT_Int instance_index;
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200571
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100572 FT_Byte* default_values = NULL;
573 FT_Byte* instance_values = NULL;
574
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200575
576 instance_index = FT_ABS( face_instance_index ) >> 16;
577
578 /* test whether current face is a GX font with named instances */
579 if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) ||
580 fvar_len < 20 ||
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200581 FT_READ_ULONG( version ) ||
582 FT_READ_USHORT( offset ) ||
Werner Lemberg99fb3c32017-03-05 11:32:41 +0100583 FT_STREAM_SKIP( 2 ) /* reserved */ ||
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200584 FT_READ_USHORT( num_axes ) ||
585 FT_READ_USHORT( axis_size ) ||
586 FT_READ_USHORT( num_instances ) ||
587 FT_READ_USHORT( instance_size ) )
588 {
589 version = 0;
Werner Lemberge93d3262015-10-22 10:17:20 +0200590 offset = 0;
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200591 num_axes = 0;
592 axis_size = 0;
593 num_instances = 0;
594 instance_size = 0;
595 }
596
Werner Lemberg25f3ac22016-12-18 15:50:18 +0100597 /* check that the data is bound by the table length */
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200598 if ( version != 0x00010000UL ||
599 axis_size != 20 ||
Werner Lemberg7c75b162016-12-17 13:28:24 +0100600 num_axes == 0 ||
Werner Lemberg25f3ac22016-12-18 15:50:18 +0100601 /* `num_axes' limit implied by 16-bit `instance_size' */
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200602 num_axes > 0x3FFE ||
Werner Lemberg25f3ac22016-12-18 15:50:18 +0100603 !( instance_size == 4 + 4 * num_axes ||
604 instance_size == 6 + 4 * num_axes ) ||
Werner Lemberg99fb3c32017-03-05 11:32:41 +0100605 /* `num_instances' limit implied by limited range of name IDs */
Werner Lemberg4f7f6f62015-10-11 07:55:25 +0200606 num_instances > 0x7EFF ||
607 offset +
608 axis_size * num_axes +
609 instance_size * num_instances > fvar_len )
Werner Lemberg64a91132016-12-21 19:30:33 +0100610 num_instances = 0;
Werner Lemberg25f3ac22016-12-18 15:50:18 +0100611 else
Werner Lemberg64a91132016-12-21 19:30:33 +0100612 face->variation_support |= TT_FACE_FLAG_VAR_FVAR;
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200613
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100614 /*
Werner Lemberg9ac90602018-06-03 09:01:17 +0200615 * As documented in the OpenType specification, an entry for the
616 * default instance may be omitted in the named instance table. In
617 * particular this means that even if there is no named instance
618 * table in the font we actually do have a named instance, namely the
619 * default instance.
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100620 *
Werner Lemberg9ac90602018-06-03 09:01:17 +0200621 * For consistency, we always want the default instance in our list
622 * of named instances. If it is missing, we try to synthesize it
623 * later on. Here, we have to adjust `num_instances' accordingly.
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100624 */
625
Werner Lemberg6342da92017-03-20 05:36:41 +0100626 if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) &&
Werner Lemberg913f4362017-03-23 18:37:06 +0100627 !( FT_ALLOC( default_values, num_axes * 4 ) ||
628 FT_ALLOC( instance_values, num_axes * 4 ) ) )
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100629 {
630 /* the current stream position is 16 bytes after the table start */
631 FT_ULong array_start = FT_STREAM_POS() - 16 + offset;
632 FT_ULong default_value_offset, instance_offset;
633
634 FT_Byte* p;
635 FT_UInt i;
636
637
638 default_value_offset = array_start + 8;
639 p = default_values;
640
641 for ( i = 0; i < num_axes; i++ )
642 {
Werner Lemberg913f4362017-03-23 18:37:06 +0100643 (void)FT_STREAM_READ_AT( default_value_offset, p, 4 );
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100644
645 default_value_offset += axis_size;
Werner Lemberg913f4362017-03-23 18:37:06 +0100646 p += 4;
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100647 }
648
649 instance_offset = array_start + axis_size * num_axes + 4;
650
651 for ( i = 0; i < num_instances; i++ )
652 {
653 (void)FT_STREAM_READ_AT( instance_offset,
654 instance_values,
Werner Lemberg913f4362017-03-23 18:37:06 +0100655 num_axes * 4 );
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100656
Werner Lemberg913f4362017-03-23 18:37:06 +0100657 if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) )
Werner Lemberg27fee7f2017-03-06 20:45:44 +0100658 break;
659
660 instance_offset += instance_size;
661 }
662
663 if ( i == num_instances )
664 {
665 /* no default instance in named instance table; */
666 /* we thus have to synthesize it */
667 num_instances++;
668 }
669 }
670
671 FT_FREE( default_values );
672 FT_FREE( instance_values );
673
Werner Lemberg7bbb91f2017-03-08 15:09:41 +0100674 /* we don't support Multiple Master CFFs yet; */
675 /* note that `glyf' or `CFF2' have precedence */
Werner Lemberg77930972017-03-07 17:27:58 +0100676 if ( face->goto_table( face, TTAG_glyf, stream, 0 ) &&
Werner Lemberg7bbb91f2017-03-08 15:09:41 +0100677 face->goto_table( face, TTAG_CFF2, stream, 0 ) &&
Werner Lemberg77930972017-03-07 17:27:58 +0100678 !face->goto_table( face, TTAG_CFF, stream, 0 ) )
679 num_instances = 0;
680
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200681 /* instance indices in `face_instance_index' start with index 1, */
682 /* thus `>' and not `>=' */
683 if ( instance_index > num_instances )
684 {
685 if ( face_instance_index >= 0 )
686 return FT_THROW( Invalid_Argument );
687 else
688 num_instances = 0;
689 }
690
691 face->root.style_flags = (FT_Long)num_instances << 16;
692 }
693#endif
694
Werner Lemberg1ad384d2008-12-25 23:52:00 +0000695 face->root.num_faces = face->ttc_header.count;
Werner Lembergee3f36f2016-07-14 10:25:20 +0200696 face->root.face_index = face_instance_index;
David Turner241e1512000-05-28 17:15:37 +0000697
David Turner241e1512000-05-28 17:15:37 +0000698 return error;
699 }
700
701
Werner Lemberg89f50642013-03-14 17:50:49 +0100702#define LOAD_( x ) \
Werner Lemberga44b7842013-12-02 09:52:38 +0100703 do \
704 { \
Werner Lemberg89f50642013-03-14 17:50:49 +0100705 FT_TRACE2(( "`" #x "' " )); \
706 FT_TRACE3(( "-->\n" )); \
707 \
708 error = sfnt->load_ ## x( face, stream ); \
709 \
710 FT_TRACE2(( "%s\n", ( !error ) \
711 ? "loaded" \
712 : FT_ERR_EQ( error, Table_Missing ) \
713 ? "missing" \
714 : "failed to load" )); \
715 FT_TRACE3(( "\n" )); \
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000716 } while ( 0 )
717
Werner Lemberg89f50642013-03-14 17:50:49 +0100718#define LOADM_( x, vertical ) \
Werner Lemberga44b7842013-12-02 09:52:38 +0100719 do \
720 { \
Werner Lemberg89f50642013-03-14 17:50:49 +0100721 FT_TRACE2(( "`%s" #x "' ", \
722 vertical ? "vertical " : "" )); \
723 FT_TRACE3(( "-->\n" )); \
724 \
725 error = sfnt->load_ ## x( face, stream, vertical ); \
726 \
727 FT_TRACE2(( "%s\n", ( !error ) \
728 ? "loaded" \
729 : FT_ERR_EQ( error, Table_Missing ) \
730 ? "missing" \
731 : "failed to load" )); \
732 FT_TRACE3(( "\n" )); \
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000733 } while ( 0 )
David Turner241e1512000-05-28 17:15:37 +0000734
Werner Lembergd77b1ea2012-08-27 05:48:23 +0200735#define GET_NAME( id, field ) \
Werner Lemberga44b7842013-12-02 09:52:38 +0100736 do \
737 { \
Werner Lembergd77b1ea2012-08-27 05:48:23 +0200738 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
739 if ( error ) \
740 goto Exit; \
Werner Lemberg95120922008-11-08 07:20:25 +0000741 } while ( 0 )
742
David Turner241e1512000-05-28 17:15:37 +0000743
David Turnerbc82f1b2002-03-01 02:26:22 +0000744 FT_LOCAL_DEF( FT_Error )
David Turnerb08fe2d2002-08-27 20:20:29 +0000745 sfnt_load_face( FT_Stream stream,
Werner Lemberg52005c32001-06-27 23:25:46 +0000746 TT_Face face,
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200747 FT_Int face_instance_index,
Werner Lemberg52005c32001-06-27 23:25:46 +0000748 FT_Int num_params,
749 FT_Parameter* params )
David Turner241e1512000-05-28 17:15:37 +0000750 {
Werner Lembergce1bad02008-10-01 22:46:26 +0000751 FT_Error error;
752#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
753 FT_Error psnames_error;
754#endif
Werner Lembergb7b163c2002-03-31 18:48:24 +0000755 FT_Bool has_outline;
756 FT_Bool is_apple_sbit;
Behdad Esfahbod778a7e62013-07-19 14:28:28 +0200757 FT_Bool is_apple_sbix;
Werner Lemberg713d68e2018-02-17 18:35:15 +0100758 FT_Bool has_CBLC;
759 FT_Bool has_CBDT;
Werner Lemberg141f0ea2017-01-24 17:00:36 +0100760 FT_Bool ignore_typographic_family = FALSE;
761 FT_Bool ignore_typographic_subfamily = FALSE;
David Turnerf96594f2000-11-06 23:07:51 +0000762
David Turner4e7eeee2002-02-28 16:10:29 +0000763 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
Werner Lemberg4e6dd852000-06-05 05:26:15 +0000764
Werner Lemberg14d6b5d2015-08-13 15:22:17 +0200765 FT_UNUSED( face_instance_index );
Werner Lembergdeb4e982000-06-29 03:14:25 +0000766
Werner Lembergd77b1ea2012-08-27 05:48:23 +0200767
suzuki toshiya75852ed2010-01-29 23:18:34 +0900768 /* Check parameters */
Werner Lembergaf7b8b12011-03-20 07:51:57 +0100769
suzuki toshiya75852ed2010-01-29 23:18:34 +0900770 {
771 FT_Int i;
772
773
774 for ( i = 0; i < num_params; i++ )
775 {
Werner Lemberg141f0ea2017-01-24 17:00:36 +0100776 if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY )
777 ignore_typographic_family = TRUE;
778 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY )
779 ignore_typographic_subfamily = TRUE;
suzuki toshiya75852ed2010-01-29 23:18:34 +0900780 }
781 }
David Turner241e1512000-05-28 17:15:37 +0000782
783 /* Load tables */
David Turner241e1512000-05-28 17:15:37 +0000784
Werner Lemberg4b680072000-11-07 06:30:29 +0000785 /* We now support two SFNT-based bitmapped font formats. They */
786 /* are recognized easily as they do not include a `glyf' */
787 /* table. */
David Turnerf96594f2000-11-06 23:07:51 +0000788 /* */
Werner Lemberg4b680072000-11-07 06:30:29 +0000789 /* The first format comes from Apple, and uses a table named */
790 /* `bhed' instead of `head' to store the font header (using */
791 /* the same format). It also doesn't include horizontal and */
792 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
793 /* missing). */
David Turnerf96594f2000-11-06 23:07:51 +0000794 /* */
Werner Lemberg4b680072000-11-07 06:30:29 +0000795 /* The other format comes from Microsoft, and is used with */
796 /* WinCE/PocketPC. It looks like a standard TTF, except that */
797 /* it doesn't contain outlines. */
David Turnerf96594f2000-11-06 23:07:51 +0000798 /* */
David Turner241e1512000-05-28 17:15:37 +0000799
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000800 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
801
Werner Lemberg4b680072000-11-07 06:30:29 +0000802 /* do we have outlines in there? */
Graham Ashercd0d1df2002-07-18 16:38:07 +0000803#ifdef FT_CONFIG_OPTION_INCREMENTAL
Werner Lemberg4441f7b2016-12-26 17:08:17 +0100804 has_outline = FT_BOOL( face->root.internal->incremental_interface ||
805 tt_face_lookup_table( face, TTAG_glyf ) ||
806 tt_face_lookup_table( face, TTAG_CFF ) ||
807 tt_face_lookup_table( face, TTAG_CFF2 ) );
Graham Ashercd0d1df2002-07-18 16:38:07 +0000808#else
Werner Lemberg4441f7b2016-12-26 17:08:17 +0100809 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) ||
810 tt_face_lookup_table( face, TTAG_CFF ) ||
811 tt_face_lookup_table( face, TTAG_CFF2 ) );
Graham Ashercd0d1df2002-07-18 16:38:07 +0000812#endif
813
David Turnerf96594f2000-11-06 23:07:51 +0000814 is_apple_sbit = 0;
Behdad Esfahbod778a7e62013-07-19 14:28:28 +0200815 is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
816
817 /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
818 * outline rendered on top. We don't support that yet, so just ignore
819 * the 'glyf' outline and advertise it as a bitmap-only font. */
820 if ( is_apple_sbix )
821 has_outline = FALSE;
822
Werner Lemberg4b680072000-11-07 06:30:29 +0000823 /* if this font doesn't contain outlines, we try to load */
824 /* a `bhed' table */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000825 if ( !has_outline && sfnt->load_bhed )
826 {
827 LOAD_( bhed );
Werner Lemberg5a73d8d2006-03-20 16:55:32 +0000828 is_apple_sbit = FT_BOOL( !error );
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000829 }
Werner Lemberg9a814fa2000-08-06 19:48:47 +0000830
Werner Lemberg4b680072000-11-07 06:30:29 +0000831 /* load the font header (`head' table) if this isn't an Apple */
832 /* sbit font file */
Behdad Esfahbod778a7e62013-07-19 14:28:28 +0200833 if ( !is_apple_sbit || is_apple_sbix )
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000834 {
835 LOAD_( head );
836 if ( error )
837 goto Exit;
838 }
839
Werner Lemberg713d68e2018-02-17 18:35:15 +0100840 has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 );
841 has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 );
842
843 /* Ignore outlines for CBLC/CBDT fonts. */
844 if ( has_CBLC || has_CBDT )
845 has_outline = FALSE;
846
Werner Lembergce367772017-08-01 08:24:51 +0200847 /* OpenType 1.8.2 introduced limits to this value; */
848 /* however, they make sense for older SFNT fonts also */
849 if ( face->header.Units_Per_EM < 16 ||
850 face->header.Units_Per_EM > 16384 )
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000851 {
Werner Lemberg059bc332013-03-14 10:27:35 +0100852 error = FT_THROW( Invalid_Table );
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000853
David Turnerf96594f2000-11-06 23:07:51 +0000854 goto Exit;
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000855 }
Werner Lemberg9a814fa2000-08-06 19:48:47 +0000856
Werner Lemberg60a1fab2002-02-08 06:23:50 +0000857 /* the following tables are often not present in embedded TrueType */
858 /* fonts within PDF documents, so don't check for them. */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000859 LOAD_( maxp );
860 LOAD_( cmap );
David Turner617a2e12002-02-27 21:25:47 +0000861
Werner Lemberg0d535112001-12-19 22:26:12 +0000862 /* the following tables are optional in PCL fonts -- */
863 /* don't check for errors */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000864 LOAD_( name );
865 LOAD_( post );
Werner Lembergce1bad02008-10-01 22:46:26 +0000866
867#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000868 psnames_error = error;
Werner Lembergce1bad02008-10-01 22:46:26 +0000869#endif
Werner Lemberg9a814fa2000-08-06 19:48:47 +0000870
David Turnerf96594f2000-11-06 23:07:51 +0000871 /* do not load the metrics headers and tables if this is an Apple */
Werner Lemberg4b680072000-11-07 06:30:29 +0000872 /* sbit font file */
David Turnerf96594f2000-11-06 23:07:51 +0000873 if ( !is_apple_sbit )
Werner Lemberg9a814fa2000-08-06 19:48:47 +0000874 {
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000875 /* load the `hhea' and `hmtx' tables */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000876 LOADM_( hhea, 0 );
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000877 if ( !error )
878 {
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000879 LOADM_( hmtx, 0 );
Werner Lemberg89f50642013-03-14 17:50:49 +0100880 if ( FT_ERR_EQ( error, Table_Missing ) )
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000881 {
Werner Lemberg059bc332013-03-14 10:27:35 +0100882 error = FT_THROW( Hmtx_Table_Missing );
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000883
884#ifdef FT_CONFIG_OPTION_INCREMENTAL
885 /* If this is an incrementally loaded font and there are */
886 /* overriding metrics, tolerate a missing `hmtx' table. */
887 if ( face->root.internal->incremental_interface &&
888 face->root.internal->incremental_interface->funcs->
889 get_glyph_metrics )
890 {
891 face->horizontal.number_Of_HMetrics = 0;
Werner Lemberge3c93012013-03-14 11:21:17 +0100892 error = FT_Err_Ok;
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000893 }
894#endif
895 }
896 }
Werner Lemberg89f50642013-03-14 17:50:49 +0100897 else if ( FT_ERR_EQ( error, Table_Missing ) )
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000898 {
899 /* No `hhea' table necessary for SFNT Mac fonts. */
900 if ( face->format_tag == TTAG_true )
901 {
Werner Lemberg52254022006-02-15 06:05:52 +0000902 FT_TRACE2(( "This is an SFNT Mac font.\n" ));
Werner Lembergb5119992011-07-03 09:46:32 +0200903
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000904 has_outline = 0;
Werner Lemberge3c93012013-03-14 11:21:17 +0100905 error = FT_Err_Ok;
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000906 }
907 else
Werner Lembergfcc1f472007-04-10 11:51:50 +0000908 {
Werner Lemberg059bc332013-03-14 10:27:35 +0100909 error = FT_THROW( Horiz_Header_Missing );
Werner Lembergfcc1f472007-04-10 11:51:50 +0000910
911#ifdef FT_CONFIG_OPTION_INCREMENTAL
912 /* If this is an incrementally loaded font and there are */
913 /* overriding metrics, tolerate a missing `hhea' table. */
914 if ( face->root.internal->incremental_interface &&
915 face->root.internal->incremental_interface->funcs->
916 get_glyph_metrics )
917 {
918 face->horizontal.number_Of_HMetrics = 0;
Werner Lemberge3c93012013-03-14 11:21:17 +0100919 error = FT_Err_Ok;
Werner Lembergfcc1f472007-04-10 11:51:50 +0000920 }
921#endif
922
923 }
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000924 }
925
Werner Lemberg4b680072000-11-07 06:30:29 +0000926 if ( error )
David Turnerf96594f2000-11-06 23:07:51 +0000927 goto Exit;
Werner Lemberg415235d2001-06-28 17:49:10 +0000928
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000929 /* try to load the `vhea' and `vmtx' tables */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000930 LOADM_( hhea, 1 );
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000931 if ( !error )
932 {
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000933 LOADM_( hmtx, 1 );
Wu, Chia-I (吳佳一)9a2b3b62006-02-14 08:37:03 +0000934 if ( !error )
935 face->vertical_info = 1;
936 }
937
Werner Lemberg89f50642013-03-14 17:50:49 +0100938 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
David Turnerf96594f2000-11-06 23:07:51 +0000939 goto Exit;
Werner Lemberg415235d2001-06-28 17:49:10 +0000940
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000941 LOAD_( os2 );
942 if ( error )
943 {
Werner Lembergfa764cf2010-11-18 13:08:52 +0100944 /* we treat the table as missing if there are any errors */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000945 face->os2.version = 0xFFFFU;
946 }
Werner Lemberg9a814fa2000-08-06 19:48:47 +0000947 }
David Turner241e1512000-05-28 17:15:37 +0000948
949 /* the optional tables */
950
Werner Lemberg76fffcd2008-12-05 18:37:44 +0000951 /* embedded bitmap support */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000952 if ( sfnt->load_eblc )
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000953 LOAD_( eblc );
Werner Lembergb7b163c2002-03-31 18:48:24 +0000954
Werner Lemberg54b332a2018-06-13 08:46:27 +0200955 /* colored glyph support */
956 if ( sfnt->load_cpal )
Shao Yu Zhangf04d8172018-05-13 03:25:09 +0200957 {
Werner Lemberg54b332a2018-06-13 08:46:27 +0200958 LOAD_( cpal );
Shao Yu Zhangf04d8172018-05-13 03:25:09 +0200959 LOAD_( colr );
960 }
961
Werner Lemberg624b6802017-01-03 09:42:41 +0100962 /* consider the pclt, kerning, and gasp tables as optional */
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000963 LOAD_( pclt );
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000964 LOAD_( gasp );
965 LOAD_( kern );
David Turnere5680272005-02-26 00:12:04 +0000966
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +0000967 face->root.num_glyphs = face->max_profile.numGlyphs;
968
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000969 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */
970 /* a WWS-only font face. `WWS' stands for `weight', width', and */
971 /* `slope', a term used by Microsoft's Windows Presentation */
Werner Lemberge7aad022008-11-08 22:00:55 +0000972 /* Foundation (WPF). This flag has been introduced in version */
973 /* 1.5 of the OpenType specification (May 2008). */
Werner Lemberg91d0f1e2004-07-25 08:43:35 +0000974
suzuki toshiyac9669a82010-01-30 02:24:25 +0900975 face->root.family_name = NULL;
976 face->root.style_name = NULL;
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000977 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000978 {
Werner Lemberg141f0ea2017-01-24 17:00:36 +0100979 if ( !ignore_typographic_family )
980 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name );
suzuki toshiyac9669a82010-01-30 02:24:25 +0900981 if ( !face->root.family_name )
982 GET_NAME( FONT_FAMILY, &face->root.family_name );
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000983
Werner Lemberg141f0ea2017-01-24 17:00:36 +0100984 if ( !ignore_typographic_subfamily )
985 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name );
suzuki toshiyac9669a82010-01-30 02:24:25 +0900986 if ( !face->root.style_name )
987 GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000988 }
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000989 else
990 {
Werner Lemberg95120922008-11-08 07:20:25 +0000991 GET_NAME( WWS_FAMILY, &face->root.family_name );
Werner Lemberg141f0ea2017-01-24 17:00:36 +0100992 if ( !face->root.family_name && !ignore_typographic_family )
993 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name );
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000994 if ( !face->root.family_name )
Werner Lemberg95120922008-11-08 07:20:25 +0000995 GET_NAME( FONT_FAMILY, &face->root.family_name );
Werner Lemberg7d9c1892007-10-21 08:12:30 +0000996
Werner Lemberg95120922008-11-08 07:20:25 +0000997 GET_NAME( WWS_SUBFAMILY, &face->root.style_name );
Werner Lemberg141f0ea2017-01-24 17:00:36 +0100998 if ( !face->root.style_name && !ignore_typographic_subfamily )
999 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name );
Werner Lemberg7d9c1892007-10-21 08:12:30 +00001000 if ( !face->root.style_name )
Werner Lemberg95120922008-11-08 07:20:25 +00001001 GET_NAME( FONT_SUBFAMILY, &face->root.style_name );
Werner Lemberg7d9c1892007-10-21 08:12:30 +00001002 }
David Turner241e1512000-05-28 17:15:37 +00001003
1004 /* now set up root fields */
1005 {
suzuki toshiya01059052009-08-01 00:32:20 +09001006 FT_Face root = &face->root;
1007 FT_Long flags = root->face_flags;
David Turner241e1512000-05-28 17:15:37 +00001008
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001009
Werner Lemberg9ac90602018-06-03 09:01:17 +02001010 /**********************************************************************
1011 *
1012 * Compute face flags.
1013 */
Behdad Esfahbod21c32b02013-07-25 21:53:18 +02001014 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
Shao Yu Zhangf04d8172018-05-13 03:25:09 +02001015 face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ||
Werner Lemberg54b332a2018-06-13 08:46:27 +02001016 face->colr )
Behdad Esfahbod21c32b02013-07-25 21:53:18 +02001017 flags |= FT_FACE_FLAG_COLOR; /* color glyphs */
1018
David Turnerf96594f2000-11-06 23:07:51 +00001019 if ( has_outline == TRUE )
Werner Lemberg7734a1f2005-10-05 15:18:29 +00001020 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001021
Werner Lemberg7734a1f2005-10-05 15:18:29 +00001022 /* The sfnt driver only supports bitmap fonts natively, thus we */
1023 /* don't set FT_FACE_FLAG_HINTER. */
1024 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001025 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
David Turner241e1512000-05-28 17:15:37 +00001026
David Turner6930b452000-07-19 17:13:03 +00001027#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
Werner Lemberg89f50642013-03-14 17:50:49 +01001028 if ( !psnames_error &&
Werner Lemberg7f1458a2003-12-17 21:57:56 +00001029 face->postscript.FormatType != 0x00030000L )
Werner Lemberg25ab4912003-12-10 20:04:50 +00001030 flags |= FT_FACE_FLAG_GLYPH_NAMES;
David Turner6930b452000-07-19 17:13:03 +00001031#endif
1032
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001033 /* fixed width font? */
David Turner241e1512000-05-28 17:15:37 +00001034 if ( face->postscript.isFixedPitch )
1035 flags |= FT_FACE_FLAG_FIXED_WIDTH;
1036
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001037 /* vertical information? */
David Turner241e1512000-05-28 17:15:37 +00001038 if ( face->vertical_info )
1039 flags |= FT_FACE_FLAG_VERTICAL;
1040
1041 /* kerning available ? */
Werner Lemberge7930922005-03-01 02:13:50 +00001042 if ( TT_FACE_HAS_KERNING( face ) )
David Turner241e1512000-05-28 17:15:37 +00001043 flags |= FT_FACE_FLAG_KERNING;
1044
Werner Lemberg44bb3032004-04-25 20:15:11 +00001045#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1046 /* Don't bother to load the tables unless somebody asks for them. */
1047 /* No need to do work which will (probably) not be used. */
Werner Lemberg64a91132016-12-21 19:30:33 +01001048 if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR )
Werner Lemberg25f3ac22016-12-18 15:50:18 +01001049 {
1050 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
1051 tt_face_lookup_table( face, TTAG_gvar ) != 0 )
1052 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
1053 if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 )
1054 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
1055 }
Werner Lemberg44bb3032004-04-25 20:15:11 +00001056#endif
1057
David Turner241e1512000-05-28 17:15:37 +00001058 root->face_flags = flags;
1059
Werner Lemberg9ac90602018-06-03 09:01:17 +02001060 /**********************************************************************
1061 *
1062 * Compute style flags.
1063 */
Werner Lemberg7d9c1892007-10-21 08:12:30 +00001064
David Turner241e1512000-05-28 17:15:37 +00001065 flags = 0;
Werner Lemberg43ba0842003-06-23 19:26:53 +00001066 if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
David Turner241e1512000-05-28 17:15:37 +00001067 {
Werner Lemberge7aad022008-11-08 22:00:55 +00001068 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */
1069 /* indicates an oblique font face. This flag has been */
1070 /* introduced in version 1.5 of the OpenType specification. */
Werner Lemberg7d9c1892007-10-21 08:12:30 +00001071
1072 if ( face->os2.fsSelection & 512 ) /* bit 9 */
1073 flags |= FT_STYLE_FLAG_ITALIC;
1074 else if ( face->os2.fsSelection & 1 ) /* bit 0 */
David Turnerf96594f2000-11-06 23:07:51 +00001075 flags |= FT_STYLE_FLAG_ITALIC;
David Turner241e1512000-05-28 17:15:37 +00001076
Werner Lemberg7d9c1892007-10-21 08:12:30 +00001077 if ( face->os2.fsSelection & 32 ) /* bit 5 */
David Turnerf96594f2000-11-06 23:07:51 +00001078 flags |= FT_STYLE_FLAG_BOLD;
1079 }
1080 else
1081 {
1082 /* this is an old Mac font, use the header field */
Werner Lemberge7aad022008-11-08 22:00:55 +00001083
David Turnerf96594f2000-11-06 23:07:51 +00001084 if ( face->header.Mac_Style & 1 )
1085 flags |= FT_STYLE_FLAG_BOLD;
David Turner241e1512000-05-28 17:15:37 +00001086
David Turnerf96594f2000-11-06 23:07:51 +00001087 if ( face->header.Mac_Style & 2 )
1088 flags |= FT_STYLE_FLAG_ITALIC;
David Turner241e1512000-05-28 17:15:37 +00001089 }
1090
Werner Lemberg14d6b5d2015-08-13 15:22:17 +02001091 root->style_flags |= flags;
David Turner241e1512000-05-28 17:15:37 +00001092
Werner Lemberg9ac90602018-06-03 09:01:17 +02001093 /**********************************************************************
1094 *
1095 * Polish the charmaps.
1096 *
1097 * Try to set the charmap encoding according to the platform &
1098 * encoding ID of each charmap. Emulate Unicode charmap if one
1099 * is missing.
1100 */
David Turnerfd88e7c2002-03-22 15:02:38 +00001101
David Turnerb08fe2d2002-08-27 20:20:29 +00001102 tt_face_build_cmaps( face ); /* ignore errors */
Werner Lembergb7b163c2002-03-31 18:48:24 +00001103
1104
David Turnerfd88e7c2002-03-22 15:02:38 +00001105 /* set the encoding fields */
1106 {
Alexei Podtelezhnikov75cb0712017-06-21 22:52:37 -04001107 FT_Int m;
1108#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
1109 FT_Bool has_unicode = FALSE;
1110#endif
Werner Lembergb7b163c2002-03-31 18:48:24 +00001111
1112
David Turner94dbf7f2002-03-26 02:38:39 +00001113 for ( m = 0; m < root->num_charmaps; m++ )
David Turnerfd88e7c2002-03-22 15:02:38 +00001114 {
David Turner94dbf7f2002-03-26 02:38:39 +00001115 FT_CharMap charmap = root->charmaps[m];
Werner Lembergb7b163c2002-03-31 18:48:24 +00001116
1117
David Turnerfd88e7c2002-03-22 15:02:38 +00001118 charmap->encoding = sfnt_find_encoding( charmap->platform_id,
1119 charmap->encoding_id );
Alexei Podtelezhnikov75cb0712017-06-21 22:52:37 -04001120
1121#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
1122
Alexei Podtelezhnikov7653c762017-08-17 21:28:32 -04001123 if ( charmap->encoding == FT_ENCODING_UNICODE ||
1124 charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */
Alexei Podtelezhnikov75cb0712017-06-21 22:52:37 -04001125 has_unicode = TRUE;
1126 }
1127
1128 /* synthesize Unicode charmap if one is missing */
1129 if ( !has_unicode )
1130 {
1131 FT_CharMapRec cmaprec;
1132
1133
1134 cmaprec.face = root;
1135 cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
1136 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
1137 cmaprec.encoding = FT_ENCODING_UNICODE;
1138
1139
1140 error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec,
1141 NULL, &cmaprec, NULL );
1142 if ( error &&
Werner Lemberg912e1742018-10-07 09:28:52 +02001143 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
1144 FT_ERR_NEQ( error, Unimplemented_Feature ) )
Alexei Podtelezhnikovabeb28f2017-07-01 16:48:32 -04001145 goto Exit;
1146 error = FT_Err_Ok;
Alexei Podtelezhnikov75cb0712017-06-21 22:52:37 -04001147
1148#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
1149
David Turnerfd88e7c2002-03-22 15:02:38 +00001150 }
1151 }
1152
Werner Lembergc2cabd42009-02-09 22:20:27 +00001153#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1154
1155 /*
Werner Lemberg9ac90602018-06-03 09:01:17 +02001156 * Now allocate the root array of FT_Bitmap_Size records and
1157 * populate them. Unfortunately, it isn't possible to indicate bit
1158 * depths in the FT_Bitmap_Size record. This is a design error.
Werner Lembergc2cabd42009-02-09 22:20:27 +00001159 */
1160 {
Werner Lembergd609b7c2016-09-09 22:11:07 +02001161 FT_UInt count;
Werner Lembergc2cabd42009-02-09 22:20:27 +00001162
1163
Werner Lembergc2cabd42009-02-09 22:20:27 +00001164 count = face->sbit_num_strikes;
Werner Lembergc2cabd42009-02-09 22:20:27 +00001165
1166 if ( count > 0 )
1167 {
1168 FT_Memory memory = face->root.stream->memory;
1169 FT_UShort em_size = face->header.Units_Per_EM;
1170 FT_Short avgwidth = face->os2.xAvgCharWidth;
1171 FT_Size_Metrics metrics;
1172
Werner Lemberge421a0b2016-09-10 08:02:30 +02001173 FT_UInt* sbit_strike_map = NULL;
1174 FT_UInt strike_idx, bsize_idx;
Werner Lembergd609b7c2016-09-09 22:11:07 +02001175
Werner Lembergc2cabd42009-02-09 22:20:27 +00001176
1177 if ( em_size == 0 || face->os2.version == 0xFFFFU )
1178 {
Werner Lemberg8af2a1c2013-11-21 13:13:12 +01001179 avgwidth = 1;
Werner Lembergc2cabd42009-02-09 22:20:27 +00001180 em_size = 1;
1181 }
1182
Werner Lembergd609b7c2016-09-09 22:11:07 +02001183 /* to avoid invalid strike data in the `available_sizes' field */
1184 /* of `FT_Face', we map `available_sizes' indices to strike */
1185 /* indices */
1186 if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
Werner Lemberge421a0b2016-09-10 08:02:30 +02001187 FT_NEW_ARRAY( sbit_strike_map, count ) )
Werner Lembergc2cabd42009-02-09 22:20:27 +00001188 goto Exit;
1189
Werner Lembergd609b7c2016-09-09 22:11:07 +02001190 bsize_idx = 0;
1191 for ( strike_idx = 0; strike_idx < count; strike_idx++ )
Werner Lembergc2cabd42009-02-09 22:20:27 +00001192 {
Werner Lembergd609b7c2016-09-09 22:11:07 +02001193 FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx;
Werner Lembergc2cabd42009-02-09 22:20:27 +00001194
1195
Werner Lembergd609b7c2016-09-09 22:11:07 +02001196 error = sfnt->load_strike_metrics( face, strike_idx, &metrics );
Werner Lembergc2cabd42009-02-09 22:20:27 +00001197 if ( error )
Werner Lemberge421a0b2016-09-10 08:02:30 +02001198 continue;
Werner Lembergc2cabd42009-02-09 22:20:27 +00001199
1200 bsize->height = (FT_Short)( metrics.height >> 6 );
Werner Lembergd609b7c2016-09-09 22:11:07 +02001201 bsize->width = (FT_Short)(
1202 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
Werner Lembergc2cabd42009-02-09 22:20:27 +00001203
1204 bsize->x_ppem = metrics.x_ppem << 6;
1205 bsize->y_ppem = metrics.y_ppem << 6;
1206
1207 /* assume 72dpi */
1208 bsize->size = metrics.y_ppem << 6;
Werner Lembergd609b7c2016-09-09 22:11:07 +02001209
1210 /* only use strikes with valid PPEM values */
1211 if ( bsize->x_ppem && bsize->y_ppem )
Werner Lemberge421a0b2016-09-10 08:02:30 +02001212 sbit_strike_map[bsize_idx++] = strike_idx;
Werner Lembergc2cabd42009-02-09 22:20:27 +00001213 }
1214
Werner Lembergd609b7c2016-09-09 22:11:07 +02001215 /* reduce array size to the actually used elements */
Werner Lemberge421a0b2016-09-10 08:02:30 +02001216 (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx );
Werner Lembergd609b7c2016-09-09 22:11:07 +02001217
Werner Lemberge421a0b2016-09-10 08:02:30 +02001218 /* from now on, all strike indices are mapped */
1219 /* using `sbit_strike_map' */
1220 if ( bsize_idx )
1221 {
1222 face->sbit_strike_map = sbit_strike_map;
1223
1224 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
1225 root->num_fixed_sizes = (FT_Int)bsize_idx;
1226 }
Werner Lembergc2cabd42009-02-09 22:20:27 +00001227 }
1228 }
1229
1230#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1231
1232 /* a font with no bitmaps and no outlines is scalable; */
1233 /* it has only empty glyphs then */
1234 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) )
1235 root->face_flags |= FT_FACE_FLAG_SCALABLE;
1236
David Turnerfd88e7c2002-03-22 15:02:38 +00001237
Werner Lemberg9ac90602018-06-03 09:01:17 +02001238 /**********************************************************************
1239 *
1240 * Set up metrics.
1241 */
Werner Lembergc2cabd42009-02-09 22:20:27 +00001242 if ( FT_IS_SCALABLE( root ) )
David Turner241e1512000-05-28 17:15:37 +00001243 {
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001244 /* XXX What about if outline header is missing */
Werner Lemberg6d798992003-07-01 07:28:55 +00001245 /* (e.g. sfnt wrapped bitmap)? */
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001246 root->bbox.xMin = face->header.xMin;
1247 root->bbox.yMin = face->header.yMin;
1248 root->bbox.xMax = face->header.xMax;
1249 root->bbox.yMax = face->header.yMax;
1250 root->units_per_EM = face->header.Units_Per_EM;
1251
David Turner5878a6d2000-08-29 16:03:01 +00001252
Nikolaus Waxweilerf72b0072019-02-02 15:45:31 +00001253 /*
1254 * Computing the ascender/descender/height is tricky.
1255 *
1256 * The OpenType specification v1.8.3 says:
1257 *
1258 * [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields
1259 * are intended to allow applications to lay out documents in a
1260 * typographically-correct and portable fashion.
1261 *
1262 * This is somewhat at odds with the decades of backwards
1263 * compatibility, operating systems and applications doing whatever
1264 * they want, not to mention broken fonts.
1265 *
1266 * Not all fonts have an OS/2 table; in this case, we take the values
1267 * in the horizontal header, although there is nothing stopping the
1268 * values from being unreliable. Even with a OS/2 table, certain fonts
1269 * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0
1270 * and instead correctly set usWinAscent and usWinDescent.
1271 *
1272 * As an example, Arial Narrow is shipped as four files ARIALN.TTF,
1273 * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have
1274 * the same values in their sTypo* fields, except ARIALNB.ttf which
1275 * sets them to 0. All of them have different usWinAscent/Descent
1276 * values. The OS/2 table therefore cannot be trusted for computing the
1277 * text height reliably.
1278 *
1279 * As a compromise, do the following:
1280 *
1281 * 1. If the OS/2 table exists and the fsSelection bit 7 is set
1282 * (USE_TYPO_METRICS), trust the font and use the sTypo* metrics.
1283 * 2. Otherwise, use the `hhea' table's metrics.
1284 * 3. If they are zero and the OS/2 table exists,
1285 * 1. use the OS/2 table's sTypo* metrics if they are non-zero.
1286 * 2. Otherwise, use the OS/2 table's usWin* metrics.
1287 */
David Turner5878a6d2000-08-29 16:03:01 +00001288
Nikolaus Waxweilerf72b0072019-02-02 15:45:31 +00001289 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 )
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001290 {
Nikolaus Waxweilerf72b0072019-02-02 15:45:31 +00001291 root->ascender = face->os2.sTypoAscender;
1292 root->descender = face->os2.sTypoDescender;
1293 root->height = root->ascender - root->descender +
1294 face->os2.sTypoLineGap;
1295 }
1296 else
1297 {
1298 root->ascender = face->horizontal.Ascender;
1299 root->descender = face->horizontal.Descender;
1300 root->height = root->ascender - root->descender +
1301 face->horizontal.Line_Gap;
1302
1303 if ( !( root->ascender || root->descender ) )
Werner Lembergf0957442011-07-07 14:10:39 +02001304 {
Nikolaus Waxweilerf72b0072019-02-02 15:45:31 +00001305 if ( face->os2.version != 0xFFFFU )
Werner Lembergf0957442011-07-07 14:10:39 +02001306 {
Nikolaus Waxweilerf72b0072019-02-02 15:45:31 +00001307 if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
1308 {
1309 root->ascender = face->os2.sTypoAscender;
1310 root->descender = face->os2.sTypoDescender;
1311 root->height = root->ascender - root->descender +
1312 face->os2.sTypoLineGap;
1313 }
1314 else
1315 {
1316 root->ascender = (FT_Short)face->os2.usWinAscent;
1317 root->descender = -(FT_Short)face->os2.usWinDescent;
1318 root->height = root->ascender - root->descender;
1319 }
Werner Lembergf0957442011-07-07 14:10:39 +02001320 }
1321 }
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001322 }
Werner Lemberg4a5c1422000-08-29 18:37:25 +00001323
Werner Lemberg01f08422015-02-22 12:03:28 +01001324 root->max_advance_width =
1325 (FT_Short)face->horizontal.advance_Width_Max;
1326 root->max_advance_height =
1327 (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max
1328 : root->height );
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001329
Werner Lemberg87ddad22017-12-04 20:43:30 +01001330 /* See https://www.microsoft.com/typography/otspec/post.htm -- */
1331 /* Adjust underline position from top edge to centre of */
1332 /* stroke to convert TrueType meaning to FreeType meaning. */
Werner Lemberg174b8de2008-10-12 11:47:29 +00001333 root->underline_position = face->postscript.underlinePosition -
1334 face->postscript.underlineThickness / 2;
Werner Lemberg9a814fa2000-08-06 19:48:47 +00001335 root->underline_thickness = face->postscript.underlineThickness;
David Turner241e1512000-05-28 17:15:37 +00001336 }
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +00001337
David Turner241e1512000-05-28 17:15:37 +00001338 }
1339
1340 Exit:
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +00001341 FT_TRACE2(( "sfnt_load_face: done\n" ));
1342
David Turner241e1512000-05-28 17:15:37 +00001343 return error;
1344 }
1345
1346
1347#undef LOAD_
Wu, Chia-I (吳佳一)0d565fd2006-02-15 07:44:31 +00001348#undef LOADM_
Werner Lemberg95120922008-11-08 07:20:25 +00001349#undef GET_NAME
David Turner241e1512000-05-28 17:15:37 +00001350
1351
David Turnerbc82f1b2002-03-01 02:26:22 +00001352 FT_LOCAL_DEF( void )
David Turnerb08fe2d2002-08-27 20:20:29 +00001353 sfnt_done_face( TT_Face face )
David Turner241e1512000-05-28 17:15:37 +00001354 {
Werner Lembergd03d8562008-10-01 22:39:05 +00001355 FT_Memory memory;
1356 SFNT_Service sfnt;
David Turner241e1512000-05-28 17:15:37 +00001357
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001358
Werner Lembergd03d8562008-10-01 22:39:05 +00001359 if ( !face )
1360 return;
1361
1362 memory = face->root.memory;
1363 sfnt = (SFNT_Service)face->sfnt;
1364
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001365 if ( sfnt )
David Turner241e1512000-05-28 17:15:37 +00001366 {
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001367 /* destroy the postscript names table if it is loaded */
1368 if ( sfnt->free_psnames )
David Turner241e1512000-05-28 17:15:37 +00001369 sfnt->free_psnames( face );
1370
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001371 /* destroy the embedded bitmaps table if it is loaded */
Wu, Chia-I (吳佳一)f5aa47b2006-02-14 06:40:10 +00001372 if ( sfnt->free_eblc )
1373 sfnt->free_eblc( face );
Shao Yu Zhangf04d8172018-05-13 03:25:09 +02001374
1375 /* destroy color table data if it is loaded */
Werner Lemberg54b332a2018-06-13 08:46:27 +02001376 if ( sfnt->free_cpal )
1377 {
1378 sfnt->free_cpal( face );
Shao Yu Zhangf04d8172018-05-13 03:25:09 +02001379 sfnt->free_colr( face );
Werner Lemberg54b332a2018-06-13 08:46:27 +02001380 }
David Turner241e1512000-05-28 17:15:37 +00001381 }
1382
David Turner89a2a4b2005-12-14 20:38:15 +00001383#ifdef TT_CONFIG_OPTION_BDF
1384 /* freeing the embedded BDF properties */
1385 tt_face_free_bdf_props( face );
1386#endif
1387
David Turner241e1512000-05-28 17:15:37 +00001388 /* freeing the kerning table */
David Turnere5680272005-02-26 00:12:04 +00001389 tt_face_done_kern( face );
David Turner241e1512000-05-28 17:15:37 +00001390
1391 /* freeing the collection table */
David Turnere459d742002-03-22 13:52:37 +00001392 FT_FREE( face->ttc_header.offsets );
Werner Lemberge1bbc012000-07-19 06:25:56 +00001393 face->ttc_header.count = 0;
David Turner241e1512000-05-28 17:15:37 +00001394
1395 /* freeing table directory */
David Turnere459d742002-03-22 13:52:37 +00001396 FT_FREE( face->dir_tables );
David Turner241e1512000-05-28 17:15:37 +00001397 face->num_tables = 0;
1398
David Turnerfd88e7c2002-03-22 15:02:38 +00001399 {
Werner Lembergb7b163c2002-03-31 18:48:24 +00001400 FT_Stream stream = FT_FACE_STREAM( face );
1401
1402
David Turnerfd88e7c2002-03-22 15:02:38 +00001403 /* simply release the 'cmap' table frame */
1404 FT_FRAME_RELEASE( face->cmap_table );
1405 face->cmap_size = 0;
1406 }
1407
Werner Lembergbf902392016-09-29 13:04:46 +02001408 face->horz_metrics_size = 0;
1409 face->vert_metrics_size = 0;
David Turner6a487b52005-02-28 22:09:07 +00001410
Werner Lembergbf902392016-09-29 13:04:46 +02001411 /* freeing vertical metrics, if any */
David Turner241e1512000-05-28 17:15:37 +00001412 if ( face->vertical_info )
1413 {
David Turnere459d742002-03-22 13:52:37 +00001414 FT_FREE( face->vertical.long_metrics );
1415 FT_FREE( face->vertical.short_metrics );
David Turner241e1512000-05-28 17:15:37 +00001416 face->vertical_info = 0;
1417 }
1418
1419 /* freeing the gasp table */
David Turnere459d742002-03-22 13:52:37 +00001420 FT_FREE( face->gasp.gaspRanges );
David Turner241e1512000-05-28 17:15:37 +00001421 face->gasp.numRanges = 0;
1422
1423 /* freeing the name table */
Werner Lembergd503fc52007-11-01 09:19:44 +00001424 if ( sfnt )
1425 sfnt->free_name( face );
David Turner241e1512000-05-28 17:15:37 +00001426
1427 /* freeing family and style name */
David Turnere459d742002-03-22 13:52:37 +00001428 FT_FREE( face->root.family_name );
1429 FT_FREE( face->root.style_name );
David Turner241e1512000-05-28 17:15:37 +00001430
1431 /* freeing sbit size table */
Werner Lembergb6420e82004-05-18 20:16:04 +00001432 FT_FREE( face->root.available_sizes );
Werner Lembergd609b7c2016-09-09 22:11:07 +02001433 FT_FREE( face->sbit_strike_map );
David Turner241e1512000-05-28 17:15:37 +00001434 face->root.num_fixed_sizes = 0;
Werner Lembergb6420e82004-05-18 20:16:04 +00001435
1436 FT_FREE( face->postscript_name );
Ben Wagner96b5e502018-08-10 22:24:26 +02001437
1438#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Werner Lemberg34010f72017-03-14 21:50:22 +01001439 FT_FREE( face->var_postscript_prefix );
Werner Lembergd5bfa052017-03-17 21:47:54 +01001440#endif
David Turner241e1512000-05-28 17:15:37 +00001441
Werner Lembergc412de52018-06-09 23:56:21 +02001442 /* freeing glyph color palette data */
Werner Lembergd8b8b6e2018-06-10 21:37:15 +02001443 FT_FREE( face->palette_data.palette_name_ids );
Werner Lemberg7edc9372018-07-02 11:50:04 +02001444 FT_FREE( face->palette_data.palette_flags );
Werner Lembergd8b8b6e2018-06-10 21:37:15 +02001445 FT_FREE( face->palette_data.palette_entry_name_ids );
Werner Lembergb85d4e82018-06-12 05:53:58 +02001446 FT_FREE( face->palette );
Werner Lembergc412de52018-06-09 23:56:21 +02001447
Alexei Podtelezhnikov792db0b2015-04-15 23:20:23 -04001448 face->sfnt = NULL;
David Turner241e1512000-05-28 17:15:37 +00001449 }
1450
Werner Lemberg4e6dd852000-06-05 05:26:15 +00001451
1452/* END */