Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1 | /***************************************************************************/ |
| 2 | /* */ |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 3 | /* t1load.c */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 4 | /* */ |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 5 | /* Type 1 font loader (body). */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 6 | /* */ |
Werner Lemberg | 504645e | 2008-05-14 23:26:20 +0000 | [diff] [blame] | 7 | /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +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 | |
| 18 | |
| 19 | /*************************************************************************/ |
| 20 | /* */ |
| 21 | /* This is the new and improved Type 1 data loader for FreeType 2. The */ |
| 22 | /* old loader has several problems: it is slow, complex, difficult to */ |
| 23 | /* maintain, and contains incredible hacks to make it accept some */ |
| 24 | /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ |
| 25 | /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ |
| 26 | /* */ |
| 27 | /* This version is much simpler, much faster and also easier to read and */ |
| 28 | /* maintain by a great order of magnitude. The idea behind it is to */ |
| 29 | /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ |
| 30 | /* a Postscript-like interpreter) but rather to perform simple pattern */ |
| 31 | /* matching. */ |
| 32 | /* */ |
| 33 | /* Indeed, nearly all data definitions follow a simple pattern like */ |
| 34 | /* */ |
| 35 | /* ... /Field <data> ... */ |
| 36 | /* */ |
| 37 | /* where <data> can be a number, a boolean, a string, or an array of */ |
| 38 | /* numbers. There are a few exceptions, namely the encoding, font name, */ |
| 39 | /* charstrings, and subrs; they are handled with a special pattern */ |
| 40 | /* matching routine. */ |
| 41 | /* */ |
| 42 | /* All other common cases are handled very simply. The matching rules */ |
| 43 | /* are defined in the file `t1tokens.h' through the use of several */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 44 | /* macros calls PARSE_XXX. This file is included twice here; the first */ |
| 45 | /* time to generate parsing callback functions, the second time to */ |
| 46 | /* generate a table of keywords (with pointers to the associated */ |
| 47 | /* callback functions). */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 48 | /* */ |
| 49 | /* The function `parse_dict' simply scans *linearly* a given dictionary */ |
| 50 | /* (either the top-level or private one) and calls the appropriate */ |
| 51 | /* callback when it encounters an immediate keyword. */ |
| 52 | /* */ |
| 53 | /* This is by far the fastest way one can find to parse and read all */ |
| 54 | /* data. */ |
| 55 | /* */ |
| 56 | /* This led to tremendous code size reduction. Note that later, the */ |
| 57 | /* glyph loader will also be _greatly_ simplified, and the automatic */ |
| 58 | /* hinter will replace the clumsy `t1hinter'. */ |
| 59 | /* */ |
| 60 | /*************************************************************************/ |
| 61 | |
Werner Lemberg | cc069be | 2000-12-08 16:17:16 +0000 | [diff] [blame] | 62 | |
David Turner | 19ed8af | 2000-12-08 02:42:29 +0000 | [diff] [blame] | 63 | #include <ft2build.h> |
| 64 | #include FT_INTERNAL_DEBUG_H |
| 65 | #include FT_CONFIG_CONFIG_H |
| 66 | #include FT_MULTIPLE_MASTERS_H |
| 67 | #include FT_INTERNAL_TYPE1_TYPES_H |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 68 | |
David Turner | 8d3a401 | 2001-03-20 11:14:24 +0000 | [diff] [blame] | 69 | #include "t1load.h" |
Werner Lemberg | 1f7f0e8 | 2001-06-06 17:30:41 +0000 | [diff] [blame] | 70 | #include "t1errors.h" |
| 71 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 72 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 73 | /*************************************************************************/ |
| 74 | /* */ |
| 75 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| 76 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| 77 | /* messages during execution. */ |
| 78 | /* */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 79 | #undef FT_COMPONENT |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 80 | #define FT_COMPONENT trace_t1load |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 81 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 82 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 83 | #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 84 | |
David Turner | 1118720 | 2000-05-26 17:13:23 +0000 | [diff] [blame] | 85 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 86 | /*************************************************************************/ |
| 87 | /*************************************************************************/ |
| 88 | /***** *****/ |
| 89 | /***** MULTIPLE MASTERS SUPPORT *****/ |
| 90 | /***** *****/ |
| 91 | /*************************************************************************/ |
| 92 | /*************************************************************************/ |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 93 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 94 | static FT_Error |
| 95 | t1_allocate_blend( T1_Face face, |
| 96 | FT_UInt num_designs, |
| 97 | FT_UInt num_axis ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 98 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 99 | PS_Blend blend; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 100 | FT_Memory memory = face->root.memory; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 101 | FT_Error error = T1_Err_Ok; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 102 | |
| 103 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 104 | blend = face->blend; |
| 105 | if ( !blend ) |
| 106 | { |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 107 | if ( FT_NEW( blend ) ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 108 | goto Exit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 109 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 110 | blend->num_default_design_vector = 0; |
| 111 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 112 | face->blend = blend; |
| 113 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 114 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 115 | /* allocate design data if needed */ |
| 116 | if ( num_designs > 0 ) |
| 117 | { |
| 118 | if ( blend->num_designs == 0 ) |
| 119 | { |
David Turner | e208f4e | 2000-07-10 20:30:59 +0000 | [diff] [blame] | 120 | FT_UInt nn; |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 121 | |
Werner Lemberg | 93ac3e3 | 2000-07-10 21:41:32 +0000 | [diff] [blame] | 122 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 123 | /* allocate the blend `private' and `font_info' dictionaries */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 124 | if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || |
| 125 | FT_NEW_ARRAY( blend->privates[1], num_designs ) || |
David Turner | 8db6a07 | 2002-07-11 11:26:21 +0000 | [diff] [blame] | 126 | FT_NEW_ARRAY( blend->bboxes[1], num_designs ) || |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 127 | FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 128 | goto Exit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 129 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 130 | blend->default_weight_vector = blend->weight_vector + num_designs; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 131 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 132 | blend->font_infos[0] = &face->type1.font_info; |
| 133 | blend->privates [0] = &face->type1.private_dict; |
David Turner | 8db6a07 | 2002-07-11 11:26:21 +0000 | [diff] [blame] | 134 | blend->bboxes [0] = &face->type1.font_bbox; |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 135 | |
David Turner | e208f4e | 2000-07-10 20:30:59 +0000 | [diff] [blame] | 136 | for ( nn = 2; nn <= num_designs; nn++ ) |
| 137 | { |
Werner Lemberg | 93ac3e3 | 2000-07-10 21:41:32 +0000 | [diff] [blame] | 138 | blend->privates[nn] = blend->privates [nn - 1] + 1; |
| 139 | blend->font_infos[nn] = blend->font_infos[nn - 1] + 1; |
David Turner | 8db6a07 | 2002-07-11 11:26:21 +0000 | [diff] [blame] | 140 | blend->bboxes[nn] = blend->bboxes [nn - 1] + 1; |
David Turner | e208f4e | 2000-07-10 20:30:59 +0000 | [diff] [blame] | 141 | } |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 142 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 143 | blend->num_designs = num_designs; |
| 144 | } |
| 145 | else if ( blend->num_designs != num_designs ) |
| 146 | goto Fail; |
| 147 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 148 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 149 | /* allocate axis data if needed */ |
| 150 | if ( num_axis > 0 ) |
| 151 | { |
| 152 | if ( blend->num_axis != 0 && blend->num_axis != num_axis ) |
| 153 | goto Fail; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 154 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 155 | blend->num_axis = num_axis; |
| 156 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 157 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 158 | /* allocate the blend design pos table if needed */ |
| 159 | num_designs = blend->num_designs; |
| 160 | num_axis = blend->num_axis; |
| 161 | if ( num_designs && num_axis && blend->design_pos[0] == 0 ) |
| 162 | { |
| 163 | FT_UInt n; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 164 | |
| 165 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 166 | if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 167 | goto Exit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 168 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 169 | for ( n = 1; n < num_designs; n++ ) |
| 170 | blend->design_pos[n] = blend->design_pos[0] + num_axis * n; |
| 171 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 172 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 173 | Exit: |
| 174 | return error; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 175 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 176 | Fail: |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 177 | error = T1_Err_Invalid_File_Format; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 178 | goto Exit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 182 | FT_LOCAL_DEF( FT_Error ) |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 183 | T1_Get_Multi_Master( T1_Face face, |
| 184 | FT_Multi_Master* master ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 185 | { |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 186 | PS_Blend blend = face->blend; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 187 | FT_UInt n; |
| 188 | FT_Error error; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 189 | |
| 190 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 191 | error = T1_Err_Invalid_Argument; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 192 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 193 | if ( blend ) |
| 194 | { |
| 195 | master->num_axis = blend->num_axis; |
| 196 | master->num_designs = blend->num_designs; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 197 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 198 | for ( n = 0; n < blend->num_axis; n++ ) |
| 199 | { |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 200 | FT_MM_Axis* axis = master->axis + n; |
| 201 | PS_DesignMap map = blend->design_map + n; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 202 | |
| 203 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 204 | axis->name = blend->axis_names[n]; |
| 205 | axis->minimum = map->design_points[0]; |
| 206 | axis->maximum = map->design_points[map->num_points - 1]; |
| 207 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 208 | |
| 209 | error = T1_Err_Ok; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 210 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 211 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 212 | return error; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | |
Werner Lemberg | 44bb303 | 2004-04-25 20:15:11 +0000 | [diff] [blame] | 216 | #define FT_INT_TO_FIXED( a ) ( (a) << 16 ) |
| 217 | #define FT_FIXED_TO_INT( a ) ( FT_RoundFix( a ) >> 16 ) |
| 218 | |
| 219 | |
| 220 | /*************************************************************************/ |
| 221 | /* */ |
Werner Lemberg | 24bf96c | 2004-05-20 09:21:19 +0000 | [diff] [blame] | 222 | /* Given a normalized (blend) coordinate, figure out the design */ |
| 223 | /* coordinate appropriate for that value. */ |
| 224 | /* */ |
| 225 | FT_LOCAL_DEF( FT_Fixed ) |
| 226 | mm_axis_unmap( PS_DesignMap axismap, |
| 227 | FT_Fixed ncv ) |
| 228 | { |
| 229 | int j; |
| 230 | |
| 231 | |
| 232 | if ( ncv <= axismap->blend_points[0] ) |
| 233 | return axismap->design_points[0]; |
| 234 | |
| 235 | for ( j = 1; j < axismap->num_points; ++j ) |
| 236 | { |
| 237 | if ( ncv <= axismap->blend_points[j] ) |
| 238 | { |
| 239 | FT_Fixed t = FT_MulDiv( ncv - axismap->blend_points[j - 1], |
| 240 | 0x10000L, |
| 241 | axismap->blend_points[j] - |
| 242 | axismap->blend_points[j - 1] ); |
| 243 | |
| 244 | |
| 245 | return axismap->design_points[j - 1] + |
| 246 | FT_MulDiv( t, |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 247 | axismap->design_points[j] - |
Werner Lemberg | 24bf96c | 2004-05-20 09:21:19 +0000 | [diff] [blame] | 248 | axismap->design_points[j - 1], |
| 249 | 1L ); |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | return axismap->design_points[axismap->num_points - 1]; |
| 254 | } |
| 255 | |
| 256 | |
| 257 | /*************************************************************************/ |
| 258 | /* */ |
| 259 | /* Given a vector of weights, one for each design, figure out the */ |
| 260 | /* normalized axis coordinates which gave rise to those weights. */ |
| 261 | /* */ |
| 262 | FT_LOCAL_DEF( void ) |
| 263 | mm_weights_unmap( FT_Fixed* weights, |
| 264 | FT_Fixed* axiscoords, |
| 265 | FT_UInt axis_count ) |
| 266 | { |
| 267 | FT_ASSERT( axis_count <= T1_MAX_MM_AXIS ); |
| 268 | |
| 269 | if ( axis_count == 1 ) |
| 270 | axiscoords[0] = weights[1]; |
| 271 | |
| 272 | else if ( axis_count == 2 ) |
| 273 | { |
| 274 | axiscoords[0] = weights[3] + weights[1]; |
| 275 | axiscoords[1] = weights[3] + weights[2]; |
| 276 | } |
| 277 | |
| 278 | else if ( axis_count == 3 ) |
| 279 | { |
| 280 | axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1]; |
| 281 | axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2]; |
| 282 | axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4]; |
| 283 | } |
| 284 | |
| 285 | else |
| 286 | { |
| 287 | axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] + |
| 288 | weights[7] + weights[5] + weights[3] + weights[1]; |
| 289 | axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] + |
| 290 | weights[7] + weights[6] + weights[3] + weights[2]; |
| 291 | axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] + |
| 292 | weights[7] + weights[6] + weights[5] + weights[4]; |
| 293 | axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] + |
| 294 | weights[11] + weights[10] + weights[9] + weights[8]; |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | |
| 299 | /*************************************************************************/ |
| 300 | /* */ |
Werner Lemberg | 44bb303 | 2004-04-25 20:15:11 +0000 | [diff] [blame] | 301 | /* Just a wrapper around T1_Get_Multi_Master to support the different */ |
| 302 | /* arguments needed by the GX var distortable fonts. */ |
| 303 | /* */ |
| 304 | FT_LOCAL_DEF( FT_Error ) |
| 305 | T1_Get_MM_Var( T1_Face face, |
| 306 | FT_MM_Var* *master ) |
| 307 | { |
| 308 | FT_Memory memory = face->root.memory; |
| 309 | FT_MM_Var *mmvar; |
| 310 | FT_Multi_Master mmaster; |
| 311 | FT_Error error; |
| 312 | FT_UInt i; |
Werner Lemberg | 24bf96c | 2004-05-20 09:21:19 +0000 | [diff] [blame] | 313 | FT_Fixed axiscoords[T1_MAX_MM_AXIS]; |
| 314 | PS_Blend blend = face->blend; |
Werner Lemberg | 44bb303 | 2004-04-25 20:15:11 +0000 | [diff] [blame] | 315 | |
| 316 | |
| 317 | error = T1_Get_Multi_Master( face, &mmaster ); |
| 318 | if ( error ) |
| 319 | goto Exit; |
| 320 | if ( FT_ALLOC( mmvar, |
| 321 | sizeof ( FT_MM_Var ) + |
| 322 | mmaster.num_axis * sizeof ( FT_Var_Axis ) ) ) |
| 323 | goto Exit; |
| 324 | |
| 325 | mmvar->num_axis = mmaster.num_axis; |
| 326 | mmvar->num_designs = mmaster.num_designs; |
| 327 | mmvar->num_namedstyles = (FT_UInt)-1; /* Does not apply */ |
| 328 | mmvar->axis = (FT_Var_Axis*)&mmvar[1]; |
| 329 | /* Point to axes after MM_Var struct */ |
| 330 | mmvar->namedstyle = NULL; |
| 331 | |
| 332 | for ( i = 0 ; i < mmaster.num_axis; ++i ) |
| 333 | { |
| 334 | mmvar->axis[i].name = mmaster.axis[i].name; |
| 335 | mmvar->axis[i].minimum = FT_INT_TO_FIXED( mmaster.axis[i].minimum); |
| 336 | mmvar->axis[i].maximum = FT_INT_TO_FIXED( mmaster.axis[i].maximum); |
| 337 | mmvar->axis[i].def = ( mmvar->axis[i].minimum + |
| 338 | mmvar->axis[i].maximum ) / 2; |
| 339 | /* Does not apply. But this value is in range */ |
Werner Lemberg | f1c2b91 | 2006-01-13 14:53:28 +0000 | [diff] [blame] | 340 | mmvar->axis[i].strid = 0xFFFFFFFFUL; /* Does not apply */ |
| 341 | mmvar->axis[i].tag = 0xFFFFFFFFUL; /* Does not apply */ |
Werner Lemberg | 24bf96c | 2004-05-20 09:21:19 +0000 | [diff] [blame] | 342 | |
| 343 | if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 ) |
| 344 | mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' ); |
| 345 | else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 ) |
| 346 | mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); |
| 347 | else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) |
| 348 | mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); |
| 349 | } |
| 350 | |
| 351 | if ( blend->num_designs == 1U << blend->num_axis ) |
| 352 | { |
| 353 | mm_weights_unmap( blend->default_weight_vector, |
| 354 | axiscoords, |
| 355 | blend->num_axis ); |
| 356 | |
| 357 | for ( i = 0; i < mmaster.num_axis; ++i ) |
Werner Lemberg | bf02d39 | 2007-01-10 07:07:37 +0000 | [diff] [blame] | 358 | mmvar->axis[i].def = |
| 359 | FT_INT_TO_FIXED( mm_axis_unmap( &blend->design_map[i], |
| 360 | axiscoords[i] ) ); |
Werner Lemberg | 44bb303 | 2004-04-25 20:15:11 +0000 | [diff] [blame] | 361 | } |
| 362 | |
| 363 | *master = mmvar; |
| 364 | |
| 365 | Exit: |
| 366 | return error; |
| 367 | } |
| 368 | |
| 369 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 370 | FT_LOCAL_DEF( FT_Error ) |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 371 | T1_Set_MM_Blend( T1_Face face, |
| 372 | FT_UInt num_coords, |
| 373 | FT_Fixed* coords ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 374 | { |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 375 | PS_Blend blend = face->blend; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 376 | FT_Error error; |
| 377 | FT_UInt n, m; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 378 | |
David Turner | 1118720 | 2000-05-26 17:13:23 +0000 | [diff] [blame] | 379 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 380 | error = T1_Err_Invalid_Argument; |
| 381 | |
| 382 | if ( blend && blend->num_axis == num_coords ) |
| 383 | { |
| 384 | /* recompute the weight vector from the blend coordinates */ |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 385 | error = T1_Err_Ok; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 386 | |
| 387 | for ( n = 0; n < blend->num_designs; n++ ) |
| 388 | { |
| 389 | FT_Fixed result = 0x10000L; /* 1.0 fixed */ |
| 390 | |
| 391 | |
| 392 | for ( m = 0; m < blend->num_axis; m++ ) |
| 393 | { |
| 394 | FT_Fixed factor; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 395 | |
David Turner | 1118720 | 2000-05-26 17:13:23 +0000 | [diff] [blame] | 396 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 397 | /* get current blend axis position */ |
| 398 | factor = coords[m]; |
| 399 | if ( factor < 0 ) factor = 0; |
| 400 | if ( factor > 0x10000L ) factor = 0x10000L; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 401 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 402 | if ( ( n & ( 1 << m ) ) == 0 ) |
| 403 | factor = 0x10000L - factor; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 404 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 405 | result = FT_MulFix( result, factor ); |
| 406 | } |
| 407 | blend->weight_vector[n] = result; |
| 408 | } |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 409 | |
Werner Lemberg | 1429db6 | 2001-04-02 23:54:01 +0000 | [diff] [blame] | 410 | error = T1_Err_Ok; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 411 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 412 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 413 | return error; |
| 414 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 415 | |
| 416 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 417 | FT_LOCAL_DEF( FT_Error ) |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 418 | T1_Set_MM_Design( T1_Face face, |
| 419 | FT_UInt num_coords, |
| 420 | FT_Long* coords ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 421 | { |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 422 | PS_Blend blend = face->blend; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 423 | FT_Error error; |
| 424 | FT_UInt n, p; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 425 | |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 426 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 427 | error = T1_Err_Invalid_Argument; |
| 428 | if ( blend && blend->num_axis == num_coords ) |
| 429 | { |
| 430 | /* compute the blend coordinates through the blend design map */ |
| 431 | FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 432 | |
David Turner | 7c388ba | 2000-05-26 02:07:40 +0000 | [diff] [blame] | 433 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 434 | for ( n = 0; n < blend->num_axis; n++ ) |
| 435 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 436 | FT_Long design = coords[n]; |
| 437 | FT_Fixed the_blend; |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 438 | PS_DesignMap map = blend->design_map + n; |
Werner Lemberg | 24bf96c | 2004-05-20 09:21:19 +0000 | [diff] [blame] | 439 | FT_Long* designs = map->design_points; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 440 | FT_Fixed* blends = map->blend_points; |
| 441 | FT_Int before = -1, after = -1; |
| 442 | |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 443 | |
David Turner | efa80f2 | 2000-12-01 21:43:05 +0000 | [diff] [blame] | 444 | for ( p = 0; p < (FT_UInt)map->num_points; p++ ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 445 | { |
Werner Lemberg | 24bf96c | 2004-05-20 09:21:19 +0000 | [diff] [blame] | 446 | FT_Long p_design = designs[p]; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 447 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 448 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 449 | /* exact match? */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 450 | if ( design == p_design ) |
| 451 | { |
| 452 | the_blend = blends[p]; |
| 453 | goto Found; |
| 454 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 455 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 456 | if ( design < p_design ) |
| 457 | { |
| 458 | after = p; |
| 459 | break; |
| 460 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 461 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 462 | before = p; |
| 463 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 464 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 465 | /* now interpolate if necessary */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 466 | if ( before < 0 ) |
| 467 | the_blend = blends[0]; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 468 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 469 | else if ( after < 0 ) |
| 470 | the_blend = blends[map->num_points - 1]; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 471 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 472 | else |
| 473 | the_blend = FT_MulDiv( design - designs[before], |
| 474 | blends [after] - blends [before], |
| 475 | designs[after] - designs[before] ); |
| 476 | |
| 477 | Found: |
| 478 | final_blends[n] = the_blend; |
| 479 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 480 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 481 | error = T1_Set_MM_Blend( face, num_coords, final_blends ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 482 | } |
| 483 | |
| 484 | return error; |
| 485 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 486 | |
| 487 | |
Werner Lemberg | 44bb303 | 2004-04-25 20:15:11 +0000 | [diff] [blame] | 488 | /*************************************************************************/ |
| 489 | /* */ |
| 490 | /* Just a wrapper around T1_Set_MM_Design to support the different */ |
| 491 | /* arguments needed by the GX var distortable fonts. */ |
| 492 | /* */ |
| 493 | FT_LOCAL_DEF( FT_Error ) |
| 494 | T1_Set_Var_Design( T1_Face face, |
| 495 | FT_UInt num_coords, |
| 496 | FT_Fixed* coords ) |
| 497 | { |
| 498 | FT_Long lcoords[4]; /* maximum axis count is 4 */ |
| 499 | FT_UInt i; |
| 500 | FT_Error error; |
| 501 | |
| 502 | |
| 503 | error = T1_Err_Invalid_Argument; |
| 504 | if ( num_coords <= 4 && num_coords > 0 ) |
| 505 | { |
| 506 | for ( i = 0; i < num_coords; ++i ) |
| 507 | lcoords[i] = FT_FIXED_TO_INT( coords[i] ); |
| 508 | error = T1_Set_MM_Design( face, num_coords, lcoords ); |
| 509 | } |
| 510 | |
| 511 | return error; |
| 512 | } |
| 513 | |
| 514 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 515 | FT_LOCAL_DEF( void ) |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 516 | T1_Done_Blend( T1_Face face ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 517 | { |
| 518 | FT_Memory memory = face->root.memory; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 519 | PS_Blend blend = face->blend; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 520 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 521 | |
| 522 | if ( blend ) |
| 523 | { |
| 524 | FT_UInt num_designs = blend->num_designs; |
| 525 | FT_UInt num_axis = blend->num_axis; |
| 526 | FT_UInt n; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 527 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 528 | |
| 529 | /* release design pos table */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 530 | FT_FREE( blend->design_pos[0] ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 531 | for ( n = 1; n < num_designs; n++ ) |
| 532 | blend->design_pos[n] = 0; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 533 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 534 | /* release blend `private' and `font info' dictionaries */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 535 | FT_FREE( blend->privates[1] ); |
| 536 | FT_FREE( blend->font_infos[1] ); |
David Turner | 8db6a07 | 2002-07-11 11:26:21 +0000 | [diff] [blame] | 537 | FT_FREE( blend->bboxes[1] ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 538 | |
| 539 | for ( n = 0; n < num_designs; n++ ) |
| 540 | { |
| 541 | blend->privates [n] = 0; |
| 542 | blend->font_infos[n] = 0; |
David Turner | 8db6a07 | 2002-07-11 11:26:21 +0000 | [diff] [blame] | 543 | blend->bboxes [n] = 0; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 544 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 545 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 546 | /* release weight vectors */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 547 | FT_FREE( blend->weight_vector ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 548 | blend->default_weight_vector = 0; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 549 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 550 | /* release axis names */ |
| 551 | for ( n = 0; n < num_axis; n++ ) |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 552 | FT_FREE( blend->axis_names[n] ); |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 553 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 554 | /* release design map */ |
| 555 | for ( n = 0; n < num_axis; n++ ) |
| 556 | { |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 557 | PS_DesignMap dmap = blend->design_map + n; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 558 | |
David Turner | 7c388ba | 2000-05-26 02:07:40 +0000 | [diff] [blame] | 559 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 560 | FT_FREE( dmap->design_points ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 561 | dmap->num_points = 0; |
| 562 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 563 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 564 | FT_FREE( face->blend ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 565 | } |
| 566 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 567 | |
| 568 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 569 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 570 | parse_blend_axis_types( T1_Face face, |
| 571 | T1_Loader loader ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 572 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 573 | T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 574 | FT_Int n, num_axis; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 575 | FT_Error error = T1_Err_Ok; |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 576 | PS_Blend blend; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 577 | FT_Memory memory; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 578 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 579 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 580 | /* take an array of objects */ |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 581 | T1_ToTokenArray( &loader->parser, axis_tokens, |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 582 | T1_MAX_MM_AXIS, &num_axis ); |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 583 | if ( num_axis < 0 ) |
| 584 | { |
| 585 | error = T1_Err_Ignore; |
| 586 | goto Exit; |
| 587 | } |
| 588 | if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 589 | { |
| 590 | FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", |
| 591 | num_axis )); |
| 592 | error = T1_Err_Invalid_File_Format; |
| 593 | goto Exit; |
| 594 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 595 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 596 | /* allocate blend if necessary */ |
| 597 | error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); |
| 598 | if ( error ) |
| 599 | goto Exit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 600 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 601 | blend = face->blend; |
| 602 | memory = face->root.memory; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 603 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 604 | /* each token is an immediate containing the name of the axis */ |
| 605 | for ( n = 0; n < num_axis; n++ ) |
| 606 | { |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 607 | T1_Token token = axis_tokens + n; |
| 608 | FT_Byte* name; |
| 609 | FT_PtrDist len; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 610 | |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 611 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 612 | /* skip first slash, if any */ |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 613 | if ( token->start[0] == '/' ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 614 | token->start++; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 615 | |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 616 | len = token->limit - token->start; |
Werner Lemberg | 77c34b8 | 2003-05-20 22:06:38 +0000 | [diff] [blame] | 617 | if ( len == 0 ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 618 | { |
| 619 | error = T1_Err_Invalid_File_Format; |
| 620 | goto Exit; |
| 621 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 622 | |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 623 | if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 624 | goto Exit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 625 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 626 | name = (FT_Byte*)blend->axis_names[n]; |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 627 | FT_MEM_COPY( name, token->start, len ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 628 | name[len] = 0; |
| 629 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 630 | |
| 631 | Exit: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 632 | loader->parser.root.error = error; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 633 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 634 | |
| 635 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 636 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 637 | parse_blend_design_positions( T1_Face face, |
| 638 | T1_Loader loader ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 639 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 640 | T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 641 | FT_Int num_designs; |
| 642 | FT_Int num_axis; |
| 643 | T1_Parser parser = &loader->parser; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 644 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 645 | FT_Error error = T1_Err_Ok; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 646 | PS_Blend blend; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 647 | |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 648 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 649 | /* get the array of design tokens -- compute number of designs */ |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 650 | T1_ToTokenArray( parser, design_tokens, |
| 651 | T1_MAX_MM_DESIGNS, &num_designs ); |
| 652 | if ( num_designs < 0 ) |
| 653 | { |
| 654 | error = T1_Err_Ignore; |
| 655 | goto Exit; |
| 656 | } |
| 657 | if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 658 | { |
| 659 | FT_ERROR(( "parse_blend_design_positions:" )); |
| 660 | FT_ERROR(( " incorrect number of designs: %d\n", |
| 661 | num_designs )); |
| 662 | error = T1_Err_Invalid_File_Format; |
| 663 | goto Exit; |
| 664 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 665 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 666 | { |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 667 | FT_Byte* old_cursor = parser->root.cursor; |
| 668 | FT_Byte* old_limit = parser->root.limit; |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 669 | FT_Int n; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 670 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 671 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 672 | blend = face->blend; |
| 673 | num_axis = 0; /* make compiler happy */ |
| 674 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 675 | for ( n = 0; n < num_designs; n++ ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 676 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 677 | T1_TokenRec axis_tokens[T1_MAX_MM_DESIGNS]; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 678 | T1_Token token; |
| 679 | FT_Int axis, n_axis; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 680 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 681 | |
| 682 | /* read axis/coordinates tokens */ |
| 683 | token = design_tokens + n; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 684 | parser->root.cursor = token->start; |
| 685 | parser->root.limit = token->limit; |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 686 | T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis ); |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 687 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 688 | if ( n == 0 ) |
| 689 | { |
| 690 | num_axis = n_axis; |
| 691 | error = t1_allocate_blend( face, num_designs, num_axis ); |
| 692 | if ( error ) |
| 693 | goto Exit; |
| 694 | blend = face->blend; |
| 695 | } |
| 696 | else if ( n_axis != num_axis ) |
| 697 | { |
| 698 | FT_ERROR(( "parse_blend_design_positions: incorrect table\n" )); |
| 699 | error = T1_Err_Invalid_File_Format; |
| 700 | goto Exit; |
| 701 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 702 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 703 | /* now read each axis token into the design position */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 704 | for ( axis = 0; axis < n_axis; axis++ ) |
| 705 | { |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 706 | T1_Token token2 = axis_tokens + axis; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 707 | |
| 708 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 709 | parser->root.cursor = token2->start; |
| 710 | parser->root.limit = token2->limit; |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 711 | blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 712 | } |
| 713 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 714 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 715 | loader->parser.root.cursor = old_cursor; |
| 716 | loader->parser.root.limit = old_limit; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 717 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 718 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 719 | Exit: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 720 | loader->parser.root.error = error; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 721 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 722 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 723 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 724 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 725 | parse_blend_design_map( T1_Face face, |
| 726 | T1_Loader loader ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 727 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 728 | FT_Error error = T1_Err_Ok; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 729 | T1_Parser parser = &loader->parser; |
| 730 | PS_Blend blend; |
| 731 | T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; |
| 732 | FT_Int n, num_axis; |
| 733 | FT_Byte* old_cursor; |
| 734 | FT_Byte* old_limit; |
| 735 | FT_Memory memory = face->root.memory; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 736 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 737 | |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 738 | T1_ToTokenArray( parser, axis_tokens, |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 739 | T1_MAX_MM_AXIS, &num_axis ); |
| 740 | if ( num_axis < 0 ) |
| 741 | { |
| 742 | error = T1_Err_Ignore; |
| 743 | goto Exit; |
| 744 | } |
| 745 | if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 746 | { |
| 747 | FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", |
| 748 | num_axis )); |
| 749 | error = T1_Err_Invalid_File_Format; |
| 750 | goto Exit; |
| 751 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 752 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 753 | old_cursor = parser->root.cursor; |
| 754 | old_limit = parser->root.limit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 755 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 756 | error = t1_allocate_blend( face, 0, num_axis ); |
| 757 | if ( error ) |
| 758 | goto Exit; |
| 759 | blend = face->blend; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 760 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 761 | /* now read each axis design map */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 762 | for ( n = 0; n < num_axis; n++ ) |
| 763 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 764 | PS_DesignMap map = blend->design_map + n; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 765 | T1_Token axis_token; |
| 766 | T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS]; |
Werner Lemberg | 8728f29 | 2000-08-23 17:32:42 +0000 | [diff] [blame] | 767 | FT_Int p, num_points; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 768 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 769 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 770 | axis_token = axis_tokens + n; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 771 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 772 | parser->root.cursor = axis_token->start; |
| 773 | parser->root.limit = axis_token->limit; |
| 774 | T1_ToTokenArray( parser, point_tokens, |
| 775 | T1_MAX_MM_MAP_POINTS, &num_points ); |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 776 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 777 | if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) |
| 778 | { |
| 779 | FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); |
| 780 | error = T1_Err_Invalid_File_Format; |
| 781 | goto Exit; |
| 782 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 783 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 784 | /* allocate design map data */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 785 | if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 786 | goto Exit; |
| 787 | map->blend_points = map->design_points + num_points; |
| 788 | map->num_points = (FT_Byte)num_points; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 789 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 790 | for ( p = 0; p < num_points; p++ ) |
| 791 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 792 | T1_Token point_token; |
| 793 | |
| 794 | |
| 795 | point_token = point_tokens + p; |
| 796 | |
| 797 | /* don't include delimiting brackets */ |
| 798 | parser->root.cursor = point_token->start + 1; |
| 799 | parser->root.limit = point_token->limit - 1; |
| 800 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 801 | map->design_points[p] = T1_ToInt( parser ); |
| 802 | map->blend_points [p] = T1_ToFixed( parser, 0 ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 803 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 804 | } |
| 805 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 806 | parser->root.cursor = old_cursor; |
| 807 | parser->root.limit = old_limit; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 808 | |
| 809 | Exit: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 810 | parser->root.error = error; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 811 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 812 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 813 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 814 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 815 | parse_weight_vector( T1_Face face, |
| 816 | T1_Loader loader ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 817 | { |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 818 | T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; |
| 819 | FT_Int num_designs; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 820 | FT_Error error = T1_Err_Ok; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 821 | T1_Parser parser = &loader->parser; |
| 822 | PS_Blend blend = face->blend; |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 823 | T1_Token token; |
| 824 | FT_Int n; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 825 | FT_Byte* old_cursor; |
| 826 | FT_Byte* old_limit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 827 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 828 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 829 | T1_ToTokenArray( parser, design_tokens, |
| 830 | T1_MAX_MM_DESIGNS, &num_designs ); |
| 831 | if ( num_designs < 0 ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 832 | { |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 833 | error = T1_Err_Ignore; |
| 834 | goto Exit; |
| 835 | } |
| 836 | if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) |
| 837 | { |
| 838 | FT_ERROR(( "parse_weight_vector:" )); |
| 839 | FT_ERROR(( " incorrect number of designs: %d\n", |
| 840 | num_designs )); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 841 | error = T1_Err_Invalid_File_Format; |
| 842 | goto Exit; |
| 843 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 844 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 845 | if ( !blend || !blend->num_designs ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 846 | { |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 847 | error = t1_allocate_blend( face, num_designs, 0 ); |
| 848 | if ( error ) |
| 849 | goto Exit; |
| 850 | blend = face->blend; |
| 851 | } |
| 852 | else if ( blend->num_designs != (FT_UInt)num_designs ) |
| 853 | { |
| 854 | FT_ERROR(( "parse_weight_vector:" |
| 855 | " /BlendDesignPosition and /WeightVector have\n" )); |
| 856 | FT_ERROR(( " " |
| 857 | " different number of elements!\n" )); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 858 | error = T1_Err_Invalid_File_Format; |
| 859 | goto Exit; |
| 860 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 861 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 862 | old_cursor = parser->root.cursor; |
| 863 | old_limit = parser->root.limit; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 864 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 865 | for ( n = 0; n < num_designs; n++ ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 866 | { |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 867 | token = design_tokens + n; |
| 868 | parser->root.cursor = token->start; |
| 869 | parser->root.limit = token->limit; |
| 870 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 871 | blend->default_weight_vector[n] = |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 872 | blend->weight_vector[n] = T1_ToFixed( parser, 0 ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 873 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 874 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 875 | parser->root.cursor = old_cursor; |
| 876 | parser->root.limit = old_limit; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 877 | |
| 878 | Exit: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 879 | parser->root.error = error; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 880 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 881 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 882 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 883 | /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ |
| 884 | /* we're only interested in the number of array elements */ |
| 885 | static void |
| 886 | parse_buildchar( T1_Face face, |
| 887 | T1_Loader loader ) |
| 888 | { |
| 889 | face->len_buildchar = T1_ToFixedArray( &loader->parser, 0, NULL, 0 ); |
| 890 | |
| 891 | return; |
| 892 | } |
| 893 | |
| 894 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 895 | #endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 896 | |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 897 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 898 | |
| 899 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 900 | /*************************************************************************/ |
| 901 | /*************************************************************************/ |
| 902 | /***** *****/ |
| 903 | /***** TYPE 1 SYMBOL PARSING *****/ |
| 904 | /***** *****/ |
| 905 | /*************************************************************************/ |
| 906 | /*************************************************************************/ |
| 907 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 908 | static FT_Error |
Werner Lemberg | fdc042b | 2003-06-12 04:59:07 +0000 | [diff] [blame] | 909 | t1_load_keyword( T1_Face face, |
| 910 | T1_Loader loader, |
| 911 | const T1_Field field ) |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 912 | { |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 913 | FT_Error error; |
| 914 | void* dummy_object; |
| 915 | void** objects; |
| 916 | FT_UInt max_objects; |
| 917 | PS_Blend blend = face->blend; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 918 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 919 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 920 | /* if the keyword has a dedicated callback, call it */ |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 921 | if ( field->type == T1_FIELD_TYPE_CALLBACK ) |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 922 | { |
David Turner | 34f1c2f | 2000-08-23 22:47:44 +0000 | [diff] [blame] | 923 | field->reader( (FT_Face)face, loader ); |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 924 | error = loader->parser.root.error; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 925 | goto Exit; |
| 926 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 927 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 928 | /* now, the keyword is either a simple field, or a table of fields; */ |
| 929 | /* we are now going to take care of it */ |
David Turner | 34f1c2f | 2000-08-23 22:47:44 +0000 | [diff] [blame] | 930 | switch ( field->location ) |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 931 | { |
David Turner | 429978b | 2002-03-14 10:09:35 +0000 | [diff] [blame] | 932 | case T1_FIELD_LOCATION_FONT_INFO: |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 933 | dummy_object = &face->type1.font_info; |
| 934 | objects = &dummy_object; |
| 935 | max_objects = 0; |
| 936 | |
| 937 | if ( blend ) |
| 938 | { |
| 939 | objects = (void**)blend->font_infos; |
| 940 | max_objects = blend->num_designs; |
| 941 | } |
| 942 | break; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 943 | |
David Turner | 429978b | 2002-03-14 10:09:35 +0000 | [diff] [blame] | 944 | case T1_FIELD_LOCATION_PRIVATE: |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 945 | dummy_object = &face->type1.private_dict; |
| 946 | objects = &dummy_object; |
| 947 | max_objects = 0; |
| 948 | |
| 949 | if ( blend ) |
| 950 | { |
| 951 | objects = (void**)blend->privates; |
| 952 | max_objects = blend->num_designs; |
| 953 | } |
| 954 | break; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 955 | |
David Turner | 8db6a07 | 2002-07-11 11:26:21 +0000 | [diff] [blame] | 956 | case T1_FIELD_LOCATION_BBOX: |
| 957 | dummy_object = &face->type1.font_bbox; |
| 958 | objects = &dummy_object; |
| 959 | max_objects = 0; |
| 960 | |
| 961 | if ( blend ) |
| 962 | { |
| 963 | objects = (void**)blend->bboxes; |
| 964 | max_objects = blend->num_designs; |
| 965 | } |
| 966 | break; |
| 967 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 968 | case T1_FIELD_LOCATION_LOADER: |
| 969 | dummy_object = loader; |
| 970 | objects = &dummy_object; |
| 971 | max_objects = 0; |
| 972 | break; |
| 973 | |
| 974 | case T1_FIELD_LOCATION_FACE: |
| 975 | dummy_object = face; |
| 976 | objects = &dummy_object; |
| 977 | max_objects = 0; |
| 978 | break; |
| 979 | |
| 980 | #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
| 981 | case T1_FIELD_LOCATION_BLEND: |
| 982 | dummy_object = face->blend; |
| 983 | objects = &dummy_object; |
| 984 | max_objects = 0; |
| 985 | break; |
| 986 | #endif |
| 987 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 988 | default: |
| 989 | dummy_object = &face->type1; |
| 990 | objects = &dummy_object; |
| 991 | max_objects = 0; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 992 | } |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 993 | |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 994 | if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || |
| 995 | field->type == T1_FIELD_TYPE_FIXED_ARRAY ) |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 996 | error = T1_Load_Field_Table( &loader->parser, field, |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 997 | objects, max_objects, 0 ); |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 998 | else |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 999 | error = T1_Load_Field( &loader->parser, field, |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1000 | objects, max_objects, 0 ); |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 1001 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 1002 | Exit: |
| 1003 | return error; |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 1004 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1005 | |
| 1006 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1007 | static void |
| 1008 | parse_private( T1_Face face, |
| 1009 | T1_Loader loader ) |
| 1010 | { |
| 1011 | FT_UNUSED( face ); |
| 1012 | |
| 1013 | loader->keywords_encountered |= T1_PRIVATE; |
| 1014 | } |
| 1015 | |
| 1016 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1017 | static int |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 1018 | read_binary_data( T1_Parser parser, |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 1019 | FT_Long* size, |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1020 | FT_Byte** base ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1021 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1022 | FT_Byte* cur; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1023 | FT_Byte* limit = parser->root.limit; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1024 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1025 | |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1026 | /* the binary data has one of the following formats */ |
| 1027 | /* */ |
| 1028 | /* `size' [white*] RD white ....... ND */ |
| 1029 | /* `size' [white*] -| white ....... |- */ |
| 1030 | /* */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1031 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1032 | T1_Skip_Spaces( parser ); |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1033 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1034 | cur = parser->root.cursor; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1035 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1036 | if ( cur < limit && ft_isdigit( *cur ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1037 | { |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1038 | *size = T1_ToInt( parser ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1039 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1040 | T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1041 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1042 | /* there is only one whitespace char after the */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1043 | /* `RD' or `-|' token */ |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1044 | *base = parser->root.cursor + 1; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1045 | |
Werner Lemberg | 8728f29 | 2000-08-23 17:32:42 +0000 | [diff] [blame] | 1046 | parser->root.cursor += *size + 1; |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1047 | return !parser->root.error; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1048 | } |
| 1049 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1050 | FT_ERROR(( "read_binary_data: invalid size field\n" )); |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1051 | parser->root.error = T1_Err_Invalid_File_Format; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1052 | return 0; |
| 1053 | } |
| 1054 | |
| 1055 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1056 | /* We now define the routines to handle the `/Encoding', `/Subrs', */ |
| 1057 | /* and `/CharStrings' dictionaries. */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1058 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1059 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1060 | parse_font_matrix( T1_Face face, |
| 1061 | T1_Loader loader ) |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 1062 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1063 | T1_Parser parser = &loader->parser; |
| 1064 | FT_Matrix* matrix = &face->type1.font_matrix; |
| 1065 | FT_Vector* offset = &face->type1.font_offset; |
| 1066 | FT_Face root = (FT_Face)&face->root; |
| 1067 | FT_Fixed temp[6]; |
| 1068 | FT_Fixed temp_scale; |
Werner Lemberg | e5c14d9 | 2007-06-05 20:50:37 +0000 | [diff] [blame] | 1069 | FT_Int result; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 1070 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1071 | |
Werner Lemberg | e5c14d9 | 2007-06-05 20:50:37 +0000 | [diff] [blame] | 1072 | result = T1_ToFixedArray( parser, 6, temp, 3 ); |
| 1073 | |
| 1074 | if ( result < 0 ) |
| 1075 | { |
| 1076 | parser->root.error = T1_Err_Invalid_File_Format; |
| 1077 | return; |
| 1078 | } |
David Turner | 24d7024 | 2000-08-17 01:09:06 +0000 | [diff] [blame] | 1079 | |
Werner Lemberg | dfa4619 | 2004-03-05 09:26:24 +0000 | [diff] [blame] | 1080 | temp_scale = FT_ABS( temp[3] ); |
Tom Kacvinsky | b2d5fef | 2001-01-24 22:41:20 +0000 | [diff] [blame] | 1081 | |
Werner Lemberg | 470210b | 2007-06-06 10:05:49 +0000 | [diff] [blame] | 1082 | if ( temp_scale == 0 ) |
| 1083 | { |
| 1084 | FT_ERROR(( "parse_font_matrix: invalid font matrix\n" )); |
| 1085 | parser->root.error = T1_Err_Invalid_File_Format; |
| 1086 | return; |
| 1087 | } |
| 1088 | |
Werner Lemberg | ec34290 | 2001-09-10 06:55:43 +0000 | [diff] [blame] | 1089 | /* Set Units per EM based on FontMatrix values. We set the value to */ |
| 1090 | /* 1000 / temp_scale, because temp_scale was already multiplied by */ |
| 1091 | /* 1000 (in t1_tofixed, from psobjs.c). */ |
Tom Kacvinsky | f3dad68 | 2001-03-19 13:52:31 +0000 | [diff] [blame] | 1092 | |
Werner Lemberg | ec34290 | 2001-09-10 06:55:43 +0000 | [diff] [blame] | 1093 | root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L, |
| 1094 | temp_scale ) >> 16 ); |
Tom Kacvinsky | b2d5fef | 2001-01-24 22:41:20 +0000 | [diff] [blame] | 1095 | |
| 1096 | /* we need to scale the values by 1.0/temp_scale */ |
| 1097 | if ( temp_scale != 0x10000L ) |
David Turner | 24d7024 | 2000-08-17 01:09:06 +0000 | [diff] [blame] | 1098 | { |
Tom Kacvinsky | b2d5fef | 2001-01-24 22:41:20 +0000 | [diff] [blame] | 1099 | temp[0] = FT_DivFix( temp[0], temp_scale ); |
| 1100 | temp[1] = FT_DivFix( temp[1], temp_scale ); |
| 1101 | temp[2] = FT_DivFix( temp[2], temp_scale ); |
| 1102 | temp[4] = FT_DivFix( temp[4], temp_scale ); |
| 1103 | temp[5] = FT_DivFix( temp[5], temp_scale ); |
Werner Lemberg | b1c8bf0 | 2000-08-17 07:18:04 +0000 | [diff] [blame] | 1104 | temp[3] = 0x10000L; |
David Turner | 24d7024 | 2000-08-17 01:09:06 +0000 | [diff] [blame] | 1105 | } |
| 1106 | |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 1107 | matrix->xx = temp[0]; |
| 1108 | matrix->yx = temp[1]; |
| 1109 | matrix->xy = temp[2]; |
| 1110 | matrix->yy = temp[3]; |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 1111 | |
Werner Lemberg | 6fbe4db | 2000-10-05 04:53:31 +0000 | [diff] [blame] | 1112 | /* note that the offsets must be expressed in integer font units */ |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1113 | offset->x = temp[4] >> 16; |
| 1114 | offset->y = temp[5] >> 16; |
David Turner | 1c9a1ca | 2000-05-24 21:12:02 +0000 | [diff] [blame] | 1115 | } |
| 1116 | |
| 1117 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1118 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1119 | parse_encoding( T1_Face face, |
| 1120 | T1_Loader loader ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1121 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1122 | T1_Parser parser = &loader->parser; |
| 1123 | FT_Byte* cur; |
| 1124 | FT_Byte* limit = parser->root.limit; |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 1125 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1126 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1127 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1128 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1129 | T1_Skip_Spaces( parser ); |
| 1130 | cur = parser->root.cursor; |
| 1131 | if ( cur >= limit ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1132 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1133 | FT_ERROR(( "parse_encoding: out of bounds!\n" )); |
| 1134 | parser->root.error = T1_Err_Invalid_File_Format; |
| 1135 | return; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1136 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1137 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1138 | /* if we have a number or `[', the encoding is an array, */ |
| 1139 | /* and we must load it now */ |
| 1140 | if ( ft_isdigit( *cur ) || *cur == '[' ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1141 | { |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1142 | T1_Encoding encode = &face->type1.encoding; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1143 | FT_Int count, n; |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1144 | PS_Table char_table = &loader->encoding_table; |
| 1145 | FT_Memory memory = parser->root.memory; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1146 | FT_Error error; |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1147 | FT_Bool only_immediates = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1148 | |
Werner Lemberg | c3b2160 | 2001-12-05 01:22:05 +0000 | [diff] [blame] | 1149 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1150 | /* read the number of entries in the encoding; should be 256 */ |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1151 | if ( *cur == '[' ) |
| 1152 | { |
| 1153 | count = 256; |
| 1154 | only_immediates = 1; |
| 1155 | parser->root.cursor++; |
| 1156 | } |
| 1157 | else |
| 1158 | count = (FT_Int)T1_ToInt( parser ); |
| 1159 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1160 | T1_Skip_Spaces( parser ); |
| 1161 | if ( parser->root.cursor >= limit ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1162 | return; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1163 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1164 | /* we use a T1_Table to store our charnames */ |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1165 | loader->num_chars = encode->num_chars = count; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1166 | if ( FT_NEW_ARRAY( encode->char_index, count ) || |
| 1167 | FT_NEW_ARRAY( encode->char_name, count ) || |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1168 | FT_SET_ERROR( psaux->ps_table_funcs->init( |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1169 | char_table, count, memory ) ) ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1170 | { |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1171 | parser->root.error = error; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1172 | return; |
| 1173 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1174 | |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1175 | /* We need to `zero' out encoding_table.elements */ |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1176 | for ( n = 0; n < count; n++ ) |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1177 | { |
Werner Lemberg | a13a473 | 2000-11-02 15:14:38 +0000 | [diff] [blame] | 1178 | char* notdef = (char *)".notdef"; |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1179 | |
| 1180 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1181 | T1_Add_Table( char_table, n, notdef, 8 ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1182 | } |
| 1183 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1184 | /* Now we need to read records of the form */ |
| 1185 | /* */ |
| 1186 | /* ... charcode /charname ... */ |
| 1187 | /* */ |
| 1188 | /* for each entry in our table. */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1189 | /* */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1190 | /* We simply look for a number followed by an immediate */ |
| 1191 | /* name. Note that this ignores correctly the sequence */ |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1192 | /* that is often seen in type1 fonts: */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1193 | /* */ |
| 1194 | /* 0 1 255 { 1 index exch /.notdef put } for dup */ |
| 1195 | /* */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1196 | /* used to clean the encoding array before anything else. */ |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1197 | /* */ |
| 1198 | /* Alternatively, if the array is directly given as */ |
| 1199 | /* */ |
| 1200 | /* /Encoding [ ... ] */ |
| 1201 | /* */ |
| 1202 | /* we only read immediates. */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1203 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1204 | n = 0; |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1205 | T1_Skip_Spaces( parser ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1206 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1207 | while ( parser->root.cursor < limit ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1208 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1209 | cur = parser->root.cursor; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1210 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1211 | /* we stop when we encounter a `def' or `]' */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1212 | if ( *cur == 'd' && cur + 3 < limit ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1213 | { |
Werner Lemberg | 17432b5 | 2007-01-12 09:28:44 +0000 | [diff] [blame] | 1214 | if ( cur[1] == 'e' && |
| 1215 | cur[2] == 'f' && |
| 1216 | IS_PS_DELIM( cur[3] ) ) |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 1217 | { |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1218 | FT_TRACE6(( "encoding end\n" )); |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1219 | cur += 3; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1220 | break; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 1221 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1222 | } |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1223 | if ( *cur == ']' ) |
| 1224 | { |
| 1225 | FT_TRACE6(( "encoding end\n" )); |
| 1226 | cur++; |
| 1227 | break; |
| 1228 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1229 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1230 | /* check whether we've found an entry */ |
| 1231 | if ( ft_isdigit( *cur ) || only_immediates ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1232 | { |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1233 | FT_Int charcode; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1234 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1235 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1236 | if ( only_immediates ) |
| 1237 | charcode = n; |
| 1238 | else |
| 1239 | { |
| 1240 | charcode = (FT_Int)T1_ToInt( parser ); |
| 1241 | T1_Skip_Spaces( parser ); |
| 1242 | } |
| 1243 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1244 | cur = parser->root.cursor; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1245 | |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1246 | if ( *cur == '/' && cur + 2 < limit && n < count ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1247 | { |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 1248 | FT_PtrDist len; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1249 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1250 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1251 | cur++; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1252 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1253 | parser->root.cursor = cur; |
| 1254 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1255 | if ( parser->root.error ) |
| 1256 | return; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1257 | |
| 1258 | len = parser->root.cursor - cur; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1259 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1260 | parser->root.error = T1_Add_Table( char_table, charcode, |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1261 | cur, len + 1 ); |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1262 | if ( parser->root.error ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1263 | return; |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1264 | char_table->elements[charcode][len] = '\0'; |
Werner Lemberg | 4795b36 | 2003-10-23 16:24:10 +0000 | [diff] [blame] | 1265 | |
| 1266 | n++; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1267 | } |
| 1268 | } |
| 1269 | else |
Werner Lemberg | 9fe5815 | 2007-06-19 07:57:30 +0000 | [diff] [blame] | 1270 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1271 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 9fe5815 | 2007-06-19 07:57:30 +0000 | [diff] [blame] | 1272 | if ( parser->root.error ) |
| 1273 | return; |
| 1274 | } |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1275 | |
| 1276 | T1_Skip_Spaces( parser ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1277 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1278 | |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 1279 | face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; |
Werner Lemberg | 8728f29 | 2000-08-23 17:32:42 +0000 | [diff] [blame] | 1280 | parser->root.cursor = cur; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1281 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1282 | |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1283 | /* Otherwise, we should have either `StandardEncoding', */ |
| 1284 | /* `ExpertEncoding', or `ISOLatin1Encoding' */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1285 | else |
| 1286 | { |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1287 | if ( cur + 17 < limit && |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 1288 | ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 1289 | face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1290 | |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1291 | else if ( cur + 15 < limit && |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 1292 | ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1293 | face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1294 | |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1295 | else if ( cur + 18 < limit && |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 1296 | ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 1297 | face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; |
Werner Lemberg | 66b3509 | 2002-02-10 12:33:14 +0000 | [diff] [blame] | 1298 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1299 | else |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1300 | parser->root.error = T1_Err_Ignore; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1301 | } |
| 1302 | } |
| 1303 | |
| 1304 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1305 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1306 | parse_subrs( T1_Face face, |
| 1307 | T1_Loader loader ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1308 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1309 | T1_Parser parser = &loader->parser; |
| 1310 | PS_Table table = &loader->subrs; |
| 1311 | FT_Memory memory = parser->root.memory; |
| 1312 | FT_Error error; |
Werner Lemberg | 3480819 | 2003-10-07 11:54:03 +0000 | [diff] [blame] | 1313 | FT_Int n, num_subrs; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1314 | |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1315 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
Werner Lemberg | 8728f29 | 2000-08-23 17:32:42 +0000 | [diff] [blame] | 1316 | |
Werner Lemberg | c3b2160 | 2001-12-05 01:22:05 +0000 | [diff] [blame] | 1317 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1318 | T1_Skip_Spaces( parser ); |
| 1319 | |
| 1320 | /* test for empty array */ |
| 1321 | if ( parser->root.cursor < parser->root.limit && |
| 1322 | *parser->root.cursor == '[' ) |
David Turner | 621e488 | 2002-12-16 21:51:24 +0000 | [diff] [blame] | 1323 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1324 | T1_Skip_PS_Token( parser ); |
| 1325 | T1_Skip_Spaces ( parser ); |
| 1326 | if ( parser->root.cursor >= parser->root.limit || |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1327 | *parser->root.cursor != ']' ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1328 | parser->root.error = T1_Err_Invalid_File_Format; |
David Turner | 621e488 | 2002-12-16 21:51:24 +0000 | [diff] [blame] | 1329 | return; |
| 1330 | } |
| 1331 | |
Werner Lemberg | 3480819 | 2003-10-07 11:54:03 +0000 | [diff] [blame] | 1332 | num_subrs = (FT_Int)T1_ToInt( parser ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1333 | |
Werner Lemberg | d082cd6 | 2000-07-25 17:25:32 +0000 | [diff] [blame] | 1334 | /* position the parser right before the `dup' of the first subr */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1335 | T1_Skip_PS_Token( parser ); /* `array' */ |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1336 | if ( parser->root.error ) |
| 1337 | return; |
| 1338 | T1_Skip_Spaces( parser ); |
Just van Rossum | 53fb1f5 | 2000-07-25 16:20:57 +0000 | [diff] [blame] | 1339 | |
Werner Lemberg | ed3a7d7 | 2003-10-07 20:06:35 +0000 | [diff] [blame] | 1340 | /* initialize subrs array -- with synthetic fonts it is possible */ |
| 1341 | /* we get here twice */ |
| 1342 | if ( !loader->num_subrs ) |
| 1343 | { |
| 1344 | error = psaux->ps_table_funcs->init( table, num_subrs, memory ); |
| 1345 | if ( error ) |
| 1346 | goto Fail; |
| 1347 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1348 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1349 | /* the format is simple: */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1350 | /* */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1351 | /* `index' + binary data */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1352 | /* */ |
Werner Lemberg | 3480819 | 2003-10-07 11:54:03 +0000 | [diff] [blame] | 1353 | for ( n = 0; n < num_subrs; n++ ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1354 | { |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 1355 | FT_Long idx, size; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1356 | FT_Byte* base; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1357 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1358 | |
Werner Lemberg | d082cd6 | 2000-07-25 17:25:32 +0000 | [diff] [blame] | 1359 | /* If the next token isn't `dup', we are also done. This */ |
| 1360 | /* happens when there are `holes' in the Subrs array. */ |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 1361 | if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 ) |
Just van Rossum | 53fb1f5 | 2000-07-25 16:20:57 +0000 | [diff] [blame] | 1362 | break; |
| 1363 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1364 | T1_Skip_PS_Token( parser ); /* `dup' */ |
| 1365 | |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 1366 | idx = T1_ToInt( parser ); |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 1367 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1368 | if ( !read_binary_data( parser, &size, &base ) ) |
| 1369 | return; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1370 | |
Werner Lemberg | d082cd6 | 2000-07-25 17:25:32 +0000 | [diff] [blame] | 1371 | /* The binary string is followed by one token, e.g. `NP' */ |
| 1372 | /* (bound to `noaccess put') or by two separate tokens: */ |
| 1373 | /* `noaccess' & `put'. We position the parser right */ |
| 1374 | /* before the next `dup', if any. */ |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1375 | T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */ |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1376 | if ( parser->root.error ) |
| 1377 | return; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1378 | T1_Skip_Spaces ( parser ); |
Werner Lemberg | d082cd6 | 2000-07-25 17:25:32 +0000 | [diff] [blame] | 1379 | |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 1380 | if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 ) |
Just van Rossum | 53fb1f5 | 2000-07-25 16:20:57 +0000 | [diff] [blame] | 1381 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1382 | T1_Skip_PS_Token( parser ); /* skip `put' */ |
| 1383 | T1_Skip_Spaces ( parser ); |
Just van Rossum | 53fb1f5 | 2000-07-25 16:20:57 +0000 | [diff] [blame] | 1384 | } |
| 1385 | |
Werner Lemberg | 3480819 | 2003-10-07 11:54:03 +0000 | [diff] [blame] | 1386 | /* with synthetic fonts it is possible we get here twice */ |
| 1387 | if ( loader->num_subrs ) |
| 1388 | continue; |
| 1389 | |
David Turner | d0079e6 | 2000-06-23 00:07:06 +0000 | [diff] [blame] | 1390 | /* some fonts use a value of -1 for lenIV to indicate that */ |
Werner Lemberg | d082cd6 | 2000-07-25 17:25:32 +0000 | [diff] [blame] | 1391 | /* the charstrings are unencoded */ |
David Turner | d0079e6 | 2000-06-23 00:07:06 +0000 | [diff] [blame] | 1392 | /* */ |
Werner Lemberg | d082cd6 | 2000-07-25 17:25:32 +0000 | [diff] [blame] | 1393 | /* thanks to Tom Kacvinsky for pointing this out */ |
David Turner | d0079e6 | 2000-06-23 00:07:06 +0000 | [diff] [blame] | 1394 | /* */ |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1395 | if ( face->type1.private_dict.lenIV >= 0 ) |
David Turner | d0079e6 | 2000-06-23 00:07:06 +0000 | [diff] [blame] | 1396 | { |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1397 | FT_Byte* temp; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 1398 | |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1399 | |
Werner Lemberg | 16dc51f | 2008-05-18 17:36:15 +0000 | [diff] [blame] | 1400 | /* some fonts define empty subr records -- this is not totally */ |
| 1401 | /* compliant to the specification (which says they should at */ |
| 1402 | /* least contain a `return'), but we support them anyway */ |
Werner Lemberg | 504645e | 2008-05-14 23:26:20 +0000 | [diff] [blame] | 1403 | if ( size < face->type1.private_dict.lenIV ) |
Werner Lemberg | ba03af6 | 2007-05-30 13:57:02 +0000 | [diff] [blame] | 1404 | { |
| 1405 | error = T1_Err_Invalid_File_Format; |
| 1406 | goto Fail; |
| 1407 | } |
| 1408 | |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1409 | /* t1_decrypt() shouldn't write to base -- make temporary copy */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1410 | if ( FT_ALLOC( temp, size ) ) |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1411 | goto Fail; |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1412 | FT_MEM_COPY( temp, base, size ); |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1413 | psaux->t1_decrypt( temp, size, 4330 ); |
| 1414 | size -= face->type1.private_dict.lenIV; |
Werner Lemberg | 7386197 | 2003-06-05 04:31:05 +0000 | [diff] [blame] | 1415 | error = T1_Add_Table( table, (FT_Int)idx, |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1416 | temp + face->type1.private_dict.lenIV, size ); |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1417 | FT_FREE( temp ); |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1418 | } |
| 1419 | else |
Werner Lemberg | 7386197 | 2003-06-05 04:31:05 +0000 | [diff] [blame] | 1420 | error = T1_Add_Table( table, (FT_Int)idx, base, size ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1421 | if ( error ) |
| 1422 | goto Fail; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1423 | } |
Werner Lemberg | 3480819 | 2003-10-07 11:54:03 +0000 | [diff] [blame] | 1424 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1425 | if ( !loader->num_subrs ) |
| 1426 | loader->num_subrs = num_subrs; |
Werner Lemberg | 3480819 | 2003-10-07 11:54:03 +0000 | [diff] [blame] | 1427 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1428 | return; |
| 1429 | |
| 1430 | Fail: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1431 | parser->root.error = error; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1432 | } |
| 1433 | |
| 1434 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1435 | #define TABLE_EXTEND 5 |
| 1436 | |
| 1437 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1438 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1439 | parse_charstrings( T1_Face face, |
| 1440 | T1_Loader loader ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1441 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1442 | T1_Parser parser = &loader->parser; |
| 1443 | PS_Table code_table = &loader->charstrings; |
| 1444 | PS_Table name_table = &loader->glyph_names; |
| 1445 | PS_Table swap_table = &loader->swap_table; |
| 1446 | FT_Memory memory = parser->root.memory; |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1447 | FT_Error error; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1448 | |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1449 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1450 | |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1451 | FT_Byte* cur; |
| 1452 | FT_Byte* limit = parser->root.limit; |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1453 | FT_Int n, num_glyphs; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1454 | FT_UInt notdef_index = 0; |
| 1455 | FT_Byte notdef_found = 0; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1456 | |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1457 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1458 | num_glyphs = (FT_Int)T1_ToInt( parser ); |
Werner Lemberg | cf7d908 | 2004-02-02 19:41:09 +0000 | [diff] [blame] | 1459 | /* some fonts like Optima-Oblique not only define the /CharStrings */ |
| 1460 | /* array but access it also */ |
| 1461 | if ( num_glyphs == 0 || parser->root.error ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1462 | return; |
| 1463 | |
Werner Lemberg | b36d4a5 | 2003-12-12 15:38:39 +0000 | [diff] [blame] | 1464 | /* initialize tables, leaving space for addition of .notdef, */ |
| 1465 | /* if necessary, and a few other glyphs to handle buggy */ |
| 1466 | /* fonts which have more glyphs than specified. */ |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1467 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1468 | /* for some non-standard fonts like `Optima' which provides */ |
| 1469 | /* different outlines depending on the resolution it is */ |
| 1470 | /* possible to get here twice */ |
| 1471 | if ( !loader->num_glyphs ) |
| 1472 | { |
| 1473 | error = psaux->ps_table_funcs->init( |
| 1474 | code_table, num_glyphs + 1 + TABLE_EXTEND, memory ); |
| 1475 | if ( error ) |
| 1476 | goto Fail; |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1477 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1478 | error = psaux->ps_table_funcs->init( |
| 1479 | name_table, num_glyphs + 1 + TABLE_EXTEND, memory ); |
| 1480 | if ( error ) |
| 1481 | goto Fail; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1482 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1483 | /* Initialize table for swapping index notdef_index and */ |
| 1484 | /* index 0 names and codes (if necessary). */ |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1485 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1486 | error = psaux->ps_table_funcs->init( swap_table, 4, memory ); |
| 1487 | if ( error ) |
| 1488 | goto Fail; |
| 1489 | } |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1490 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1491 | n = 0; |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1492 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1493 | for (;;) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1494 | { |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 1495 | FT_Long size; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 1496 | FT_Byte* base; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1497 | |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1498 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1499 | /* the format is simple: */ |
| 1500 | /* `/glyphname' + binary data */ |
Werner Lemberg | e3f4198 | 2003-10-16 15:48:39 +0000 | [diff] [blame] | 1501 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1502 | T1_Skip_Spaces( parser ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1503 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1504 | cur = parser->root.cursor; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1505 | if ( cur >= limit ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1506 | break; |
| 1507 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1508 | /* we stop when we find a `def' or `end' keyword */ |
Werner Lemberg | 17432b5 | 2007-01-12 09:28:44 +0000 | [diff] [blame] | 1509 | if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1510 | { |
| 1511 | if ( cur[0] == 'd' && |
| 1512 | cur[1] == 'e' && |
| 1513 | cur[2] == 'f' ) |
Werner Lemberg | e7602c4 | 2005-04-14 11:43:40 +0000 | [diff] [blame] | 1514 | { |
| 1515 | /* There are fonts which have this: */ |
| 1516 | /* */ |
| 1517 | /* /CharStrings 118 dict def */ |
| 1518 | /* Private begin */ |
| 1519 | /* CharStrings begin */ |
| 1520 | /* ... */ |
| 1521 | /* */ |
| 1522 | /* To catch this we ignore `def' if */ |
| 1523 | /* no charstring has actually been */ |
| 1524 | /* seen. */ |
| 1525 | if ( n ) |
| 1526 | break; |
| 1527 | } |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 1528 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1529 | if ( cur[0] == 'e' && |
| 1530 | cur[1] == 'n' && |
| 1531 | cur[2] == 'd' ) |
| 1532 | break; |
| 1533 | } |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1534 | |
Werner Lemberg | ed3a7d7 | 2003-10-07 20:06:35 +0000 | [diff] [blame] | 1535 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1536 | if ( parser->root.error ) |
| 1537 | return; |
Werner Lemberg | ed3a7d7 | 2003-10-07 20:06:35 +0000 | [diff] [blame] | 1538 | |
| 1539 | if ( *cur == '/' ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1540 | { |
Werner Lemberg | bc1837a | 2002-09-17 12:39:19 +0000 | [diff] [blame] | 1541 | FT_PtrDist len; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1542 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1543 | |
Werner Lemberg | ed3a7d7 | 2003-10-07 20:06:35 +0000 | [diff] [blame] | 1544 | if ( cur + 1 >= limit ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1545 | { |
| 1546 | error = T1_Err_Invalid_File_Format; |
| 1547 | goto Fail; |
| 1548 | } |
| 1549 | |
Werner Lemberg | ed3a7d7 | 2003-10-07 20:06:35 +0000 | [diff] [blame] | 1550 | cur++; /* skip `/' */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1551 | len = parser->root.cursor - cur; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1552 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1553 | if ( !read_binary_data( parser, &size, &base ) ) |
| 1554 | return; |
| 1555 | |
| 1556 | /* for some non-standard fonts like `Optima' which provides */ |
| 1557 | /* different outlines depending on the resolution it is */ |
| 1558 | /* possible to get here twice */ |
| 1559 | if ( loader->num_glyphs ) |
| 1560 | continue; |
| 1561 | |
Werner Lemberg | ed3a7d7 | 2003-10-07 20:06:35 +0000 | [diff] [blame] | 1562 | error = T1_Add_Table( name_table, n, cur, len + 1 ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1563 | if ( error ) |
| 1564 | goto Fail; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1565 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1566 | /* add a trailing zero to the name table */ |
| 1567 | name_table->elements[n][len] = '\0'; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1568 | |
Werner Lemberg | e3f4198 | 2003-10-16 15:48:39 +0000 | [diff] [blame] | 1569 | /* record index of /.notdef */ |
| 1570 | if ( *cur == '.' && |
| 1571 | ft_strcmp( ".notdef", |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 1572 | (const char*)(name_table->elements[n]) ) == 0 ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1573 | { |
| 1574 | notdef_index = n; |
| 1575 | notdef_found = 1; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1576 | } |
| 1577 | |
Werner Lemberg | ba03af6 | 2007-05-30 13:57:02 +0000 | [diff] [blame] | 1578 | if ( face->type1.private_dict.lenIV >= 0 && |
| 1579 | n < num_glyphs + TABLE_EXTEND ) |
David Turner | d0079e6 | 2000-06-23 00:07:06 +0000 | [diff] [blame] | 1580 | { |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1581 | FT_Byte* temp; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 1582 | |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1583 | |
Werner Lemberg | ba03af6 | 2007-05-30 13:57:02 +0000 | [diff] [blame] | 1584 | if ( size <= face->type1.private_dict.lenIV ) |
| 1585 | { |
| 1586 | error = T1_Err_Invalid_File_Format; |
| 1587 | goto Fail; |
| 1588 | } |
| 1589 | |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1590 | /* t1_decrypt() shouldn't write to base -- make temporary copy */ |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1591 | if ( FT_ALLOC( temp, size ) ) |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1592 | goto Fail; |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1593 | FT_MEM_COPY( temp, base, size ); |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1594 | psaux->t1_decrypt( temp, size, 4330 ); |
| 1595 | size -= face->type1.private_dict.lenIV; |
| 1596 | error = T1_Add_Table( code_table, n, |
| 1597 | temp + face->type1.private_dict.lenIV, size ); |
David Turner | e459d74 | 2002-03-22 13:52:37 +0000 | [diff] [blame] | 1598 | FT_FREE( temp ); |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 1599 | } |
| 1600 | else |
| 1601 | error = T1_Add_Table( code_table, n, base, size ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1602 | if ( error ) |
| 1603 | goto Fail; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1604 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1605 | n++; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1606 | } |
| 1607 | } |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1608 | |
Werner Lemberg | 5972e9a | 2004-02-01 00:49:56 +0000 | [diff] [blame] | 1609 | if ( loader->num_glyphs ) |
| 1610 | return; |
| 1611 | else |
| 1612 | loader->num_glyphs = n; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1613 | |
Werner Lemberg | e3f4198 | 2003-10-16 15:48:39 +0000 | [diff] [blame] | 1614 | /* if /.notdef is found but does not occupy index 0, do our magic. */ |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 1615 | if ( ft_strcmp( (const char*)".notdef", |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 1616 | (const char*)name_table->elements[0] ) && |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1617 | notdef_found ) |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1618 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1619 | /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ |
| 1620 | /* name and code entries to swap_table. Then place notdef_index */ |
| 1621 | /* name and code entries into swap_table. Then swap name and code */ |
| 1622 | /* entries at indices notdef_index and 0 using values stored in */ |
| 1623 | /* swap_table. */ |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1624 | |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1625 | /* Index 0 name */ |
| 1626 | error = T1_Add_Table( swap_table, 0, |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1627 | name_table->elements[0], |
| 1628 | name_table->lengths [0] ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1629 | if ( error ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1630 | goto Fail; |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1631 | |
| 1632 | /* Index 0 code */ |
| 1633 | error = T1_Add_Table( swap_table, 1, |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1634 | code_table->elements[0], |
| 1635 | code_table->lengths [0] ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1636 | if ( error ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1637 | goto Fail; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1638 | |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1639 | /* Index notdef_index name */ |
| 1640 | error = T1_Add_Table( swap_table, 2, |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1641 | name_table->elements[notdef_index], |
| 1642 | name_table->lengths [notdef_index] ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1643 | if ( error ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1644 | goto Fail; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1645 | |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1646 | /* Index notdef_index code */ |
| 1647 | error = T1_Add_Table( swap_table, 3, |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1648 | code_table->elements[notdef_index], |
| 1649 | code_table->lengths [notdef_index] ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1650 | if ( error ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1651 | goto Fail; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1652 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1653 | error = T1_Add_Table( name_table, notdef_index, |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1654 | swap_table->elements[0], |
| 1655 | swap_table->lengths [0] ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1656 | if ( error ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1657 | goto Fail; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1658 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1659 | error = T1_Add_Table( code_table, notdef_index, |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1660 | swap_table->elements[1], |
| 1661 | swap_table->lengths [1] ); |
| 1662 | if ( error ) |
| 1663 | goto Fail; |
| 1664 | |
| 1665 | error = T1_Add_Table( name_table, 0, |
| 1666 | swap_table->elements[2], |
| 1667 | swap_table->lengths [2] ); |
| 1668 | if ( error ) |
| 1669 | goto Fail; |
| 1670 | |
| 1671 | error = T1_Add_Table( code_table, 0, |
| 1672 | swap_table->elements[3], |
| 1673 | swap_table->lengths [3] ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1674 | if ( error ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1675 | goto Fail; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1676 | |
| 1677 | } |
| 1678 | else if ( !notdef_found ) |
| 1679 | { |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 1680 | /* notdef_index is already 0, or /.notdef is undefined in */ |
| 1681 | /* charstrings dictionary. Worry about /.notdef undefined. */ |
| 1682 | /* We take index 0 and add it to the end of the table(s) */ |
| 1683 | /* and add our own /.notdef glyph to index 0. */ |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 1684 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1685 | /* 0 333 hsbw endchar */ |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1686 | FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E}; |
Werner Lemberg | a13a473 | 2000-11-02 15:14:38 +0000 | [diff] [blame] | 1687 | char* notdef_name = (char *)".notdef"; |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 1688 | |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1689 | |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1690 | error = T1_Add_Table( swap_table, 0, |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1691 | name_table->elements[0], |
| 1692 | name_table->lengths [0] ); |
| 1693 | if ( error ) |
| 1694 | goto Fail; |
| 1695 | |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1696 | error = T1_Add_Table( swap_table, 1, |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1697 | code_table->elements[0], |
| 1698 | code_table->lengths [0] ); |
| 1699 | if ( error ) |
| 1700 | goto Fail; |
| 1701 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1702 | error = T1_Add_Table( name_table, 0, notdef_name, 8 ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1703 | if ( error ) |
| 1704 | goto Fail; |
| 1705 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1706 | error = T1_Add_Table( code_table, 0, notdef_glyph, 5 ); |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1707 | |
| 1708 | if ( error ) |
| 1709 | goto Fail; |
| 1710 | |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 1711 | error = T1_Add_Table( name_table, n, |
| 1712 | swap_table->elements[0], |
| 1713 | swap_table->lengths [0] ); |
| 1714 | if ( error ) |
| 1715 | goto Fail; |
| 1716 | |
| 1717 | error = T1_Add_Table( code_table, n, |
| 1718 | swap_table->elements[1], |
| 1719 | swap_table->lengths [1] ); |
| 1720 | if ( error ) |
| 1721 | goto Fail; |
| 1722 | |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1723 | /* we added a glyph. */ |
| 1724 | loader->num_glyphs = n + 1; |
Tom Kacvinsky | 4082200 | 2000-10-17 20:25:30 +0000 | [diff] [blame] | 1725 | } |
| 1726 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1727 | return; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1728 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1729 | Fail: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1730 | parser->root.error = error; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1731 | } |
| 1732 | |
| 1733 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1734 | /*************************************************************************/ |
| 1735 | /* */ |
| 1736 | /* Define the token field static variables. This is a set of */ |
| 1737 | /* T1_FieldRec variables. */ |
| 1738 | /* */ |
| 1739 | /*************************************************************************/ |
| 1740 | |
| 1741 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1742 | static |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 1743 | const T1_FieldRec t1_keywords[] = |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1744 | { |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1745 | |
David Turner | 8d3a401 | 2001-03-20 11:14:24 +0000 | [diff] [blame] | 1746 | #include "t1tokens.h" |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 1747 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1748 | /* now add the special functions... */ |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1749 | T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix, |
| 1750 | T1_FIELD_DICT_FONTDICT ) |
| 1751 | T1_FIELD_CALLBACK( "Encoding", parse_encoding, |
| 1752 | T1_FIELD_DICT_FONTDICT ) |
| 1753 | T1_FIELD_CALLBACK( "Subrs", parse_subrs, |
| 1754 | T1_FIELD_DICT_PRIVATE ) |
| 1755 | T1_FIELD_CALLBACK( "CharStrings", parse_charstrings, |
| 1756 | T1_FIELD_DICT_PRIVATE ) |
| 1757 | T1_FIELD_CALLBACK( "Private", parse_private, |
| 1758 | T1_FIELD_DICT_FONTDICT ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1759 | |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 1760 | #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1761 | T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions, |
| 1762 | T1_FIELD_DICT_FONTDICT ) |
| 1763 | T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map, |
| 1764 | T1_FIELD_DICT_FONTDICT ) |
| 1765 | T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types, |
| 1766 | T1_FIELD_DICT_FONTDICT ) |
| 1767 | T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector, |
| 1768 | T1_FIELD_DICT_FONTDICT ) |
| 1769 | T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar, |
| 1770 | T1_FIELD_DICT_PRIVATE ) |
Werner Lemberg | b48a609 | 2000-07-09 19:15:30 +0000 | [diff] [blame] | 1771 | #endif |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1772 | |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1773 | { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1774 | }; |
| 1775 | |
| 1776 | |
Werner Lemberg | 64f1ba9 | 2003-07-25 22:09:53 +0000 | [diff] [blame] | 1777 | #define T1_FIELD_COUNT \ |
| 1778 | ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) ) |
| 1779 | |
| 1780 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1781 | static FT_Error |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1782 | parse_dict( T1_Face face, |
| 1783 | T1_Loader loader, |
| 1784 | FT_Byte* base, |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1785 | FT_Long size ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1786 | { |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 1787 | T1_Parser parser = &loader->parser; |
Werner Lemberg | d1d2b45 | 2004-02-16 09:38:05 +0000 | [diff] [blame] | 1788 | FT_Byte *limit, *start_binary = NULL; |
Werner Lemberg | 0a84eba | 2004-02-05 14:36:43 +0000 | [diff] [blame] | 1789 | FT_Bool have_integer = 0; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1790 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1791 | |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1792 | parser->root.cursor = base; |
| 1793 | parser->root.limit = base + size; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1794 | parser->root.error = T1_Err_Ok; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1795 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1796 | limit = parser->root.limit; |
| 1797 | |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1798 | T1_Skip_Spaces( parser ); |
| 1799 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1800 | while ( parser->root.cursor < limit ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1801 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1802 | FT_Byte* cur; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1803 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1804 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1805 | cur = parser->root.cursor; |
| 1806 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1807 | /* look for `eexec' */ |
| 1808 | if ( IS_PS_TOKEN( cur, limit, "eexec" ) ) |
Werner Lemberg | 63abb4b | 2003-12-22 11:35:36 +0000 | [diff] [blame] | 1809 | break; |
| 1810 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1811 | /* look for `closefile' which ends the eexec section */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1812 | else if ( IS_PS_TOKEN( cur, limit, "closefile" ) ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1813 | break; |
| 1814 | |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 1815 | /* in a synthetic font the base font starts after a */ |
| 1816 | /* `FontDictionary' token that is placed after a Private dict */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1817 | else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) ) |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 1818 | { |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1819 | if ( loader->keywords_encountered & T1_PRIVATE ) |
| 1820 | loader->keywords_encountered |= |
| 1821 | T1_FONTDIR_AFTER_PRIVATE; |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 1822 | parser->root.cursor += 13; |
| 1823 | } |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 1824 | |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1825 | /* check whether we have an integer */ |
| 1826 | else if ( ft_isdigit( *cur ) ) |
| 1827 | { |
| 1828 | start_binary = cur; |
| 1829 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1830 | if ( parser->root.error ) |
| 1831 | goto Exit; |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1832 | have_integer = 1; |
| 1833 | } |
| 1834 | |
| 1835 | /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ |
| 1836 | /* since those tokens are handled by parse_subrs and */ |
| 1837 | /* parse_charstrings */ |
| 1838 | else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && |
| 1839 | have_integer ) |
| 1840 | { |
| 1841 | FT_Long s; |
| 1842 | FT_Byte* b; |
| 1843 | |
| 1844 | |
| 1845 | parser->root.cursor = start_binary; |
| 1846 | if ( !read_binary_data( parser, &s, &b ) ) |
| 1847 | return T1_Err_Invalid_File_Format; |
| 1848 | have_integer = 0; |
| 1849 | } |
| 1850 | |
| 1851 | else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && |
| 1852 | have_integer ) |
| 1853 | { |
| 1854 | FT_Long s; |
| 1855 | FT_Byte* b; |
| 1856 | |
| 1857 | |
| 1858 | parser->root.cursor = start_binary; |
| 1859 | if ( !read_binary_data( parser, &s, &b ) ) |
| 1860 | return T1_Err_Invalid_File_Format; |
| 1861 | have_integer = 0; |
| 1862 | } |
| 1863 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1864 | /* look for immediates */ |
| 1865 | else if ( *cur == '/' && cur + 2 < limit ) |
| 1866 | { |
| 1867 | FT_PtrDist len; |
| 1868 | |
| 1869 | |
| 1870 | cur++; |
| 1871 | |
| 1872 | parser->root.cursor = cur; |
| 1873 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 1d565fb | 2005-02-13 21:42:42 +0000 | [diff] [blame] | 1874 | if ( parser->root.error ) |
| 1875 | goto Exit; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1876 | |
| 1877 | len = parser->root.cursor - cur; |
| 1878 | |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1879 | if ( len > 0 && len < 22 && parser->root.cursor < limit ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1880 | { |
| 1881 | /* now compare the immediate name to the keyword table */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1882 | T1_Field keyword = (T1_Field)t1_keywords; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1883 | |
| 1884 | |
| 1885 | for (;;) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1886 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1887 | FT_Byte* name; |
| 1888 | |
| 1889 | |
| 1890 | name = (FT_Byte*)keyword->ident; |
| 1891 | if ( !name ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1892 | break; |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1893 | |
Werner Lemberg | 023a4bf | 2004-10-14 11:33:04 +0000 | [diff] [blame] | 1894 | if ( cur[0] == name[0] && |
| 1895 | len == (FT_PtrDist)ft_strlen( (const char *)name ) && |
| 1896 | ft_memcmp( cur, name, len ) == 0 ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1897 | { |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1898 | /* We found it -- run the parsing callback! */ |
| 1899 | /* We record every instance of every field */ |
| 1900 | /* (until we reach the base font of a */ |
| 1901 | /* synthetic font) to deal adequately with */ |
| 1902 | /* multiple master fonts; this is also */ |
| 1903 | /* necessary because later PostScript */ |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1904 | /* definitions override earlier ones. */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1905 | |
| 1906 | /* Once we encounter `FontDirectory' after */ |
| 1907 | /* `/Private', we know that this is a synthetic */ |
| 1908 | /* font; except for `/CharStrings' we are not */ |
| 1909 | /* interested in anything that follows this */ |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1910 | /* `FontDirectory'. */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1911 | |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1912 | /* MM fonts have more than one /Private token at */ |
| 1913 | /* the top level; let's hope that all the junk */ |
| 1914 | /* that follows the first /Private token is not */ |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1915 | /* interesting to us. */ |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1916 | |
| 1917 | /* According to Adobe Tech Note #5175 (CID-Keyed */ |
| 1918 | /* Font Installation for ATM Software) a `begin' */ |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1919 | /* must be followed by exactly one `end', and */ |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1920 | /* `begin' -- `end' pairs must be accurately */ |
Werner Lemberg | 6e87ed9 | 2007-01-26 22:18:56 +0000 | [diff] [blame] | 1921 | /* paired. We could use this to distinguish */ |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1922 | /* between the global Private and the Private */ |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1923 | /* dict that is a member of the Blend dict. */ |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1924 | |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1925 | const FT_UInt dict = |
| 1926 | ( loader->keywords_encountered & T1_PRIVATE ) |
| 1927 | ? T1_FIELD_DICT_PRIVATE |
| 1928 | : T1_FIELD_DICT_FONTDICT; |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1929 | |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1930 | if ( !( dict & keyword->dict ) ) |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1931 | { |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1932 | FT_TRACE1(( "parse_dict: found %s but ignoring it " |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1933 | "since it is in the wrong dictionary\n", |
| 1934 | keyword->ident )); |
| 1935 | break; |
| 1936 | } |
| 1937 | |
Werner Lemberg | 1234299 | 2006-08-19 11:18:09 +0000 | [diff] [blame] | 1938 | if ( !( loader->keywords_encountered & |
| 1939 | T1_FONTDIR_AFTER_PRIVATE ) || |
Jens Claudius | 9950adc | 2006-08-13 12:14:36 +0000 | [diff] [blame] | 1940 | ft_strcmp( (const char*)name, "CharStrings" ) == 0 ) |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1941 | { |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1942 | parser->root.error = t1_load_keyword( face, |
| 1943 | loader, |
| 1944 | keyword ); |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1945 | if ( parser->root.error != T1_Err_Ok ) |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1946 | { |
Werner Lemberg | dfa4619 | 2004-03-05 09:26:24 +0000 | [diff] [blame] | 1947 | if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore ) |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1948 | parser->root.error = T1_Err_Ok; |
| 1949 | else |
| 1950 | return parser->root.error; |
| 1951 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1952 | } |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1953 | break; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1954 | } |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1955 | |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1956 | keyword++; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1957 | } |
| 1958 | } |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1959 | |
| 1960 | have_integer = 0; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1961 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1962 | else |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1963 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 1964 | T1_Skip_PS_Token( parser ); |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1965 | if ( parser->root.error ) |
| 1966 | goto Exit; |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 1967 | have_integer = 0; |
| 1968 | } |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1969 | |
| 1970 | T1_Skip_Spaces( parser ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1971 | } |
Werner Lemberg | 38c4647 | 2003-10-13 05:58:54 +0000 | [diff] [blame] | 1972 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 1973 | Exit: |
David Turner | a39acf5 | 2000-08-23 02:47:57 +0000 | [diff] [blame] | 1974 | return parser->root.error; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1975 | } |
| 1976 | |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1977 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1978 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 1979 | t1_init_loader( T1_Loader loader, |
| 1980 | T1_Face face ) |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1981 | { |
| 1982 | FT_UNUSED( face ); |
| 1983 | |
Werner Lemberg | b3d5e9c | 2002-07-28 05:05:24 +0000 | [diff] [blame] | 1984 | FT_MEM_ZERO( loader, sizeof ( *loader ) ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1985 | loader->num_glyphs = 0; |
| 1986 | loader->num_chars = 0; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 1987 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1988 | /* initialize the tables -- simply set their `init' field to 0 */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 1989 | loader->encoding_table.init = 0; |
| 1990 | loader->charstrings.init = 0; |
| 1991 | loader->glyph_names.init = 0; |
| 1992 | loader->subrs.init = 0; |
| 1993 | loader->swap_table.init = 0; |
| 1994 | loader->fontdata = 0; |
| 1995 | loader->keywords_encountered = 0; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 1996 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 1997 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 1998 | |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 1999 | static void |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 2000 | t1_done_loader( T1_Loader loader ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2001 | { |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 2002 | T1_Parser parser = &loader->parser; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2003 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2004 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2005 | /* finalize tables */ |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 2006 | T1_Release_Table( &loader->encoding_table ); |
| 2007 | T1_Release_Table( &loader->charstrings ); |
| 2008 | T1_Release_Table( &loader->glyph_names ); |
Tom Kacvinsky | cad797e | 2001-04-10 18:15:17 +0000 | [diff] [blame] | 2009 | T1_Release_Table( &loader->swap_table ); |
Werner Lemberg | b5084e1 | 2000-10-28 17:10:06 +0000 | [diff] [blame] | 2010 | T1_Release_Table( &loader->subrs ); |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2011 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2012 | /* finalize parser */ |
Werner Lemberg | 27695e5 | 2000-11-23 08:21:13 +0000 | [diff] [blame] | 2013 | T1_Finalize_Parser( parser ); |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2014 | } |
| 2015 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2016 | |
David Turner | bc82f1b | 2002-03-01 02:26:22 +0000 | [diff] [blame] | 2017 | FT_LOCAL_DEF( FT_Error ) |
Werner Lemberg | 4a2305c | 2001-06-28 07:17:51 +0000 | [diff] [blame] | 2018 | T1_Open_Face( T1_Face face ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2019 | { |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 2020 | T1_LoaderRec loader; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 2021 | T1_Parser parser; |
| 2022 | T1_Font type1 = &face->type1; |
Werner Lemberg | 675431b | 2004-02-25 21:17:49 +0000 | [diff] [blame] | 2023 | PS_Private priv = &type1->private_dict; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 2024 | FT_Error error; |
Werner Lemberg | e4b32a5 | 2000-10-31 20:42:18 +0000 | [diff] [blame] | 2025 | |
David Turner | 4e7eeee | 2002-02-28 16:10:29 +0000 | [diff] [blame] | 2026 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2027 | |
Werner Lemberg | 8728f29 | 2000-08-23 17:32:42 +0000 | [diff] [blame] | 2028 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2029 | t1_init_loader( &loader, face ); |
| 2030 | |
Werner Lemberg | 675431b | 2004-02-25 21:17:49 +0000 | [diff] [blame] | 2031 | /* default values */ |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 2032 | face->ndv_idx = -1; |
| 2033 | face->cdv_idx = -1; |
| 2034 | face->len_buildchar = 0; |
| 2035 | |
Werner Lemberg | 675431b | 2004-02-25 21:17:49 +0000 | [diff] [blame] | 2036 | priv->blue_shift = 7; |
| 2037 | priv->blue_fuzz = 1; |
| 2038 | priv->lenIV = 4; |
| 2039 | priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); |
| 2040 | priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); |
David Turner | 971517a | 2002-07-08 23:13:25 +0000 | [diff] [blame] | 2041 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2042 | parser = &loader.parser; |
Werner Lemberg | efa9961 | 2002-04-01 22:01:46 +0000 | [diff] [blame] | 2043 | error = T1_New_Parser( parser, |
| 2044 | face->root.stream, |
| 2045 | face->root.memory, |
| 2046 | psaux ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2047 | if ( error ) |
| 2048 | goto Exit; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2049 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 2050 | error = parse_dict( face, &loader, |
| 2051 | parser->base_dict, parser->base_len ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2052 | if ( error ) |
| 2053 | goto Exit; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2054 | |
Werner Lemberg | 27695e5 | 2000-11-23 08:21:13 +0000 | [diff] [blame] | 2055 | error = T1_Get_Private_Dict( parser, psaux ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2056 | if ( error ) |
| 2057 | goto Exit; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2058 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 2059 | error = parse_dict( face, &loader, |
| 2060 | parser->private_dict, parser->private_len ); |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2061 | if ( error ) |
| 2062 | goto Exit; |
Werner Lemberg | c011f4c | 2006-06-26 09:40:00 +0000 | [diff] [blame] | 2063 | |
Werner Lemberg | 422d2a0 | 2006-02-27 18:25:22 +0000 | [diff] [blame] | 2064 | /* ensure even-ness of `num_blue_values' */ |
David Turner | c13e75f | 2006-02-27 13:14:42 +0000 | [diff] [blame] | 2065 | priv->num_blue_values &= ~1; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2066 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 2067 | #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
| 2068 | |
Werner Lemberg | 1a380e0 | 2006-07-14 18:28:08 +0000 | [diff] [blame] | 2069 | if ( face->blend && |
| 2070 | face->blend->num_default_design_vector != 0 && |
| 2071 | face->blend->num_default_design_vector != face->blend->num_axis ) |
| 2072 | { |
| 2073 | /* we don't use it currently so just warn, reset, and ignore */ |
| 2074 | FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries " |
| 2075 | "while there are %u axes.\n", |
| 2076 | face->blend->num_default_design_vector, |
| 2077 | face->blend->num_axis )); |
| 2078 | |
| 2079 | face->blend->num_default_design_vector = 0; |
| 2080 | } |
| 2081 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 2082 | /* the following can happen for MM instances; we then treat the */ |
| 2083 | /* font as a normal PS font */ |
| 2084 | if ( face->blend && |
| 2085 | ( !face->blend->num_designs || !face->blend->num_axis ) ) |
| 2086 | T1_Done_Blend( face ); |
| 2087 | |
| 2088 | /* another safety check */ |
| 2089 | if ( face->blend ) |
| 2090 | { |
| 2091 | FT_UInt i; |
| 2092 | |
| 2093 | |
| 2094 | for ( i = 0; i < face->blend->num_axis; i++ ) |
| 2095 | if ( !face->blend->design_map[i].num_points ) |
| 2096 | { |
| 2097 | T1_Done_Blend( face ); |
| 2098 | break; |
| 2099 | } |
| 2100 | } |
| 2101 | |
Werner Lemberg | a4d6a1c | 2006-07-19 09:54:56 +0000 | [diff] [blame] | 2102 | if ( face->blend ) |
| 2103 | { |
| 2104 | if ( face->len_buildchar > 0 ) |
| 2105 | { |
| 2106 | FT_Memory memory = face->root.memory; |
| 2107 | |
| 2108 | |
| 2109 | if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) ) |
| 2110 | { |
| 2111 | FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" )); |
| 2112 | face->len_buildchar = 0; |
| 2113 | goto Exit; |
| 2114 | } |
| 2115 | } |
| 2116 | } |
| 2117 | |
Werner Lemberg | 9586707 | 2004-02-12 08:33:20 +0000 | [diff] [blame] | 2118 | #endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */ |
| 2119 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2120 | /* now, propagate the subrs, charstrings, and glyphnames tables */ |
| 2121 | /* to the Type1 data */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2122 | type1->num_glyphs = loader.num_glyphs; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2123 | |
Tom Kacvinsky | b2d5fef | 2001-01-24 22:41:20 +0000 | [diff] [blame] | 2124 | if ( loader.subrs.init ) |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 2125 | { |
Tom Kacvinsky | b2d5fef | 2001-01-24 22:41:20 +0000 | [diff] [blame] | 2126 | loader.subrs.init = 0; |
| 2127 | type1->num_subrs = loader.num_subrs; |
| 2128 | type1->subrs_block = loader.subrs.block; |
| 2129 | type1->subrs = loader.subrs.elements; |
| 2130 | type1->subrs_len = loader.subrs.lengths; |
David Turner | 95bec28 | 2000-02-15 12:55:57 +0000 | [diff] [blame] | 2131 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2132 | |
Graham Asher | 733c255 | 2002-08-01 16:16:16 +0000 | [diff] [blame] | 2133 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
Werner Lemberg | 3c403e4 | 2002-08-06 21:47:40 +0000 | [diff] [blame] | 2134 | if ( !face->root.internal->incremental_interface ) |
Graham Asher | 733c255 | 2002-08-01 16:16:16 +0000 | [diff] [blame] | 2135 | #endif |
| 2136 | if ( !loader.charstrings.init ) |
| 2137 | { |
Werner Lemberg | 6b3d00e | 2004-02-03 21:34:29 +0000 | [diff] [blame] | 2138 | FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face!\n" )); |
Graham Asher | 733c255 | 2002-08-01 16:16:16 +0000 | [diff] [blame] | 2139 | error = T1_Err_Invalid_File_Format; |
| 2140 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2141 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2142 | loader.charstrings.init = 0; |
| 2143 | type1->charstrings_block = loader.charstrings.block; |
| 2144 | type1->charstrings = loader.charstrings.elements; |
| 2145 | type1->charstrings_len = loader.charstrings.lengths; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2146 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2147 | /* we copy the glyph names `block' and `elements' fields; */ |
| 2148 | /* the `lengths' field must be released later */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2149 | type1->glyph_names_block = loader.glyph_names.block; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 2150 | type1->glyph_names = (FT_String**)loader.glyph_names.elements; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2151 | loader.glyph_names.block = 0; |
| 2152 | loader.glyph_names.elements = 0; |
| 2153 | |
Werner Lemberg | bd889e5 | 2002-05-12 19:59:17 +0000 | [diff] [blame] | 2154 | /* we must now build type1.encoding when we have a custom array */ |
David Turner | 2964417 | 2002-02-28 18:59:37 +0000 | [diff] [blame] | 2155 | if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2156 | { |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 2157 | FT_Int charcode, idx, min_char, max_char; |
David Turner | f9b8dec | 2000-06-16 19:34:52 +0000 | [diff] [blame] | 2158 | FT_Byte* char_name; |
| 2159 | FT_Byte* glyph_name; |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2160 | |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2161 | |
| 2162 | /* OK, we do the following: for each element in the encoding */ |
| 2163 | /* table, look up the index of the glyph having the same name */ |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2164 | /* the index is then stored in type1.encoding.char_index, and */ |
| 2165 | /* a the name to type1.encoding.char_name */ |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2166 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2167 | min_char = +32000; |
| 2168 | max_char = -32000; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2169 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2170 | charcode = 0; |
Tom Kacvinsky | 95ac657 | 2000-10-15 08:53:27 +0000 | [diff] [blame] | 2171 | for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2172 | { |
| 2173 | type1->encoding.char_index[charcode] = 0; |
Werner Lemberg | b1dd353 | 2000-07-31 22:51:00 +0000 | [diff] [blame] | 2174 | type1->encoding.char_name [charcode] = (char *)".notdef"; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2175 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2176 | char_name = loader.encoding_table.elements[charcode]; |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2177 | if ( char_name ) |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 2178 | for ( idx = 0; idx < type1->num_glyphs; idx++ ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2179 | { |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 2180 | glyph_name = (FT_Byte*)type1->glyph_names[idx]; |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 2181 | if ( ft_strcmp( (const char*)char_name, |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 2182 | (const char*)glyph_name ) == 0 ) |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2183 | { |
Werner Lemberg | 0d9165e | 2002-03-07 21:59:59 +0000 | [diff] [blame] | 2184 | type1->encoding.char_index[charcode] = (FT_UShort)idx; |
David Turner | 0dd3434 | 2000-02-02 12:20:53 +0000 | [diff] [blame] | 2185 | type1->encoding.char_name [charcode] = (char*)glyph_name; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2186 | |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 2187 | /* Change min/max encoded char only if glyph name is */ |
| 2188 | /* not /.notdef */ |
David Turner | d15bc0d | 2002-04-12 09:31:48 +0000 | [diff] [blame] | 2189 | if ( ft_strcmp( (const char*)".notdef", |
Werner Lemberg | 94ffae5 | 2002-04-14 00:54:32 +0000 | [diff] [blame] | 2190 | (const char*)glyph_name ) != 0 ) |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 2191 | { |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 2192 | if ( charcode < min_char ) |
| 2193 | min_char = charcode; |
| 2194 | if ( charcode > max_char ) |
| 2195 | max_char = charcode; |
Werner Lemberg | 05f0ad0 | 2000-10-19 05:12:00 +0000 | [diff] [blame] | 2196 | } |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2197 | break; |
| 2198 | } |
| 2199 | } |
| 2200 | } |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 2201 | |
| 2202 | /* |
| 2203 | * Yes, this happens: Certain PDF-embedded fonts have only a |
| 2204 | * `.notdef' glyph defined! |
Werner Lemberg | b442ca1 | 2003-04-23 15:50:27 +0000 | [diff] [blame] | 2205 | */ |
Werner Lemberg | 52f911a | 2003-10-07 05:49:41 +0000 | [diff] [blame] | 2206 | |
David Turner | e0ec6b3 | 2003-04-03 15:52:59 +0000 | [diff] [blame] | 2207 | if ( min_char > max_char ) |
| 2208 | { |
| 2209 | min_char = 0; |
| 2210 | max_char = loader.encoding_table.max_elems; |
| 2211 | } |
| 2212 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2213 | type1->encoding.code_first = min_char; |
| 2214 | type1->encoding.code_last = max_char; |
| 2215 | type1->encoding.num_chars = loader.num_chars; |
Werner Lemberg | 556ad08 | 2002-01-28 13:34:52 +0000 | [diff] [blame] | 2216 | } |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2217 | |
David Turner | 2dfb5ac | 2000-01-27 14:02:04 +0000 | [diff] [blame] | 2218 | Exit: |
| 2219 | t1_done_loader( &loader ); |
| 2220 | return error; |
David Turner | e49ab25 | 2000-05-16 23:44:38 +0000 | [diff] [blame] | 2221 | } |
Werner Lemberg | 681e8ee | 2000-07-09 00:48:37 +0000 | [diff] [blame] | 2222 | |
| 2223 | |
| 2224 | /* END */ |