1 /***************************************************************************/
5 /* TrueType glyph data/program tables loader (body). */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/ftobjs.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/internal/psnames.h>
24 #include <freetype/internal/t2errors.h>
25 #include <freetype/tttags.h>
28 #ifdef FT_FLAT_COMPILE
35 #include <freetype/src/cff/t2load.h>
36 #include <freetype/src/cff/t2parse.h>
41 /*************************************************************************/
43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
44 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
45 /* messages during execution. */
48 #define FT_COMPONENT trace_t2load
51 /* read a CFF offset from memory */
53 FT_ULong t2_get_offset( FT_Byte* p,
59 for ( result = 0; off_size > 0; off_size-- )
70 FT_Error t2_new_cff_index( CFF_Index* index,
75 FT_Memory memory = stream->memory;
79 MEM_Set( index, 0, sizeof ( *index ) );
81 index->stream = stream;
82 if ( !READ_UShort( count ) &&
91 /* there is at least one element; read the offset size, */
92 /* then access the offset table to compute the index's total size */
93 if ( READ_Byte( offsize ) )
96 index->stream = stream;
98 index->off_size = offsize;
99 data_size = (FT_ULong)( count + 1 ) * offsize;
101 if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
102 ACCESS_Frame( data_size ) )
105 poff = index->offsets;
106 p = (FT_Byte*)stream->cursor;
108 for ( ; (FT_Short)count >= 0; count-- )
110 poff[0] = t2_get_offset( p, offsize );
117 index->data_offset = FILE_Pos();
118 data_size = poff[-1] - 1;
123 if ( EXTRACT_Frame( data_size, index->bytes ) )
129 (void)FILE_Skip( data_size );
135 FREE( index->offsets );
142 void t2_done_cff_index( CFF_Index* index )
146 FT_Stream stream = index->stream;
147 FT_Memory memory = stream->memory;
151 RELEASE_Frame( index->bytes );
153 FREE( index->offsets );
154 MEM_Set( index, 0, sizeof ( *index ) );
160 FT_Error t2_explicit_cff_index( CFF_Index* index,
164 FT_Memory memory = index->stream->memory;
165 FT_UInt n, offset, old_offset;
171 if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) )
174 for ( n = 0; n <= index->count; n++ )
176 offset = index->offsets[n];
180 t[n] = index->bytes + offset - 1;
192 FT_Error T2_Access_Element( CFF_Index* index,
195 FT_ULong* pbyte_len )
200 if ( index && index->count > element )
202 /* compute start and end offsets */
206 off1 = index->offsets[element];
212 off2 = index->offsets[element];
214 } while ( off2 == 0 && element < index->count );
223 *pbyte_len = off2 - off1;
227 /* this index was completely loaded in memory, that's easy */
228 *pbytes = index->bytes + off1 - 1;
232 /* this index is still on disk/file, access it through a frame */
233 FT_Stream stream = index->stream;
236 if ( FILE_Seek( index->data_offset + off1 - 1 ) ||
237 EXTRACT_Frame( off2 - off1, *pbytes ) )
243 /* empty index element */
249 error = T2_Err_Invalid_Argument;
257 void T2_Forget_Element( CFF_Index* index,
260 if ( index->bytes == 0 )
262 FT_Stream stream = index->stream;
265 RELEASE_Frame( *pbytes );
271 FT_String* T2_Get_Name( CFF_Index* index,
274 FT_Memory memory = index->stream->memory;
281 error = T2_Access_Element( index, element, &bytes, &byte_len );
285 if ( !ALLOC( name, byte_len + 1 ) )
287 MEM_Copy( name, bytes, byte_len );
290 T2_Forget_Element( index, &bytes );
298 FT_String* T2_Get_String( CFF_Index* index,
300 PSNames_Interface* interface )
302 /* if it is not a standard string, return it */
304 return T2_Get_Name( index, sid - 390 );
306 /* that's a standard string, fetch a copy from the PSName module */
309 const char* adobe_name = interface->adobe_std_strings( sid );
315 FT_Memory memory = index->stream->memory;
319 len = (FT_UInt)strlen( adobe_name );
320 if ( !ALLOC( name, len + 1 ) )
322 MEM_Copy( name, adobe_name, len );
332 /*************************************************************************/
333 /*************************************************************************/
335 /*** FD Select table support ***/
337 /*************************************************************************/
338 /*************************************************************************/
342 void CFF_Done_FD_Select( CFF_FD_Select* select,
346 RELEASE_Frame( select->data );
348 select->data_size = 0;
350 select->range_count = 0;
355 FT_Error CFF_Load_FD_Select( CFF_FD_Select* select,
366 if ( FILE_Seek( offset ) || READ_Byte( format ) )
369 select->format = format;
370 select->cache_count = 0; /* clear cache */
374 case 0: /* format 0, that's simple */
375 select->data_size = num_glyphs;
378 case 3: /* format 3, a tad more complex */
379 if ( READ_UShort( num_ranges ) )
382 select->data_size = num_ranges * 3 + 2;
385 if ( EXTRACT_Frame( select->data_size, select->data ) )
389 default: /* hmm... that's wrong */
390 error = T2_Err_Invalid_File_Format;
399 FT_Byte CFF_Get_FD( CFF_FD_Select* select,
400 FT_UInt glyph_index )
405 switch ( select->format )
408 fd = select->data[glyph_index];
412 /* first, compare to cache */
413 if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count )
415 fd = select->cache_fd;
419 /* then, lookup the ranges array */
421 FT_Byte* p = select->data;
422 FT_Byte* p_limit = p + select->data_size;
424 FT_UInt first, limit;
427 first = NEXT_UShort( p );
430 if ( glyph_index < first )
434 limit = NEXT_UShort( p );
436 if ( glyph_index < limit )
441 select->cache_first = first;
442 select->cache_count = limit-first;
443 select->cache_fd = fd2;
448 } while ( p < p_limit );
460 /*************************************************************************/
461 /*************************************************************************/
463 /*** CFF font support ***/
465 /*************************************************************************/
466 /*************************************************************************/
470 FT_Error CFF_Load_SubFont( CFF_SubFont* font,
474 FT_ULong base_offset )
480 CFF_Font_Dict* top = &font->font_dict;
481 CFF_Private* priv = &font->private_dict;
484 T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->font_dict );
487 MEM_Set( top, 0, sizeof ( *top ) );
489 top->underline_position = -100;
490 top->underline_thickness = 50;
491 top->charstring_type = 2;
492 top->font_matrix.xx = 0x10000L;
493 top->font_matrix.yy = 0x10000L;
494 top->cid_count = 8720;
496 error = T2_Access_Element( index, font_index, &dict, &dict_len ) ||
497 T2_Parser_Run( &parser, dict, dict + dict_len );
499 T2_Forget_Element( index, &dict );
504 /* if it is a CID font, we stop there */
505 if ( top->cid_registry )
508 /* parse the private dictionary, if any */
509 if ( top->private_offset && top->private_size )
512 MEM_Set( priv, 0, sizeof ( *priv ) );
514 priv->blue_shift = 7;
517 priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
518 priv->blue_scale = (FT_Fixed)0.039625 * 0x10000L;
520 T2_Parser_Init( &parser, T2CODE_PRIVATE, priv );
522 if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
523 ACCESS_Frame( font->font_dict.private_size ) )
526 error = T2_Parser_Run( &parser,
527 (FT_Byte*)stream->cursor,
528 (FT_Byte*)stream->limit );
534 /* read the local subrs, if any */
535 if ( priv->local_subrs_offset )
537 if ( FILE_Seek( base_offset + top->private_offset +
538 priv->local_subrs_offset ) )
541 error = t2_new_cff_index( &font->local_subrs_index, stream, 1 );
545 font->num_local_subrs = font->local_subrs_index.count;
546 error = t2_explicit_cff_index( &font->local_subrs_index,
547 &font->local_subrs );
556 void CFF_Done_SubFont( FT_Memory memory,
557 CFF_SubFont* subfont )
561 t2_done_cff_index( &subfont->local_subrs_index );
562 FREE( subfont->local_subrs );
568 FT_Error T2_Load_CFF_Font( FT_Stream stream,
572 static const FT_Frame_Field cff_header_fields[] =
575 FT_FRAME_BYTE( CFF_Font, version_major ),
576 FT_FRAME_BYTE( CFF_Font, version_minor ),
577 FT_FRAME_BYTE( CFF_Font, header_size ),
578 FT_FRAME_BYTE( CFF_Font, absolute_offsize ),
583 FT_Memory memory = stream->memory;
584 FT_ULong base_offset;
588 MEM_Set( font, 0, sizeof ( *font ) );
589 font->stream = stream;
590 font->memory = memory;
591 dict = &font->top_font.font_dict;
592 base_offset = FILE_Pos();
594 /* read CFF font header */
595 if ( READ_Fields( cff_header_fields, font ) )
599 if ( font->version_major != 1 ||
600 font->header_size < 4 ||
601 font->absolute_offsize > 4 )
603 FT_TRACE2(( "[not a CFF font header!]\n" ));
604 error = FT_Err_Unknown_File_Format;
608 /* skip the rest of the header */
609 (void)FILE_Skip( font->header_size - 4 );
611 /* read the name, top dict, string and global subrs index */
612 error = t2_new_cff_index( &font->name_index, stream, 0 ) ||
613 t2_new_cff_index( &font->font_dict_index, stream, 0 ) ||
614 t2_new_cff_index( &font->string_index, stream, 0 ) ||
615 t2_new_cff_index( &font->global_subrs_index, stream, 1 );
619 /* well, we don't really forget the `disabled' fonts... */
620 font->num_faces = font->name_index.count;
621 if ( face_index >= (FT_Int)font->num_faces )
623 FT_ERROR(( "T2_Load_CFF_Font: incorrect face index = %d\n",
625 error = T2_Err_Invalid_Argument;
628 /* in case of a font format check, simply exit now */
629 if ( face_index < 0 )
632 /* now, parse the top-level font dictionary */
633 error = CFF_Load_SubFont( &font->top_font,
634 &font->font_dict_index,
641 /* now, check for a CID font */
642 if ( dict->cid_registry )
649 /* this is a CID-keyed font, we must now allocate a table of */
650 /* sub-fonts, then load each of them separately */
651 if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
654 error = t2_new_cff_index( &fd_index, stream, 0 );
658 if ( fd_index.count > CFF_MAX_CID_FONTS )
660 FT_ERROR(( "T2_Load_CFF_Font: FD array too large in CID font\n" ));
664 /* allocate & read each font dict independently */
665 font->num_subfonts = fd_index.count;
666 if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
669 /* setup pointer table */
670 for ( index = 0; index < fd_index.count; index++ )
671 font->subfonts[index] = sub + index;
673 /* now load each sub font independently */
674 for ( index = 0; index < fd_index.count; index++ )
676 sub = font->subfonts[index];
677 error = CFF_Load_SubFont( sub, &fd_index, index,
678 stream, base_offset );
683 /* now load the FD Select array */
684 error = CFF_Load_FD_Select( &font->fd_select,
687 base_offset + dict->cid_fd_select_offset );
690 t2_done_cff_index( &fd_index );
696 font->num_subfonts = 0;
698 /* read the charstrings index now */
699 if ( dict->charstrings_offset == 0 )
701 FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" ));
702 error = FT_Err_Unknown_File_Format;
706 if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
709 error = t2_new_cff_index( &font->charstrings_index, stream, 0 );
713 /* explicit the global subrs */
714 font->num_global_subrs = font->global_subrs_index.count;
715 font->num_glyphs = font->charstrings_index.count;
717 error = t2_explicit_cff_index( &font->global_subrs_index,
718 &font->global_subrs ) ;
723 /* get the font name */
724 font->font_name = T2_Get_Name( &font->name_index, face_index );
732 void T2_Done_CFF_Font( CFF_Font* font )
734 FT_Memory memory = font->memory;
738 t2_done_cff_index( &font->global_subrs_index );
739 t2_done_cff_index( &font->string_index );
740 t2_done_cff_index( &font->font_dict_index );
741 t2_done_cff_index( &font->name_index );
742 t2_done_cff_index( &font->charstrings_index );
744 /* release font dictionaries */
745 for ( index = 0; index < font->num_subfonts; index++ )
746 CFF_Done_SubFont( memory, font->subfonts[index] );
748 CFF_Done_SubFont( memory, &font->top_font );
750 CFF_Done_FD_Select( &font->fd_select, font->stream );
752 FREE( font->global_subrs );
753 FREE( font->font_name );