David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 1 | /***************************************************************************/ |
| 2 | /* */ |
| 3 | /* cffobjs.c */ |
| 4 | /* */ |
| 5 | /* OpenType objects manager (body). */ |
| 6 | /* */ |
Werner Lemberg | 415235d | 2001-06-28 17:49:10 +0000 | [diff] [blame] | 7 | /* Copyright 1996-2001 by */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 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 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 18 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 19 | #include <ft2build.h> |
| 20 | #include FT_INTERNAL_DEBUG_H |
| 21 | #include FT_INTERNAL_CALC_H |
| 22 | #include FT_INTERNAL_STREAM_H |
| 23 | #include FT_ERRORS_H |
David Turner | 6ce03ef | 2001-03-20 14:50:04 +0000 | [diff] [blame] | 24 | #include FT_TRUETYPE_IDS_H |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 25 | #include FT_TRUETYPE_TAGS_H |
| 26 | #include FT_INTERNAL_SFNT_H |
| 27 | #include FT_INTERNAL_POSTSCRIPT_NAMES_H |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 28 | #include FT_INTERNAL_POSTSCRIPT_HINTS_H |
David Turner | 8d3a401 | 2001-03-20 11:14:24 +0000 | [diff] [blame] | 29 | #include "cffobjs.h" |
| 30 | #include "cffload.h" |
Werner Lemberg | 1f7f0e8 | 2001-06-06 17:30:41 +0000 | [diff] [blame] | 31 | |
| 32 | #include "cfferrs.h" |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 33 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 34 | #include <string.h> /* for strlen() */ |
| 35 | |
| 36 | |
| 37 | /*************************************************************************/ |
| 38 | /* */ |
| 39 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| 40 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| 41 | /* messages during execution. */ |
| 42 | /* */ |
| 43 | #undef FT_COMPONENT |
Tom Kacvinsky | 8d1f604 | 2001-01-03 00:21:59 +0000 | [diff] [blame] | 44 | #define FT_COMPONENT trace_cffobjs |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 45 | |
| 46 | |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 47 | |
| 48 | |
| 49 | /*************************************************************************/ |
| 50 | /* */ |
| 51 | /* SIZE FUNCTIONS */ |
| 52 | /* */ |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 53 | /* Note that we store the global hints in the size's "internal" root */ |
| 54 | /* field. */ |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 55 | /* */ |
| 56 | /*************************************************************************/ |
| 57 | |
| 58 | |
| 59 | static PSH_Globals_Funcs |
| 60 | CFF_Size_Get_Globals_Funcs( CFF_Size size ) |
| 61 | { |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 62 | CFF_Face face = (CFF_Face)size->face; |
David Turner | ab4fc4d | 2002-03-14 08:57:10 +0000 | [diff] [blame] | 63 | CFF_Font font = (CFF_FontRec *)face->extra.data; |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 64 | PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; |
| 65 | FT_Module module; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 66 | |
| 67 | |
| 68 | module = FT_Get_Module( size->face->driver->root.library, |
| 69 | "pshinter" ); |
| 70 | return ( module && pshinter && pshinter->get_globals_funcs ) |
| 71 | ? pshinter->get_globals_funcs( module ) |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 72 | : 0; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 76 | FT_LOCAL_DEF( void ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 77 | CFF_Size_Done( CFF_Size size ) |
| 78 | { |
| 79 | if ( size->internal ) |
| 80 | { |
| 81 | PSH_Globals_Funcs funcs; |
| 82 | |
| 83 | |
| 84 | funcs = CFF_Size_Get_Globals_Funcs( size ); |
| 85 | if ( funcs ) |
| 86 | funcs->destroy( (PSH_Globals)size->internal ); |
| 87 | |
| 88 | size->internal = 0; |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 93 | FT_LOCAL_DEF( FT_Error ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 94 | CFF_Size_Init( CFF_Size size ) |
| 95 | { |
| 96 | FT_Error error = 0; |
| 97 | PSH_Globals_Funcs funcs = CFF_Size_Get_Globals_Funcs( size ); |
| 98 | |
| 99 | |
| 100 | if ( funcs ) |
| 101 | { |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 102 | PSH_Globals globals; |
| 103 | CFF_Face face = (CFF_Face)size->face; |
David Turner | ab4fc4d | 2002-03-14 08:57:10 +0000 | [diff] [blame] | 104 | CFF_Font font = (CFF_FontRec *)face->extra.data; |
| 105 | CFF_SubFont subfont = &font->top_font; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 106 | |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 107 | CFF_Private cpriv = &subfont->private_dict; |
| 108 | PS_PrivateRec priv; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 109 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 110 | |
| 111 | /* IMPORTANT: The CFF and Type1 private dictionaries have */ |
| 112 | /* slightly different structures; we need to */ |
| 113 | /* synthetize a type1 dictionary on the fly here. */ |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 114 | |
| 115 | { |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 116 | FT_UInt n, count; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 117 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 118 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame^] | 119 | FT_MEM_SET( &priv, 0, sizeof ( priv ) ); |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 120 | |
| 121 | count = priv.num_blue_values = cpriv->num_blue_values; |
| 122 | for ( n = 0; n < count; n++ ) |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 123 | priv.blue_values[n] = (FT_Short)cpriv->blue_values[n]; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 124 | |
| 125 | count = priv.num_other_blues = cpriv->num_other_blues; |
| 126 | for ( n = 0; n < count; n++ ) |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 127 | priv.other_blues[n] = (FT_Short)cpriv->other_blues[n]; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 128 | |
| 129 | count = priv.num_family_blues = cpriv->num_family_blues; |
| 130 | for ( n = 0; n < count; n++ ) |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 131 | priv.family_blues[n] = (FT_Short)cpriv->family_blues[n]; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 132 | |
| 133 | count = priv.num_family_other_blues = cpriv->num_family_other_blues; |
| 134 | for ( n = 0; n < count; n++ ) |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 135 | priv.family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 136 | |
| 137 | priv.blue_scale = cpriv->blue_scale; |
| 138 | priv.blue_shift = cpriv->blue_shift; |
| 139 | priv.blue_fuzz = cpriv->blue_fuzz; |
| 140 | |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 141 | priv.standard_width[0] = (FT_UShort)cpriv->standard_width; |
| 142 | priv.standard_height[0] = (FT_UShort)cpriv->standard_height; |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 143 | |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 144 | count = priv.num_snap_widths = cpriv->num_snap_widths; |
| 145 | for ( n = 0; n < count; n++ ) |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 146 | priv.snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 147 | |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 148 | count = priv.num_snap_heights = cpriv->num_snap_heights; |
| 149 | for ( n = 0; n < count; n++ ) |
Werner Lemberg | 3975e2e | 2002-01-09 21:01:18 +0000 | [diff] [blame] | 150 | priv.snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 151 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 152 | priv.force_bold = cpriv->force_bold; |
| 153 | priv.language_group = cpriv->language_group; |
| 154 | priv.lenIV = cpriv->lenIV; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | error = funcs->create( size->face->memory, &priv, &globals ); |
| 158 | if ( !error ) |
| 159 | size->internal = (FT_Size_Internal)(void*)globals; |
| 160 | } |
| 161 | |
| 162 | return error; |
| 163 | } |
| 164 | |
| 165 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 166 | FT_LOCAL_DEF( FT_Error ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 167 | CFF_Size_Reset( CFF_Size size ) |
| 168 | { |
| 169 | PSH_Globals_Funcs funcs = CFF_Size_Get_Globals_Funcs( size ); |
| 170 | FT_Error error = 0; |
| 171 | |
| 172 | |
| 173 | if ( funcs ) |
| 174 | error = funcs->set_scale( (PSH_Globals)size->internal, |
| 175 | size->metrics.x_scale, |
| 176 | size->metrics.y_scale, |
| 177 | 0, 0 ); |
| 178 | return error; |
| 179 | } |
| 180 | |
| 181 | |
| 182 | /*************************************************************************/ |
| 183 | /* */ |
| 184 | /* SLOT FUNCTIONS */ |
| 185 | /* */ |
| 186 | /*************************************************************************/ |
| 187 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 188 | FT_LOCAL_DEF( void ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 189 | CFF_GlyphSlot_Done( CFF_GlyphSlot slot ) |
| 190 | { |
| 191 | slot->root.internal->glyph_hints = 0; |
| 192 | } |
| 193 | |
| 194 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 195 | FT_LOCAL_DEF( FT_Error ) |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 196 | CFF_GlyphSlot_Init( CFF_GlyphSlot slot ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 197 | { |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 198 | CFF_Face face = (CFF_Face)slot->root.face; |
David Turner | ab4fc4d | 2002-03-14 08:57:10 +0000 | [diff] [blame] | 199 | CFF_Font font = (CFF_FontRec *)face->extra.data; |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 200 | PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 201 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 202 | |
| 203 | if ( pshinter ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 204 | { |
| 205 | FT_Module module; |
| 206 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 207 | |
| 208 | module = FT_Get_Module( slot->root.face->driver->root.library, |
| 209 | "pshinter" ); |
| 210 | if ( module ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 211 | { |
| 212 | T2_Hints_Funcs funcs; |
| 213 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 214 | |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 215 | funcs = pshinter->get_t2_funcs( module ); |
| 216 | slot->root.internal->glyph_hints = (void*)funcs; |
| 217 | } |
| 218 | } |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 219 | |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 220 | return 0; |
| 221 | } |
| 222 | |
| 223 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 224 | /*************************************************************************/ |
| 225 | /* */ |
| 226 | /* FACE FUNCTIONS */ |
| 227 | /* */ |
| 228 | /*************************************************************************/ |
| 229 | |
Werner Lemberg | 93616ec | 2001-06-27 19:46:12 +0000 | [diff] [blame] | 230 | static FT_String* |
| 231 | CFF_StrCopy( FT_Memory memory, |
| 232 | const FT_String* source ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 233 | { |
| 234 | FT_Error error; |
| 235 | FT_String* result = 0; |
| 236 | FT_Int len = (FT_Int)strlen( source ); |
| 237 | |
| 238 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame^] | 239 | if ( !FT_ALLOC( result, len + 1 ) ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 240 | { |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame^] | 241 | FT_MEM_COPY( result, source, len ); |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 242 | result[len] = 0; |
| 243 | } |
Werner Lemberg | b5349a9 | 2002-02-19 16:30:15 +0000 | [diff] [blame] | 244 | |
| 245 | FT_UNUSED( error ); |
| 246 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 247 | return result; |
| 248 | } |
| 249 | |
| 250 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 251 | |
| 252 | |
Werner Lemberg | 93616ec | 2001-06-27 19:46:12 +0000 | [diff] [blame] | 253 | static FT_Encoding |
| 254 | find_encoding( int platform_id, |
| 255 | int encoding_id ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 256 | { |
| 257 | typedef struct TEncoding |
| 258 | { |
| 259 | int platform_id; |
| 260 | int encoding_id; |
| 261 | FT_Encoding encoding; |
| 262 | |
| 263 | } TEncoding; |
| 264 | |
| 265 | static |
| 266 | const TEncoding tt_encodings[] = |
| 267 | { |
| 268 | { TT_PLATFORM_ISO, -1, ft_encoding_unicode }, |
| 269 | |
| 270 | { TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode }, |
| 271 | |
| 272 | { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman }, |
| 273 | |
| 274 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode }, |
| 275 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis }, |
| 276 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, ft_encoding_gb2312 }, |
| 277 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 }, |
| 278 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, ft_encoding_wansung }, |
| 279 | { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, ft_encoding_johab } |
| 280 | }; |
| 281 | |
| 282 | const TEncoding *cur, *limit; |
| 283 | |
| 284 | |
| 285 | cur = tt_encodings; |
| 286 | limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); |
| 287 | |
| 288 | for ( ; cur < limit; cur++ ) |
| 289 | { |
| 290 | if ( cur->platform_id == platform_id ) |
| 291 | { |
| 292 | if ( cur->encoding_id == encoding_id || |
| 293 | cur->encoding_id == -1 ) |
| 294 | return cur->encoding; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | return ft_encoding_none; |
| 299 | } |
| 300 | |
| 301 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 302 | FT_LOCAL_DEF( FT_Error ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 303 | CFF_Face_Init( FT_Stream stream, |
Werner Lemberg | 93616ec | 2001-06-27 19:46:12 +0000 | [diff] [blame] | 304 | CFF_Face face, |
| 305 | FT_Int face_index, |
| 306 | FT_Int num_params, |
| 307 | FT_Parameter* params ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 308 | { |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 309 | FT_Error error; |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 310 | SFNT_Service sfnt; |
| 311 | PSNames_Service psnames; |
| 312 | PSHinter_Service pshinter; |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 313 | FT_Bool pure_cff = 1; |
| 314 | FT_Bool sfnt_format = 0; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 315 | |
| 316 | |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 317 | sfnt = (SFNT_Service)FT_Get_Module_Interface( |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 318 | face->root.driver->root.library, "sfnt" ); |
| 319 | if ( !sfnt ) |
| 320 | goto Bad_Format; |
| 321 | |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 322 | psnames = (PSNames_Service)FT_Get_Module_Interface( |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 323 | face->root.driver->root.library, "psnames" ); |
| 324 | |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 325 | pshinter = (PSHinter_Service)FT_Get_Module_Interface( |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 326 | face->root.driver->root.library, "pshinter" ); |
| 327 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 328 | /* create input stream from resource */ |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 329 | if ( FT_STREAM_SEEK( 0 ) ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 330 | goto Exit; |
| 331 | |
| 332 | /* check that we have a valid OpenType file */ |
| 333 | error = sfnt->init_face( stream, face, face_index, num_params, params ); |
| 334 | if ( !error ) |
| 335 | { |
| 336 | if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ |
| 337 | { |
| 338 | FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); |
| 339 | goto Bad_Format; |
| 340 | } |
| 341 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 342 | /* if we are performing a simple font format check, exit immediately */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 343 | if ( face_index < 0 ) |
Tom Kacvinsky | 8d1f604 | 2001-01-03 00:21:59 +0000 | [diff] [blame] | 344 | return CFF_Err_Ok; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 345 | |
| 346 | sfnt_format = 1; |
| 347 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 348 | /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ |
| 349 | /* font in the later case; it doesn't have a `head' table */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 350 | error = face->goto_table( face, TTAG_head, stream, 0 ); |
| 351 | if ( !error ) |
| 352 | { |
| 353 | pure_cff = 0; |
| 354 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 355 | /* load font directory */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 356 | error = sfnt->load_face( stream, face, |
| 357 | face_index, num_params, params ); |
| 358 | if ( error ) |
| 359 | goto Exit; |
| 360 | } |
| 361 | else |
| 362 | { |
| 363 | /* load the `cmap' table by hand */ |
| 364 | error = sfnt->load_charmaps( face, stream ); |
| 365 | if ( error ) |
| 366 | goto Exit; |
| 367 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 368 | /* XXX: we don't load the GPOS table, as OpenType Layout */ |
| 369 | /* support will be added later to a layout library on top of */ |
| 370 | /* FreeType 2 */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 371 | } |
| 372 | |
| 373 | /* now, load the CFF part of the file */ |
| 374 | error = face->goto_table( face, TTAG_CFF, stream, 0 ); |
| 375 | if ( error ) |
| 376 | goto Exit; |
| 377 | } |
| 378 | else |
| 379 | { |
| 380 | /* rewind to start of file; we are going to load a pure-CFF font */ |
David Turner | 7d3a264 | 2002-03-20 10:49:31 +0000 | [diff] [blame] | 381 | if ( FT_STREAM_SEEK( 0 ) ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 382 | goto Exit; |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 383 | error = CFF_Err_Ok; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 384 | } |
| 385 | |
| 386 | /* now load and parse the CFF table in the file */ |
| 387 | { |
David Turner | ab4fc4d | 2002-03-14 08:57:10 +0000 | [diff] [blame] | 388 | CFF_Font cff; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 389 | FT_Memory memory = face->root.memory; |
| 390 | FT_Face root; |
| 391 | FT_UInt flags; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 392 | |
| 393 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame^] | 394 | if ( FT_NEW( cff ) ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 395 | goto Exit; |
| 396 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 397 | face->extra.data = cff; |
| 398 | error = CFF_Load_Font( stream, face_index, cff ); |
| 399 | if ( error ) |
| 400 | goto Exit; |
| 401 | |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 402 | cff->pshinter = pshinter; |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 403 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 404 | /* Complement the root flags with some interesting information. */ |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 405 | /* Note that this is only necessary for pure CFF and CEF fonts. */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 406 | |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 407 | root = &face->root; |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 408 | root->num_glyphs = cff->num_glyphs; |
Werner Lemberg | f41e71a | 2001-12-20 21:22:02 +0000 | [diff] [blame] | 409 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 410 | if ( pure_cff ) |
| 411 | { |
David Turner | ab4fc4d | 2002-03-14 08:57:10 +0000 | [diff] [blame] | 412 | CFF_FontRecDict dict = &cff->top_font.font_dict; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 413 | |
| 414 | |
| 415 | /* we need the `PSNames' module for pure-CFF and CEF formats */ |
| 416 | if ( !psnames ) |
| 417 | { |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 418 | FT_ERROR(( "CFF_Face_Init:" )); |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 419 | FT_ERROR(( " cannot open CFF & CEF fonts\n" )); |
| 420 | FT_ERROR(( " " )); |
| 421 | FT_ERROR(( " without the `PSNames' module\n" )); |
| 422 | goto Bad_Format; |
| 423 | } |
| 424 | |
| 425 | /* Set up num_faces. */ |
| 426 | root->num_faces = cff->num_faces; |
| 427 | |
| 428 | /* compute number of glyphs */ |
| 429 | if ( dict->cid_registry ) |
| 430 | root->num_glyphs = dict->cid_count; |
| 431 | else |
| 432 | root->num_glyphs = cff->charstrings_index.count; |
| 433 | |
| 434 | /* set global bbox, as well as EM size */ |
David Turner | 7d0f0ba | 2002-03-05 15:55:28 +0000 | [diff] [blame] | 435 | root->bbox.xMin = dict->font_bbox.xMin >> 16; |
| 436 | root->bbox.yMin = dict->font_bbox.yMin >> 16; |
| 437 | root->bbox.xMax = (dict->font_bbox.xMax + 0xFFFFU) >> 16; |
| 438 | root->bbox.yMax = (dict->font_bbox.yMax + 0xFFFFU) >> 16; |
| 439 | |
| 440 | |
| 441 | root->ascender = (FT_Short)( root->bbox.yMax ); |
| 442 | root->descender = (FT_Short)( root->bbox.yMin ); |
Werner Lemberg | 8eb0353 | 2001-06-19 23:03:41 +0000 | [diff] [blame] | 443 | root->height = (FT_Short)( |
| 444 | ( ( root->ascender - root->descender ) * 12 ) / 10 ); |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 445 | |
Tom Kacvinsky | c97cf17 | 2001-02-07 01:08:34 +0000 | [diff] [blame] | 446 | if ( dict->units_per_em ) |
| 447 | root->units_per_EM = dict->units_per_em; |
| 448 | else |
| 449 | root->units_per_EM = 1000; |
| 450 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 451 | /* retrieve font family & style name */ |
| 452 | root->family_name = CFF_Get_Name( &cff->name_index, face_index ); |
| 453 | if ( dict->cid_registry ) |
Tom Kacvinsky | 8d1f604 | 2001-01-03 00:21:59 +0000 | [diff] [blame] | 454 | root->style_name = CFF_StrCopy( memory, "Regular" ); /* XXXX */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 455 | else |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 456 | root->style_name = CFF_Get_String( &cff->string_index, |
| 457 | dict->weight, |
| 458 | psnames ); |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 459 | |
| 460 | /*******************************************************************/ |
| 461 | /* */ |
| 462 | /* Compute face flags. */ |
| 463 | /* */ |
| 464 | flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ |
| 465 | FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ |
| 466 | |
| 467 | if ( sfnt_format ) |
| 468 | flags |= FT_FACE_FLAG_SFNT; |
| 469 | |
| 470 | /* fixed width font? */ |
| 471 | if ( dict->is_fixed_pitch ) |
| 472 | flags |= FT_FACE_FLAG_FIXED_WIDTH; |
| 473 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 474 | /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 475 | #if 0 |
| 476 | /* kerning available? */ |
| 477 | if ( face->kern_pairs ) |
| 478 | flags |= FT_FACE_FLAG_KERNING; |
| 479 | #endif |
| 480 | |
Tom Kacvinsky | b9561b7 | 2001-03-16 13:40:50 +0000 | [diff] [blame] | 481 | #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES |
| 482 | flags |= FT_FACE_FLAG_GLYPH_NAMES; |
| 483 | #endif |
| 484 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 485 | root->face_flags = flags; |
| 486 | |
| 487 | /*******************************************************************/ |
| 488 | /* */ |
| 489 | /* Compute style flags. */ |
| 490 | /* */ |
| 491 | flags = 0; |
| 492 | |
| 493 | if ( dict->italic_angle ) |
| 494 | flags |= FT_STYLE_FLAG_ITALIC; |
| 495 | |
| 496 | /* XXX: may not be correct */ |
| 497 | if ( cff->top_font.private_dict.force_bold ) |
| 498 | flags |= FT_STYLE_FLAG_BOLD; |
| 499 | |
| 500 | root->style_flags = flags; |
| 501 | |
| 502 | /* set the charmaps if any */ |
| 503 | if ( sfnt_format ) |
| 504 | { |
| 505 | /*****************************************************************/ |
| 506 | /* */ |
| 507 | /* Polish the charmaps. */ |
| 508 | /* */ |
| 509 | /* Try to set the charmap encoding according to the platform & */ |
| 510 | /* encoding ID of each charmap. */ |
| 511 | /* */ |
| 512 | TT_CharMap charmap; |
| 513 | FT_Int n; |
| 514 | |
| 515 | |
| 516 | charmap = face->charmaps; |
| 517 | root->num_charmaps = face->num_charmaps; |
| 518 | |
| 519 | /* allocate table of pointers */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame^] | 520 | if ( FT_NEW_ARRAY( root->charmaps, root->num_charmaps ) ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 521 | goto Exit; |
| 522 | |
| 523 | for ( n = 0; n < root->num_charmaps; n++, charmap++ ) |
| 524 | { |
| 525 | FT_Int platform = charmap->cmap.platformID; |
| 526 | FT_Int encoding = charmap->cmap.platformEncodingID; |
| 527 | |
| 528 | |
| 529 | charmap->root.face = (FT_Face)face; |
David Turner | 8edbcab | 2001-06-19 08:28:24 +0000 | [diff] [blame] | 530 | charmap->root.platform_id = (FT_UShort)platform; |
| 531 | charmap->root.encoding_id = (FT_UShort)encoding; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 532 | charmap->root.encoding = find_encoding( platform, encoding ); |
| 533 | |
| 534 | /* now, set root->charmap with a unicode charmap */ |
| 535 | /* wherever available */ |
| 536 | if ( !root->charmap && |
| 537 | charmap->root.encoding == ft_encoding_unicode ) |
| 538 | root->charmap = (FT_CharMap)charmap; |
| 539 | |
| 540 | root->charmaps[n] = (FT_CharMap)charmap; |
| 541 | } |
| 542 | } |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | Exit: |
| 547 | return error; |
| 548 | |
| 549 | Bad_Format: |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 550 | error = CFF_Err_Unknown_File_Format; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 551 | goto Exit; |
| 552 | } |
| 553 | |
| 554 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 555 | FT_LOCAL_DEF( void ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 556 | CFF_Face_Done( CFF_Face face ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 557 | { |
| 558 | FT_Memory memory = face->root.memory; |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 559 | SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 560 | |
| 561 | |
| 562 | if ( sfnt ) |
| 563 | sfnt->done_face( face ); |
| 564 | |
| 565 | { |
David Turner | ab4fc4d | 2002-03-14 08:57:10 +0000 | [diff] [blame] | 566 | CFF_Font cff = (CFF_Font)face->extra.data; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 567 | |
| 568 | |
| 569 | if ( cff ) |
| 570 | { |
| 571 | CFF_Done_Font( cff ); |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame^] | 572 | FT_FREE( face->extra.data ); |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 573 | } |
| 574 | } |
| 575 | } |
| 576 | |
| 577 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 578 | FT_LOCAL_DEF( FT_Error ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 579 | CFF_Driver_Init( CFF_Driver driver ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 580 | { |
| 581 | /* init extension registry if needed */ |
| 582 | |
| 583 | #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE |
| 584 | |
| 585 | return TT_Init_Extensions( driver ); |
| 586 | |
| 587 | #else |
| 588 | |
| 589 | FT_UNUSED( driver ); |
| 590 | |
Tom Kacvinsky | 8d1f604 | 2001-01-03 00:21:59 +0000 | [diff] [blame] | 591 | return CFF_Err_Ok; |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 592 | |
| 593 | #endif |
| 594 | } |
| 595 | |
| 596 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 597 | FT_LOCAL_DEF( void ) |
David Turner | c808748 | 2001-12-20 13:14:18 +0000 | [diff] [blame] | 598 | CFF_Driver_Done( CFF_Driver driver ) |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 599 | { |
| 600 | /* destroy extensions registry if needed */ |
| 601 | |
| 602 | #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE |
| 603 | |
| 604 | TT_Done_Extensions( driver ); |
| 605 | |
| 606 | #else |
| 607 | |
| 608 | FT_UNUSED( driver ); |
| 609 | |
| 610 | #endif |
| 611 | } |
| 612 | |
| 613 | |
| 614 | /* END */ |