ReactOS 0.4.15-dev-7788-g1ad9096
ttpload.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* ttpload.c */
4/* */
5/* TrueType-specific tables loader (body). */
6/* */
7/* Copyright 1996-2018 by */
8/* 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/***************************************************************************/
17
18
19#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
24
25#include "ttpload.h"
26
27#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
28#include "ttgxvar.h"
29#endif
30
31#include "tterrors.h"
32
33
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 /* */
40#undef FT_COMPONENT
41#define FT_COMPONENT trace_ttpload
42
43
44 /*************************************************************************/
45 /* */
46 /* <Function> */
47 /* tt_face_load_loca */
48 /* */
49 /* <Description> */
50 /* Load the locations table. */
51 /* */
52 /* <InOut> */
53 /* face :: A handle to the target face object. */
54 /* */
55 /* <Input> */
56 /* stream :: The input stream. */
57 /* */
58 /* <Return> */
59 /* FreeType error code. 0 means success. */
60 /* */
64 {
66 FT_ULong table_len;
68
69
70 /* we need the size of the `glyf' table for malformed `loca' tables */
71 error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
72
73 /* it is possible that a font doesn't have a glyf table at all */
74 /* or its size is zero */
75 if ( FT_ERR_EQ( error, Table_Missing ) )
76 {
77 face->glyf_len = 0;
78 face->glyf_offset = 0;
79 }
80 else if ( error )
81 goto Exit;
82 else
83 {
84#ifdef FT_CONFIG_OPTION_INCREMENTAL
85 if ( face->root.internal->incremental_interface )
86 face->glyf_offset = 0;
87 else
88#endif
89 face->glyf_offset = FT_STREAM_POS();
90 }
91
92 FT_TRACE2(( "Locations " ));
93 error = face->goto_table( face, TTAG_loca, stream, &table_len );
94 if ( error )
95 {
96 error = FT_THROW( Locations_Missing );
97 goto Exit;
98 }
99
100 if ( face->header.Index_To_Loc_Format != 0 )
101 {
102 shift = 2;
103
104 if ( table_len >= 0x40000L )
105 {
106 FT_TRACE2(( "table too large\n" ));
107 table_len = 0x3FFFFL;
108 }
109 face->num_locations = table_len >> shift;
110 }
111 else
112 {
113 shift = 1;
114
115 if ( table_len >= 0x20000L )
116 {
117 FT_TRACE2(( "table too large\n" ));
118 table_len = 0x1FFFFL;
119 }
120 face->num_locations = table_len >> shift;
121 }
122
123 if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
124 {
125 FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
126 face->num_locations - 1, face->root.num_glyphs ));
127
128 /* we only handle the case where `maxp' gives a larger value */
129 if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
130 {
131 FT_ULong new_loca_len =
132 ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;
133
134 TT_Table entry = face->dir_tables;
135 TT_Table limit = entry + face->num_tables;
136
138 FT_Long dist = 0x7FFFFFFFL;
139 FT_Bool found = 0;
140
141
142 /* compute the distance to next table in font file */
143 for ( ; entry < limit; entry++ )
144 {
145 FT_Long diff = (FT_Long)entry->Offset - pos;
146
147
148 if ( diff > 0 && diff < dist )
149 {
150 dist = diff;
151 found = 1;
152 }
153 }
154
155 if ( !found )
156 {
157 /* `loca' is the last table */
158 dist = (FT_Long)stream->size - pos;
159 }
160
161 if ( new_loca_len <= (FT_ULong)dist )
162 {
163 face->num_locations = (FT_ULong)face->root.num_glyphs + 1;
164 table_len = new_loca_len;
165
166 FT_TRACE2(( "adjusting num_locations to %d\n",
167 face->num_locations ));
168 }
169 else
170 {
171 face->root.num_glyphs = face->num_locations
172 ? (FT_Long)face->num_locations - 1 : 0;
173
174 FT_TRACE2(( "adjusting num_glyphs to %d\n",
175 face->root.num_glyphs ));
176 }
177 }
178 }
179
180 /*
181 * Extract the frame. We don't need to decompress it since
182 * we are able to parse it directly.
183 */
184 if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
185 goto Exit;
186
187 FT_TRACE2(( "loaded\n" ));
188
189 Exit:
190 return error;
191 }
192
193
196 FT_UInt gindex,
197 FT_UInt *asize )
198 {
199 FT_ULong pos1, pos2;
200 FT_Byte* p;
201 FT_Byte* p_limit;
202
203
204 pos1 = pos2 = 0;
205
206 if ( gindex < face->num_locations )
207 {
208 if ( face->header.Index_To_Loc_Format != 0 )
209 {
210 p = face->glyph_locations + gindex * 4;
211 p_limit = face->glyph_locations + face->num_locations * 4;
212
213 pos1 = FT_NEXT_ULONG( p );
214 pos2 = pos1;
215
216 if ( p + 4 <= p_limit )
217 pos2 = FT_NEXT_ULONG( p );
218 }
219 else
220 {
221 p = face->glyph_locations + gindex * 2;
222 p_limit = face->glyph_locations + face->num_locations * 2;
223
224 pos1 = FT_NEXT_USHORT( p );
225 pos2 = pos1;
226
227 if ( p + 2 <= p_limit )
228 pos2 = FT_NEXT_USHORT( p );
229
230 pos1 <<= 1;
231 pos2 <<= 1;
232 }
233 }
234
235 /* Check broken location data. */
236 if ( pos1 > face->glyf_len )
237 {
238 FT_TRACE1(( "tt_face_get_location:"
239 " too large offset (0x%08lx) found for glyph index %ld,\n"
240 " "
241 " exceeding the end of `glyf' table (0x%08lx)\n",
242 pos1, gindex, face->glyf_len ));
243 *asize = 0;
244 return 0;
245 }
246
247 if ( pos2 > face->glyf_len )
248 {
249 /* We try to sanitize the last `loca' entry. */
250 if ( gindex == face->num_locations - 2 )
251 {
252 FT_TRACE1(( "tt_face_get_location:"
253 " too large size (%ld bytes) found for glyph index %ld,\n"
254 " "
255 " truncating at the end of `glyf' table to %ld bytes\n",
256 pos2 - pos1, gindex, face->glyf_len - pos1 ));
257 pos2 = face->glyf_len;
258 }
259 else
260 {
261 FT_TRACE1(( "tt_face_get_location:"
262 " too large offset (0x%08lx) found for glyph index %ld,\n"
263 " "
264 " exceeding the end of `glyf' table (0x%08lx)\n",
265 pos2, gindex + 1, face->glyf_len ));
266 *asize = 0;
267 return 0;
268 }
269 }
270
271 /* The `loca' table must be ordered; it refers to the length of */
272 /* an entry as the difference between the current and the next */
273 /* position. However, there do exist (malformed) fonts which */
274 /* don't obey this rule, so we are only able to provide an */
275 /* upper bound for the size. */
276 /* */
277 /* We get (intentionally) a wrong, non-zero result in case the */
278 /* `glyf' table is missing. */
279 if ( pos2 >= pos1 )
280 *asize = (FT_UInt)( pos2 - pos1 );
281 else
282 *asize = (FT_UInt)( face->glyf_len - pos1 );
283
284 return pos1;
285 }
286
287
288 FT_LOCAL_DEF( void )
290 {
291 FT_Stream stream = face->root.stream;
292
293
294 FT_FRAME_RELEASE( face->glyph_locations );
295 face->num_locations = 0;
296 }
297
298
299
300 /*************************************************************************/
301 /* */
302 /* <Function> */
303 /* tt_face_load_cvt */
304 /* */
305 /* <Description> */
306 /* Load the control value table into a face object. */
307 /* */
308 /* <InOut> */
309 /* face :: A handle to the target face object. */
310 /* */
311 /* <Input> */
312 /* stream :: A handle to the input stream. */
313 /* */
314 /* <Return> */
315 /* FreeType error code. 0 means success. */
316 /* */
320 {
321#ifdef TT_USE_BYTECODE_INTERPRETER
322
324 FT_Memory memory = stream->memory;
325 FT_ULong table_len;
326
327
328 FT_TRACE2(( "CVT " ));
329
330 error = face->goto_table( face, TTAG_cvt, stream, &table_len );
331 if ( error )
332 {
333 FT_TRACE2(( "is missing\n" ));
334
335 face->cvt_size = 0;
336 face->cvt = NULL;
338
339 goto Exit;
340 }
341
342 face->cvt_size = table_len / 2;
343
344 if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
345 goto Exit;
346
347 if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
348 goto Exit;
349
350 {
351 FT_Short* cur = face->cvt;
352 FT_Short* limit = cur + face->cvt_size;
353
354
355 for ( ; cur < limit; cur++ )
356 *cur = FT_GET_SHORT();
357 }
358
360 FT_TRACE2(( "loaded\n" ));
361
362#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
363 if ( face->doblend )
364 error = tt_face_vary_cvt( face, stream );
365#endif
366
367 Exit:
368 return error;
369
370#else /* !TT_USE_BYTECODE_INTERPRETER */
371
372 FT_UNUSED( face );
373 FT_UNUSED( stream );
374
375 return FT_Err_Ok;
376
377#endif
378 }
379
380
381 /*************************************************************************/
382 /* */
383 /* <Function> */
384 /* tt_face_load_fpgm */
385 /* */
386 /* <Description> */
387 /* Load the font program. */
388 /* */
389 /* <InOut> */
390 /* face :: A handle to the target face object. */
391 /* */
392 /* <Input> */
393 /* stream :: A handle to the input stream. */
394 /* */
395 /* <Return> */
396 /* FreeType error code. 0 means success. */
397 /* */
401 {
402#ifdef TT_USE_BYTECODE_INTERPRETER
403
405 FT_ULong table_len;
406
407
408 FT_TRACE2(( "Font program " ));
409
410 /* The font program is optional */
411 error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
412 if ( error )
413 {
414 face->font_program = NULL;
415 face->font_program_size = 0;
417
418 FT_TRACE2(( "is missing\n" ));
419 }
420 else
421 {
422 face->font_program_size = table_len;
423 if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
424 goto Exit;
425
426 FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
427 }
428
429 Exit:
430 return error;
431
432#else /* !TT_USE_BYTECODE_INTERPRETER */
433
434 FT_UNUSED( face );
435 FT_UNUSED( stream );
436
437 return FT_Err_Ok;
438
439#endif
440 }
441
442
443 /*************************************************************************/
444 /* */
445 /* <Function> */
446 /* tt_face_load_prep */
447 /* */
448 /* <Description> */
449 /* Load the cvt program. */
450 /* */
451 /* <InOut> */
452 /* face :: A handle to the target face object. */
453 /* */
454 /* <Input> */
455 /* stream :: A handle to the input stream. */
456 /* */
457 /* <Return> */
458 /* FreeType error code. 0 means success. */
459 /* */
463 {
464#ifdef TT_USE_BYTECODE_INTERPRETER
465
467 FT_ULong table_len;
468
469
470 FT_TRACE2(( "Prep program " ));
471
472 error = face->goto_table( face, TTAG_prep, stream, &table_len );
473 if ( error )
474 {
475 face->cvt_program = NULL;
476 face->cvt_program_size = 0;
478
479 FT_TRACE2(( "is missing\n" ));
480 }
481 else
482 {
483 face->cvt_program_size = table_len;
484 if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
485 goto Exit;
486
487 FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
488 }
489
490 Exit:
491 return error;
492
493#else /* !TT_USE_BYTECODE_INTERPRETER */
494
495 FT_UNUSED( face );
496 FT_UNUSED( stream );
497
498 return FT_Err_Ok;
499
500#endif
501 }
502
503
504 /*************************************************************************/
505 /* */
506 /* <Function> */
507 /* tt_face_load_hdmx */
508 /* */
509 /* <Description> */
510 /* Load the `hdmx' table into the face object. */
511 /* */
512 /* <Input> */
513 /* face :: A handle to the target face object. */
514 /* */
515 /* stream :: A handle to the input stream. */
516 /* */
517 /* <Return> */
518 /* FreeType error code. 0 means success. */
519 /* */
520
524 {
526 FT_Memory memory = stream->memory;
527 FT_UInt nn, num_records;
528 FT_ULong table_size, record_size;
529 FT_Byte* p;
530 FT_Byte* limit;
531
532
533 /* this table is optional */
534 error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
535 if ( error || table_size < 8 )
536 return FT_Err_Ok;
537
538 if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
539 goto Exit;
540
541 p = face->hdmx_table;
542 limit = p + table_size;
543
544 /* Given that `hdmx' tables are losing its importance (for example, */
545 /* variation fonts introduced in OpenType 1.8 must not have this */
546 /* table) we no longer test for a correct `version' field. */
547 p += 2;
548 num_records = FT_NEXT_USHORT( p );
549 record_size = FT_NEXT_ULONG( p );
550
551 /* The maximum number of bytes in an hdmx device record is the */
552 /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus */
553 /* explaining why `record_size' is a long (which we read as */
554 /* unsigned long for convenience). In practice, two bytes are */
555 /* sufficient to hold the size value. */
556 /* */
557 /* There are at least two fonts, HANNOM-A and HANNOM-B version */
558 /* 2.0 (2005), which get this wrong: The upper two bytes of */
559 /* the size value are set to 0xFF instead of 0x00. We catch */
560 /* and fix this. */
561
562 if ( record_size >= 0xFFFF0000UL )
563 record_size &= 0xFFFFU;
564
565 /* The limit for `num_records' is a heuristic value. */
566 if ( num_records > 255 ||
567 ( num_records > 0 &&
568 ( record_size > 0x10001L ||
569 record_size < 4 ) ) )
570 {
571 error = FT_THROW( Invalid_File_Format );
572 goto Fail;
573 }
574
575 if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
576 goto Fail;
577
578 for ( nn = 0; nn < num_records; nn++ )
579 {
580 if ( p + record_size > limit )
581 break;
582
583 face->hdmx_record_sizes[nn] = p[0];
584 p += record_size;
585 }
586
587 face->hdmx_record_count = nn;
588 face->hdmx_table_size = table_size;
589 face->hdmx_record_size = record_size;
590
591 Exit:
592 return error;
593
594 Fail:
595 FT_FRAME_RELEASE( face->hdmx_table );
596 face->hdmx_table_size = 0;
597 goto Exit;
598 }
599
600
601 FT_LOCAL_DEF( void )
603 {
604 FT_Stream stream = face->root.stream;
605 FT_Memory memory = stream->memory;
606
607
608 FT_FREE( face->hdmx_record_sizes );
609 FT_FRAME_RELEASE( face->hdmx_table );
610 }
611
612
613 /*************************************************************************/
614 /* */
615 /* Return the advance width table for a given pixel size if it is found */
616 /* in the font's `hdmx' table (if any). */
617 /* */
620 FT_UInt ppem,
621 FT_UInt gindex )
622 {
623 FT_UInt nn;
625 FT_ULong record_size = face->hdmx_record_size;
626 FT_Byte* record = face->hdmx_table + 8;
627
628
629 for ( nn = 0; nn < face->hdmx_record_count; nn++ )
630 if ( face->hdmx_record_sizes[nn] == ppem )
631 {
632 gindex += 2;
633 if ( gindex < record_size )
634 result = record + nn * record_size + gindex;
635 break;
636 }
637
638 return result;
639 }
640
641
642/* END */
#define NULL
Definition: types.h:112
int Fail
Definition: ehthrow.cxx:24
return FT_Err_Ok
Definition: ftbbox.c:511
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:388
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_THROW(e)
Definition: ftdebug.h:213
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
#define FT_TRACE1(varformat)
Definition: ftdebug.h:158
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:333
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:512
#define FT_FRAME_RELEASE(bytes)
Definition: ftstream.h:526
#define FT_NEXT_USHORT(buffer)
Definition: ftstream.h:226
#define FT_STREAM_POS()
Definition: ftstream.h:486
#define FT_GET_SHORT()
Definition: ftstream.h:288
#define FT_FRAME_EXIT()
Definition: ftstream.h:517
#define FT_FRAME_EXTRACT(size, bytes)
Definition: ftstream.h:520
#define FT_NEXT_ULONG(buffer)
Definition: ftstream.h:238
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
#define FT_ERR_EQ(x, e)
Definition: fttypes.h:591
int FT_Error
Definition: fttypes.h:300
signed long FT_Long
Definition: fttypes.h:242
signed short FT_Short
Definition: fttypes.h:198
unsigned int FT_UInt
Definition: fttypes.h:231
signed int FT_Int
Definition: fttypes.h:220
FxCollectionEntry * cur
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLint limit
Definition: glext.h:10326
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
uint32_t entry
Definition: isohybrid.c:63
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static char memory[1024 *256]
Definition: process.c:116
#define shift
Definition: input.c:1755
LOCAL int table_size
Definition: write.c:65
static void Exit(void)
Definition: sock.c:1330
Definition: parse.h:23
unsigned int size
Definition: parse.h:27
tt_face_load_prep(TT_Face face, FT_Stream stream)
Definition: ttpload.c:461
tt_face_load_cvt(TT_Face face, FT_Stream stream)
Definition: ttpload.c:318
tt_face_free_hdmx(TT_Face face)
Definition: ttpload.c:602
tt_face_get_device_metrics(TT_Face face, FT_UInt ppem, FT_UInt gindex)
Definition: ttpload.c:619
tt_face_load_fpgm(TT_Face face, FT_Stream stream)
Definition: ttpload.c:399
tt_face_load_hdmx(TT_Face face, FT_Stream stream)
Definition: ttpload.c:522
tt_face_done_loca(TT_Face face)
Definition: ttpload.c:289
tt_face_load_loca(TT_Face face, FT_Stream stream)
Definition: ttpload.c:62
tt_face_get_location(TT_Face face, FT_UInt gindex, FT_UInt *asize)
Definition: ttpload.c:195
#define TTAG_hdmx
Definition: tttags.h:66
#define TTAG_prep
Definition: tttags.h:92
#define TTAG_cvt
Definition: tttags.h:50
#define TTAG_glyf
Definition: tttags.h:61
#define TTAG_fpgm
Definition: tttags.h:57
#define TTAG_loca
Definition: tttags.h:74