blob: ae3e4aadf1c661bd4a7da87eeb62550b8f4222df [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
David Turner19ed8af2000-12-08 02:42:29 +00003/* ttpload.c */
David Turnerd2b1f351999-12-16 23:11:37 +00004/* */
5/* TrueType glyph data/program tables loader (body). */
6/* */
Werner Lemberge7930922005-03-01 02:13:50 +00007/* Copyright 1996-2001, 2002, 2004, 2005 by */
David Turnerd2b1f351999-12-16 23:11:37 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000012/* 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/***************************************************************************/
17
Werner Lembergcc069be2000-12-08 16:17:16 +000018
David Turner19ed8af2000-12-08 02:42:29 +000019#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_OBJECTS_H
22#include FT_INTERNAL_STREAM_H
23#include FT_TRUETYPE_TAGS_H
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000024
David Turner8d3a4012001-03-20 11:14:24 +000025#include "ttpload.h"
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000026
Werner Lemberg44bb3032004-04-25 20:15:11 +000027#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
28#include "ttgxvar.h"
29#endif
30
Werner Lemberg1f7f0e82001-06-06 17:30:41 +000031#include "tterrors.h"
David Turnerd2b1f351999-12-16 23:11:37 +000032
Werner Lemberg78575dc2000-06-12 19:36:41 +000033
34 /*************************************************************************/
35 /* */
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
39 /* */
David Turnerd2b1f351999-12-16 23:11:37 +000040#undef FT_COMPONENT
Werner Lemberg78575dc2000-06-12 19:36:41 +000041#define FT_COMPONENT trace_ttpload
42
David Turnerd2b1f351999-12-16 23:11:37 +000043
44 /*************************************************************************/
45 /* */
46 /* <Function> */
David Turnerb08fe2d2002-08-27 20:20:29 +000047 /* tt_face_load_loca */
David Turnerd2b1f351999-12-16 23:11:37 +000048 /* */
49 /* <Description> */
50 /* Loads the locations table. */
51 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +000052 /* <InOut> */
David Turnerd2b1f351999-12-16 23:11:37 +000053 /* face :: A handle to the target face object. */
Werner Lemberg78575dc2000-06-12 19:36:41 +000054 /* */
55 /* <Input> */
David Turnerd2b1f351999-12-16 23:11:37 +000056 /* stream :: The input stream. */
57 /* */
58 /* <Return> */
Werner Lemberg9ca2af32000-06-21 03:03:28 +000059 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +000060 /* */
David Turnere70d5532005-02-22 16:53:06 +000061#ifdef FT_OPTIMIZE_MEMORY
62
63 FT_LOCAL_DEF( FT_Error )
64 tt_face_load_loca( TT_Face face,
65 FT_Stream stream )
66 {
67 FT_Error error;
68 FT_Memory memory = stream->memory;
69 FT_ULong table_len;
70
71
72 FT_TRACE2(( "Locations " ));
73 error = face->goto_table( face, TTAG_loca, stream, &table_len );
74 if ( error )
75 {
76 error = TT_Err_Locations_Missing;
77 goto Exit;
78 }
79
80 if ( face->header.Index_To_Loc_Format != 0 )
81 {
Werner Lemberge7930922005-03-01 02:13:50 +000082 if ( table_len >= 0x40000 )
David Turnere70d5532005-02-22 16:53:06 +000083 {
Werner Lemberge7930922005-03-01 02:13:50 +000084 FT_TRACE2(( "table too large!\n" ));
David Turnere70d5532005-02-22 16:53:06 +000085 error = TT_Err_Invalid_Table;
86 goto Exit;
87 }
Werner Lemberge7930922005-03-01 02:13:50 +000088 face->num_locations = (FT_UInt)( table_len >> 2 );
David Turnere70d5532005-02-22 16:53:06 +000089 }
90 else
91 {
92 if ( table_len >= 0x20000 )
93 {
Werner Lemberge7930922005-03-01 02:13:50 +000094 FT_TRACE2(( "table too large!\n" ));
David Turnere70d5532005-02-22 16:53:06 +000095 error = TT_Err_Invalid_Table;
96 goto Exit;
97 }
Werner Lemberge7930922005-03-01 02:13:50 +000098 face->num_locations = (FT_UInt)( table_len >> 1 );
David Turnere70d5532005-02-22 16:53:06 +000099 }
100
Werner Lemberge7930922005-03-01 02:13:50 +0000101 /*
102 * Extract the frame. We don't need to decompress it since
103 * we are able to parse it directly.
104 */
David Turnere70d5532005-02-22 16:53:06 +0000105 if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
106 goto Exit;
107
108 FT_TRACE2(( "loaded\n" ));
109
110 Exit:
111 return error;
112 }
113
114
115 FT_LOCAL_DEF( FT_ULong )
Werner Lemberge7930922005-03-01 02:13:50 +0000116 tt_face_get_location( TT_Face face,
117 FT_UInt gindex,
118 FT_UInt *asize )
David Turnere70d5532005-02-22 16:53:06 +0000119 {
120 FT_ULong pos1, pos2;
121 FT_Byte* p;
122 FT_Byte* p_limit;
123
Werner Lemberge7930922005-03-01 02:13:50 +0000124
David Turnere70d5532005-02-22 16:53:06 +0000125 pos1 = pos2 = 0;
Werner Lemberge7930922005-03-01 02:13:50 +0000126
David Turnere70d5532005-02-22 16:53:06 +0000127 if ( gindex < face->num_locations )
128 {
129 if ( face->header.Index_To_Loc_Format != 0 )
130 {
Werner Lemberge7930922005-03-01 02:13:50 +0000131 p = face->glyph_locations + gindex * 4;
132 p_limit = face->glyph_locations + face->num_locations * 4;
David Turnere70d5532005-02-22 16:53:06 +0000133
Werner Lemberge7930922005-03-01 02:13:50 +0000134 pos1 = FT_NEXT_ULONG( p );
David Turnere70d5532005-02-22 16:53:06 +0000135 pos2 = pos1;
136
Werner Lemberge7930922005-03-01 02:13:50 +0000137 if ( p + 4 <= p_limit )
138 pos2 = FT_NEXT_ULONG( p );
David Turnere70d5532005-02-22 16:53:06 +0000139 }
140 else
141 {
Werner Lemberge7930922005-03-01 02:13:50 +0000142 p = face->glyph_locations + gindex * 2;
143 p_limit = face->glyph_locations + face->num_locations * 2;
David Turnere70d5532005-02-22 16:53:06 +0000144
Werner Lemberge7930922005-03-01 02:13:50 +0000145 pos1 = FT_NEXT_USHORT( p );
David Turnere70d5532005-02-22 16:53:06 +0000146 pos2 = pos1;
147
Werner Lemberge7930922005-03-01 02:13:50 +0000148 if ( p + 2 <= p_limit )
149 pos2 = FT_NEXT_USHORT( p );
David Turnere70d5532005-02-22 16:53:06 +0000150
151 pos1 <<= 1;
152 pos2 <<= 1;
153 }
154 }
155
Werner Lemberge7930922005-03-01 02:13:50 +0000156 *asize = (FT_UInt)( pos2 - pos1 );
David Turnere70d5532005-02-22 16:53:06 +0000157
158 return pos1;
159 }
160
161
162 FT_LOCAL_DEF( void )
163 tt_face_done_loca( TT_Face face )
164 {
Werner Lemberge7930922005-03-01 02:13:50 +0000165 FT_Stream stream = face->root.stream;
166
David Turnere70d5532005-02-22 16:53:06 +0000167
168 FT_FRAME_RELEASE( face->glyph_locations );
169 face->num_locations = 0;
170 }
171
172
David Turnere70d5532005-02-22 16:53:06 +0000173#else /* !FT_OPTIMIZE_MEMORY */
174
Werner Lemberge7930922005-03-01 02:13:50 +0000175
David Turnerbc82f1b2002-03-01 02:26:22 +0000176 FT_LOCAL_DEF( FT_Error )
David Turnerb08fe2d2002-08-27 20:20:29 +0000177 tt_face_load_loca( TT_Face face,
Werner Lemberg4a2305c2001-06-28 07:17:51 +0000178 FT_Stream stream )
David Turnerd2b1f351999-12-16 23:11:37 +0000179 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000180 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000181 FT_Memory memory = stream->memory;
David Turnerf9b8dec2000-06-16 19:34:52 +0000182 FT_Short LongOffsets;
183 FT_ULong table_len;
David Turnerd2b1f351999-12-16 23:11:37 +0000184
Werner Lemberg78575dc2000-06-12 19:36:41 +0000185
David Turnerd2b1f351999-12-16 23:11:37 +0000186 FT_TRACE2(( "Locations " ));
187 LongOffsets = face->header.Index_To_Loc_Format;
188
189 error = face->goto_table( face, TTAG_loca, stream, &table_len );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000190 if ( error )
David Turnerd2b1f351999-12-16 23:11:37 +0000191 {
192 error = TT_Err_Locations_Missing;
193 goto Exit;
194 }
195
196 if ( LongOffsets != 0 )
197 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000198 face->num_locations = (FT_UShort)( table_len >> 2 );
David Turnerd2b1f351999-12-16 23:11:37 +0000199
Werner Lemberg78575dc2000-06-12 19:36:41 +0000200 FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations ));
David Turnerd2b1f351999-12-16 23:11:37 +0000201
David Turnere459d742002-03-22 13:52:37 +0000202 if ( FT_NEW_ARRAY( face->glyph_locations, face->num_locations ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000203 goto Exit;
204
David Turner7d3a2642002-03-20 10:49:31 +0000205 if ( FT_FRAME_ENTER( face->num_locations * 4L ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000206 goto Exit;
207
208 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000209 FT_Long* loc = face->glyph_locations;
210 FT_Long* limit = loc + face->num_locations;
David Turnerd2b1f351999-12-16 23:11:37 +0000211
Werner Lemberg78575dc2000-06-12 19:36:41 +0000212
David Turnerd2b1f351999-12-16 23:11:37 +0000213 for ( ; loc < limit; loc++ )
David Turnera890c292002-03-22 12:55:23 +0000214 *loc = FT_GET_LONG();
David Turnerd2b1f351999-12-16 23:11:37 +0000215 }
216
David Turner7d3a2642002-03-20 10:49:31 +0000217 FT_FRAME_EXIT();
David Turnerd2b1f351999-12-16 23:11:37 +0000218 }
219 else
220 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000221 face->num_locations = (FT_UShort)( table_len >> 1 );
David Turnerd2b1f351999-12-16 23:11:37 +0000222
Werner Lemberg78575dc2000-06-12 19:36:41 +0000223 FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations ));
David Turnerd2b1f351999-12-16 23:11:37 +0000224
David Turnere459d742002-03-22 13:52:37 +0000225 if ( FT_NEW_ARRAY( face->glyph_locations, face->num_locations ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000226 goto Exit;
227
David Turner7d3a2642002-03-20 10:49:31 +0000228 if ( FT_FRAME_ENTER( face->num_locations * 2L ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000229 goto Exit;
Werner Lemberge7930922005-03-01 02:13:50 +0000230
David Turnerd2b1f351999-12-16 23:11:37 +0000231 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000232 FT_Long* loc = face->glyph_locations;
233 FT_Long* limit = loc + face->num_locations;
David Turnerd2b1f351999-12-16 23:11:37 +0000234
Werner Lemberg78575dc2000-06-12 19:36:41 +0000235
David Turnerd2b1f351999-12-16 23:11:37 +0000236 for ( ; loc < limit; loc++ )
David Turnera890c292002-03-22 12:55:23 +0000237 *loc = (FT_Long)( (FT_ULong)FT_GET_USHORT() * 2 );
David Turnerd2b1f351999-12-16 23:11:37 +0000238 }
Werner Lemberge7930922005-03-01 02:13:50 +0000239
David Turner7d3a2642002-03-20 10:49:31 +0000240 FT_FRAME_EXIT();
David Turnerd2b1f351999-12-16 23:11:37 +0000241 }
242
243 FT_TRACE2(( "loaded\n" ));
244
245 Exit:
246 return error;
247 }
248
249
David Turnere70d5532005-02-22 16:53:06 +0000250 FT_LOCAL_DEF( FT_ULong )
Werner Lemberge7930922005-03-01 02:13:50 +0000251 tt_face_get_location( TT_Face face,
252 FT_UInt gindex,
253 FT_UInt *asize )
David Turnere70d5532005-02-22 16:53:06 +0000254 {
255 FT_ULong offset;
256 FT_UInt count;
257
Werner Lemberge7930922005-03-01 02:13:50 +0000258
David Turnere70d5532005-02-22 16:53:06 +0000259 offset = face->glyph_locations[gindex];
260 count = 0;
261
262 if ( gindex < (FT_UInt)face->num_locations - 1 )
263 count = (FT_UInt)( face->glyph_locations[gindex + 1] - offset );
264
265 *asize = count;
266 return offset;
267 }
268
269
270 FT_LOCAL_DEF( void )
271 tt_face_done_loca( TT_Face face )
272 {
Werner Lemberge7930922005-03-01 02:13:50 +0000273 FT_Memory memory = face->root.memory;
274
David Turnere70d5532005-02-22 16:53:06 +0000275
276 FT_FREE( face->glyph_locations );
277 face->num_locations = 0;
278 }
279
280
David Turnere70d5532005-02-22 16:53:06 +0000281#endif /* !FT_OPTIMIZE_MEMORY */
282
283
David Turnerd2b1f351999-12-16 23:11:37 +0000284 /*************************************************************************/
285 /* */
286 /* <Function> */
David Turnerb08fe2d2002-08-27 20:20:29 +0000287 /* tt_face_load_cvt */
David Turnerd2b1f351999-12-16 23:11:37 +0000288 /* */
289 /* <Description> */
290 /* Loads the control value table into a face object. */
291 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000292 /* <InOut> */
David Turnerd2b1f351999-12-16 23:11:37 +0000293 /* face :: A handle to the target face object. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000294 /* */
295 /* <Input> */
David Turnerd2b1f351999-12-16 23:11:37 +0000296 /* stream :: A handle to the input stream. */
297 /* */
298 /* <Return> */
Werner Lemberg9ca2af32000-06-21 03:03:28 +0000299 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000300 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000301 FT_LOCAL_DEF( FT_Error )
David Turnerb08fe2d2002-08-27 20:20:29 +0000302 tt_face_load_cvt( TT_Face face,
303 FT_Stream stream )
David Turnerd2b1f351999-12-16 23:11:37 +0000304 {
David Turnere70d5532005-02-22 16:53:06 +0000305#ifdef FT_CONFIG_OPTION_BYTECODE_INTERPRETER
306
David Turnerf9b8dec2000-06-16 19:34:52 +0000307 FT_Error error;
David Turnerd2b1f351999-12-16 23:11:37 +0000308 FT_Memory memory = stream->memory;
David Turnerf9b8dec2000-06-16 19:34:52 +0000309 FT_ULong table_len;
David Turnerd2b1f351999-12-16 23:11:37 +0000310
Werner Lemberg78575dc2000-06-12 19:36:41 +0000311
David Turnerd2b1f351999-12-16 23:11:37 +0000312 FT_TRACE2(( "CVT " ));
313
314 error = face->goto_table( face, TTAG_cvt, stream, &table_len );
Werner Lemberg78575dc2000-06-12 19:36:41 +0000315 if ( error )
David Turnerd2b1f351999-12-16 23:11:37 +0000316 {
317 FT_TRACE2(( "is missing!\n" ));
318
319 face->cvt_size = 0;
320 face->cvt = NULL;
321 error = TT_Err_Ok;
322
323 goto Exit;
324 }
325
326 face->cvt_size = table_len / 2;
327
David Turnere459d742002-03-22 13:52:37 +0000328 if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000329 goto Exit;
330
David Turner7d3a2642002-03-20 10:49:31 +0000331 if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000332 goto Exit;
333
334 {
David Turnerf9b8dec2000-06-16 19:34:52 +0000335 FT_Short* cur = face->cvt;
336 FT_Short* limit = cur + face->cvt_size;
David Turnerd2b1f351999-12-16 23:11:37 +0000337
Werner Lemberg78575dc2000-06-12 19:36:41 +0000338
David Turnerd2b1f351999-12-16 23:11:37 +0000339 for ( ; cur < limit; cur++ )
David Turnera890c292002-03-22 12:55:23 +0000340 *cur = FT_GET_SHORT();
David Turnerd2b1f351999-12-16 23:11:37 +0000341 }
342
David Turner7d3a2642002-03-20 10:49:31 +0000343 FT_FRAME_EXIT();
David Turnerd2b1f351999-12-16 23:11:37 +0000344 FT_TRACE2(( "loaded\n" ));
345
Werner Lemberg44bb3032004-04-25 20:15:11 +0000346#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
347 if ( face->doblend )
348 error = tt_face_vary_cvt( face, stream );
349#endif
350
David Turnerd2b1f351999-12-16 23:11:37 +0000351 Exit:
352 return error;
David Turnere70d5532005-02-22 16:53:06 +0000353
Werner Lemberge7930922005-03-01 02:13:50 +0000354#else /* !FT_CONFIG_OPTION_BYTECODE_INTERPRETER */
355
356 FT_UNUSED( face );
357 FT_UNUSED( stream );
358
David Turnere70d5532005-02-22 16:53:06 +0000359 return 0;
Werner Lemberge7930922005-03-01 02:13:50 +0000360
David Turnere70d5532005-02-22 16:53:06 +0000361#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000362 }
363
364
365 /*************************************************************************/
366 /* */
367 /* <Function> */
David Turnerb08fe2d2002-08-27 20:20:29 +0000368 /* tt_face_load_fpgm */
David Turnerd2b1f351999-12-16 23:11:37 +0000369 /* */
370 /* <Description> */
371 /* Loads the font program and the cvt program. */
372 /* */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000373 /* <InOut> */
David Turnerd2b1f351999-12-16 23:11:37 +0000374 /* face :: A handle to the target face object. */
Werner Lemberg78575dc2000-06-12 19:36:41 +0000375 /* */
376 /* <Input> */
David Turnerd2b1f351999-12-16 23:11:37 +0000377 /* stream :: A handle to the input stream. */
378 /* */
379 /* <Return> */
Werner Lemberg9ca2af32000-06-21 03:03:28 +0000380 /* FreeType error code. 0 means success. */
David Turnerd2b1f351999-12-16 23:11:37 +0000381 /* */
David Turnerbc82f1b2002-03-01 02:26:22 +0000382 FT_LOCAL_DEF( FT_Error )
David Turnerb08fe2d2002-08-27 20:20:29 +0000383 tt_face_load_fpgm( TT_Face face,
384 FT_Stream stream )
David Turnerd2b1f351999-12-16 23:11:37 +0000385 {
David Turnere70d5532005-02-22 16:53:06 +0000386#ifdef FT_CONFIG_OPTION_BYTECODE_INTERPRETER
387
David Turnerf9b8dec2000-06-16 19:34:52 +0000388 FT_Error error;
389 FT_ULong table_len;
David Turnerd2b1f351999-12-16 23:11:37 +0000390
Werner Lemberg78575dc2000-06-12 19:36:41 +0000391
Werner Lembergf6978662000-01-08 20:00:54 +0000392 FT_TRACE2(( "Font program " ));
David Turnerd2b1f351999-12-16 23:11:37 +0000393
394 /* The font program is optional */
395 error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
Werner Lembergf6978662000-01-08 20:00:54 +0000396 if ( error )
David Turnerd2b1f351999-12-16 23:11:37 +0000397 {
398 face->font_program = NULL;
399 face->font_program_size = 0;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000400
David Turnerd2b1f351999-12-16 23:11:37 +0000401 FT_TRACE2(( "is missing!\n" ));
402 }
403 else
404 {
405 face->font_program_size = table_len;
David Turner7d3a2642002-03-20 10:49:31 +0000406 if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
David Turnerd2b1f351999-12-16 23:11:37 +0000407 goto Exit;
408
409 FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
410 }
411
412 FT_TRACE2(( "Prep program " ));
413
414 error = face->goto_table( face, TTAG_prep, stream, &table_len );
Werner Lembergf6978662000-01-08 20:00:54 +0000415 if ( error )
David Turnerd2b1f351999-12-16 23:11:37 +0000416 {
417 face->cvt_program = NULL;
418 face->cvt_program_size = 0;
Werner Lembergf6978662000-01-08 20:00:54 +0000419 error = TT_Err_Ok;
David Turnerd2b1f351999-12-16 23:11:37 +0000420
421 FT_TRACE2(( "is missing!\n" ));
422 }
423 else
424 {
425 face->cvt_program_size = table_len;
David Turner7d3a2642002-03-20 10:49:31 +0000426 if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
David Turner2e421312000-05-26 22:13:17 +0000427 goto Exit;
Werner Lemberg78575dc2000-06-12 19:36:41 +0000428
David Turnerd2b1f351999-12-16 23:11:37 +0000429 FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
430 }
431
432 Exit:
433 return error;
David Turnere70d5532005-02-22 16:53:06 +0000434
Werner Lemberge7930922005-03-01 02:13:50 +0000435#else /* !FT_CONFIG_OPTION_BYTECODE_INTERPRETER */
436
437 FT_UNUSED( face );
438 FT_UNUSED( stream );
439
David Turnere70d5532005-02-22 16:53:06 +0000440 return 0;
Werner Lemberge7930922005-03-01 02:13:50 +0000441
David Turnere70d5532005-02-22 16:53:06 +0000442#endif
David Turnerd2b1f351999-12-16 23:11:37 +0000443 }
444
445
446/* END */