1 /***************************************************************************/
5 /* OpenType objects manager (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/ftcalc.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/fterrors.h>
23 #include <freetype/ttnameid.h>
24 #include <freetype/tttags.h>
26 #include <freetype/internal/sfnt.h>
27 #include <freetype/internal/psnames.h>
30 #ifdef FT_FLAT_COMPILE
37 #include <cff/t2objs.h>
38 #include <cff/t2load.h>
43 #include <freetype/internal/t2errors.h>
45 #include <string.h> /* for strlen() */
48 /*************************************************************************/
50 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
51 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
52 /* messages during execution. */
55 #define FT_COMPONENT trace_t2objs
58 /*************************************************************************/
62 /*************************************************************************/
65 FT_String
* T2_StrCopy( FT_Memory memory
,
66 const FT_String
* source
)
69 FT_String
* result
= 0;
70 FT_Int len
= (FT_Int
)strlen( source
);
73 if ( !ALLOC( result
, len
+ 1 ) )
75 MEM_Copy( result
, source
, len
);
84 /* this function is used to build a Unicode charmap from the glyph names */
87 FT_Error
CFF_Build_Unicode_Charmap( T2_Face face
,
89 PSNames_Interface
* psnames
)
91 CFF_Font
* font
= (CFF_Font
*)face
->extra
.data
;
92 FT_Memory memory
= FT_FACE_MEMORY(face
);
93 FT_UInt n
, num_glyphs
= face
->root
.num_glyphs
;
94 const char** glyph_names
;
96 CFF_Font_Dict
* dict
= &font
->top_font
.font_dict
;
97 FT_ULong charset_offset
;
99 FT_Stream stream
= face
->root
.stream
;
102 charset_offset
= dict
->charset_offset
;
103 if ( !charset_offset
)
105 FT_ERROR(( "CFF.Build_Unicode_Charmap: charset table is missing\n" ));
106 error
= T2_Err_Invalid_File_Format
;
110 /* allocate the charmap */
111 if ( ALLOC( face
->charmap
, ...
113 /* seek to charset table and allocate glyph names table */
114 if ( FILE_Seek( base_offset
+ charset_offset
) ||
115 ALLOC_ARRAY( glyph_names
, num_glyphs
, const char* ) )
118 /* now, read each glyph name and store it in the glyph name table */
119 if ( READ_Byte( format
) )
124 case 0: /* format 0 - one SID per glyph */
126 const char** gname
= glyph_names
;
127 const char** limit
= gname
+ num_glyphs
;
129 if ( ACCESS_Frame( num_glyphs
*2 ) )
132 for ( ; gname
< limit
; gname
++ )
133 gname
[0] = T2_Get_String( &font
->string_index
,
140 case 1: /* format 1 - sequential ranges */
141 case 2: /* format 2 - sequential ranges with 16-bit counts */
143 const char** gname
= glyph_names
;
144 const char** limit
= gname
+ num_glyphs
;
150 while (gname
< limit
)
155 if ( ACCESS_Frame( len
) )
158 first
= GET_UShort();
160 count
= GET_UShort();
166 for ( ; count
> 0; count
-- )
168 gname
[0] = T2_Get_String( &font
->string_index
,
178 default: /* unknown charset format! */
179 FT_ERROR(( "CFF: unknown charset format!\n" ));
180 error
= T2_Err_Invalid_File_Format
;
184 /* all right, the glyph names were loaded, we now need to create */
185 /* the corresponding unicode charmap.. */
188 for ( n
= 0; n
< num_glyphs
; n
++ )
189 FREE( glyph_names
[n
] );
201 FT_Encoding
find_encoding( int platform_id
,
204 typedef struct TEncoding
208 FT_Encoding encoding
;
213 const TEncoding tt_encodings
[] =
215 { TT_PLATFORM_ISO
, -1, ft_encoding_unicode
},
217 { TT_PLATFORM_APPLE_UNICODE
, -1, ft_encoding_unicode
},
219 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, ft_encoding_apple_roman
},
221 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, ft_encoding_unicode
},
222 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, ft_encoding_sjis
},
223 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, ft_encoding_gb2312
},
224 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, ft_encoding_big5
},
225 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, ft_encoding_wansung
},
226 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, ft_encoding_johab
}
229 const TEncoding
*cur
, *limit
;
233 limit
= cur
+ sizeof ( tt_encodings
) / sizeof ( tt_encodings
[0] );
235 for ( ; cur
< limit
; cur
++ )
237 if ( cur
->platform_id
== platform_id
)
239 if ( cur
->encoding_id
== encoding_id
||
240 cur
->encoding_id
== -1 )
241 return cur
->encoding
;
245 return ft_encoding_none
;
249 /*************************************************************************/
255 /* Initializes a given OpenType face object. */
258 /* stream :: The source font stream. */
260 /* face_index :: The index of the font face in the resource. */
262 /* num_params :: Number of additional generic parameters. Ignored. */
264 /* params :: Additional generic parameters. Ignored. */
267 /* face :: The newly built face object. */
270 /* FreeType error code. 0 means success. */
273 FT_Error
T2_Init_Face( FT_Stream stream
,
277 FT_Parameter
* params
)
280 SFNT_Interface
* sfnt
;
281 PSNames_Interface
* psnames
;
282 FT_Bool pure_cff
= 1;
283 FT_Bool sfnt_format
= 0;
286 sfnt
= (SFNT_Interface
*)FT_Get_Module_Interface(
287 face
->root
.driver
->root
.library
, "sfnt" );
291 psnames
= (PSNames_Interface
*)FT_Get_Module_Interface(
292 face
->root
.driver
->root
.library
, "psnames" );
294 /* create input stream from resource */
295 if ( FILE_Seek( 0 ) )
298 /* check that we have a valid OpenType file */
299 error
= sfnt
->init_face( stream
, face
, face_index
, num_params
, params
);
302 if ( face
->format_tag
!= 0x4F54544FL
) /* `OTTO'; OpenType/CFF font */
304 FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
308 /* If we are performing a simple font format check, exit immediately */
309 if ( face_index
< 0 )
314 /* now, the font can be either an OpenType/CFF font, or a SVG CEF */
315 /* font in the later case; it doesn't have a `head' table */
316 error
= face
->goto_table( face
, TTAG_head
, stream
, 0 );
321 /* Load font directory */
322 error
= sfnt
->load_face( stream
, face
,
323 face_index
, num_params
, params
);
329 /* load the `cmap' table by hand */
330 error
= sfnt
->load_charmaps( face
, stream
);
334 /* XXX: for now, we don't load the GPOS table, as OpenType Layout */
335 /* support will be added later to FreeType 2 as a separate module */
338 /* now, load the CFF part of the file */
339 error
= face
->goto_table( face
, TTAG_CFF
, stream
, 0 );
345 /* rewind to start of file; we are going to load a pure-CFF font */
346 (void)FILE_Seek( 0 );
350 /* now load and parse the CFF table in the file */
353 FT_Memory memory
= face
->root
.memory
;
356 FT_ULong base_offset
;
359 if ( ALLOC( cff
, sizeof ( *cff
) ) )
362 base_offset
= FILE_Pos();
364 face
->extra
.data
= cff
;
365 error
= T2_Load_CFF_Font( stream
, face_index
, cff
);
369 /* Complement the root flags with some interesting information. */
370 /* Note that this is only necessary for pure CFF and CEF fonts */
375 CFF_Font_Dict
* dict
= &cff
->top_font
.font_dict
;
378 /* we need the `PSNames' module for pure-CFF and CEF formats */
381 FT_ERROR(( "T2_Init_Face:" ));
382 FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
384 FT_ERROR(( " without the `PSNames' module\n" ));
388 /* compute number of glyphs */
389 if ( dict
->cid_registry
)
390 root
->num_glyphs
= dict
->cid_count
;
392 root
->num_glyphs
= cff
->charstrings_index
.count
;
394 /* set global bbox, as well as EM size */
395 root
->units_per_EM
= (FT_UInt
)FT_DivFix( 1000L << 16,
396 dict
->font_matrix
.yy
) >> 16;
397 root
->bbox
= dict
->font_bbox
;
398 root
->ascender
= (FT_Short
)root
->bbox
.yMax
;
399 root
->descender
= (FT_Short
)root
->bbox
.yMin
;
401 /* retrieve font family & style name */
402 root
->family_name
= T2_Get_Name( &cff
->name_index
, face_index
);
403 if ( dict
->cid_registry
)
405 root
->style_name
= T2_StrCopy( memory
, "Regular" ); /* XXXX */
409 root
->style_name
= T2_Get_String( &cff
->string_index
,
414 /*******************************************************************/
416 /* Compute face flags. */
418 flags
= FT_FACE_FLAG_SCALABLE
| /* scalable outlines */
419 FT_FACE_FLAG_HORIZONTAL
; /* horizontal data */
422 flags
|= FT_FACE_FLAG_SFNT
;
424 /* fixed width font? */
425 if ( dict
->is_fixed_pitch
)
426 flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
428 /* XXXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
430 /* kerning available? */
431 if ( face
->kern_pairs
)
432 flags
|= FT_FACE_FLAG_KERNING
;
435 root
->face_flags
= flags
;
437 /*******************************************************************/
439 /* Compute style flags. */
443 if ( dict
->italic_angle
)
444 flags
|= FT_STYLE_FLAG_ITALIC
;
446 /* XXX: may not be correct */
447 if ( cff
->top_font
.private_dict
.force_bold
)
448 flags
|= FT_STYLE_FLAG_BOLD
;
450 root
->style_flags
= flags
;
452 /* set the charmaps if any */
455 /*****************************************************************/
457 /* Polish the charmaps. */
459 /* Try to set the charmap encoding according to the platform & */
460 /* encoding ID of each charmap. */
466 charmap
= face
->charmaps
;
467 root
->num_charmaps
= face
->num_charmaps
;
469 /* allocate table of pointers */
470 if ( ALLOC_ARRAY( root
->charmaps
, root
->num_charmaps
, FT_CharMap
) )
473 for ( n
= 0; n
< root
->num_charmaps
; n
++, charmap
++ )
475 FT_Int platform
= charmap
->cmap
.platformID
;
476 FT_Int encoding
= charmap
->cmap
.platformEncodingID
;
479 charmap
->root
.face
= (FT_Face
)face
;
480 charmap
->root
.platform_id
= platform
;
481 charmap
->root
.encoding_id
= encoding
;
482 charmap
->root
.encoding
= find_encoding( platform
, encoding
);
484 /* now, set root->charmap with a unicode charmap */
485 /* wherever available */
486 if ( !root
->charmap
&&
487 charmap
->root
.encoding
== ft_encoding_unicode
)
488 root
->charmap
= (FT_CharMap
)charmap
;
490 root
->charmaps
[n
] = (FT_CharMap
)charmap
;
500 error
= FT_Err_Unknown_File_Format
;
505 /*************************************************************************/
511 /* Finalizes a given face object. */
514 /* face :: A pointer to the face object to destroy. */
517 void T2_Done_Face( T2_Face face
)
519 FT_Memory memory
= face
->root
.memory
;
520 SFNT_Interface
* sfnt
= (SFNT_Interface
*)face
->sfnt
;
524 sfnt
->done_face( face
);
527 CFF_Font
* cff
= (CFF_Font
*)face
->extra
.data
;
532 T2_Done_CFF_Font( cff
);
533 FREE( face
->extra
.data
);
539 /*************************************************************************/
545 /* Initializes a given OpenType driver object. */
548 /* driver :: A handle to the target driver object. */
551 /* FreeType error code. 0 means success. */
554 FT_Error
T2_Init_Driver( T2_Driver driver
)
556 /* init extension registry if needed */
558 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
560 return TT_Init_Extensions( driver
);
572 /*************************************************************************/
578 /* Finalizes a given OpenType driver. */
581 /* driver :: A handle to the target OpenType driver. */
584 void T2_Done_Driver( T2_Driver driver
)
586 /* destroy extensions registry if needed */
588 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
590 TT_Done_Extensions( driver
);