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 <cff/t2load.h>
36 #include <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
);