1 /***************************************************************************/ 2 /* */ 3 /* t1gload.c */ 4 /* */ 5 /* Type 1 Glyph Loader (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002 by */ 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 #include <ft2build.h> 20 #include "t1gload.h" 21 #include FT_INTERNAL_DEBUG_H 22 #include FT_INTERNAL_STREAM_H 23 #include FT_OUTLINE_H 24 #include FT_INTERNAL_POSTSCRIPT_AUX_H 25 26 #include "t1errors.h" 27 28 29 /*************************************************************************/ 30 /* */ 31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 33 /* messages during execution. */ 34 /* */ 35 #undef FT_COMPONENT 36 #define FT_COMPONENT trace_t1gload 37 38 39 /*************************************************************************/ 40 /*************************************************************************/ 41 /*************************************************************************/ 42 /********** *********/ 43 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 44 /********** *********/ 45 /********** The following code is in charge of computing *********/ 46 /********** the maximum advance width of the font. It *********/ 47 /********** quickly processes each glyph charstring to *********/ 48 /********** extract the value from either a `sbw' or `seac' *********/ 49 /********** operator. *********/ 50 /********** *********/ 51 /*************************************************************************/ 52 /*************************************************************************/ 53 /*************************************************************************/ 54 55 56 FT_LOCAL_DEF( FT_Error ) T1_Parse_Glyph_And_Get_Char_String(T1_Decoder decoder,FT_UInt glyph_index,FT_Data * char_string)57 T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, 58 FT_UInt glyph_index, 59 FT_Data* char_string ) 60 { 61 T1_Face face = (T1_Face)decoder->builder.face; 62 T1_Font type1 = &face->type1; 63 FT_Error error = 0; 64 65 66 decoder->font_matrix = type1->font_matrix; 67 decoder->font_offset = type1->font_offset; 68 69 #ifdef FT_CONFIG_OPTION_INCREMENTAL 70 71 /* For incremental fonts get the character data using the */ 72 /* callback function. */ 73 if ( face->root.internal->incremental_interface ) 74 error = face->root.internal->incremental_interface->funcs->get_glyph_data( 75 face->root.internal->incremental_interface->object, 76 glyph_index, char_string ); 77 else 78 79 #endif 80 81 /* For ordinary fonts get the character data stored in the face record. */ 82 { 83 char_string->pointer = type1->charstrings[glyph_index]; 84 char_string->length = type1->charstrings_len[glyph_index]; 85 } 86 87 if ( !error ) 88 error = decoder->funcs.parse_charstrings( 89 decoder, (FT_Byte*)char_string->pointer, 90 char_string->length ); 91 92 #ifdef FT_CONFIG_OPTION_INCREMENTAL 93 94 /* Incremental fonts can optionally override the metrics. */ 95 if ( !error && face->root.internal->incremental_interface && 96 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 97 { 98 FT_Bool found = FALSE; 99 FT_Incremental_MetricsRec metrics; 100 101 102 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 103 face->root.internal->incremental_interface->object, 104 glyph_index, FALSE, &metrics, &found ); 105 if ( found ) 106 { 107 decoder->builder.left_bearing.x = metrics.bearing_x; 108 decoder->builder.left_bearing.y = metrics.bearing_y; 109 decoder->builder.advance.x = metrics.advance; 110 decoder->builder.advance.y = 0; 111 } 112 } 113 114 #endif 115 116 return error; 117 } 118 119 120 FT_CALLBACK_DEF( FT_Error ) T1_Parse_Glyph(T1_Decoder decoder,FT_UInt glyph_index)121 T1_Parse_Glyph( T1_Decoder decoder, 122 FT_UInt glyph_index ) 123 { 124 FT_Data glyph_data; 125 FT_Error error = T1_Parse_Glyph_And_Get_Char_String( 126 decoder, glyph_index, &glyph_data ); 127 128 129 #ifdef FT_CONFIG_OPTION_INCREMENTAL 130 if ( !error ) 131 { 132 T1_Face face = (T1_Face)decoder->builder.face; 133 134 135 if ( face->root.internal->incremental_interface ) 136 face->root.internal->incremental_interface->funcs->free_glyph_data( 137 face->root.internal->incremental_interface->object, 138 &glyph_data ); 139 } 140 #endif 141 142 return error; 143 } 144 145 146 FT_LOCAL_DEF( FT_Error ) T1_Compute_Max_Advance(T1_Face face,FT_Int * max_advance)147 T1_Compute_Max_Advance( T1_Face face, 148 FT_Int* max_advance ) 149 { 150 FT_Error error; 151 T1_DecoderRec decoder; 152 FT_Int glyph_index; 153 T1_Font type1 = &face->type1; 154 PSAux_Service psaux = (PSAux_Service)face->psaux; 155 156 157 *max_advance = 0; 158 159 /* initialize load decoder */ 160 error = psaux->t1_decoder_funcs->init( &decoder, 161 (FT_Face)face, 162 0, /* size */ 163 0, /* glyph slot */ 164 (FT_Byte**)type1->glyph_names, 165 face->blend, 166 0, 167 FT_RENDER_MODE_NORMAL, 168 T1_Parse_Glyph ); 169 if ( error ) 170 return error; 171 172 decoder.builder.metrics_only = 1; 173 decoder.builder.load_points = 0; 174 175 decoder.num_subrs = type1->num_subrs; 176 decoder.subrs = type1->subrs; 177 decoder.subrs_len = type1->subrs_len; 178 179 *max_advance = 0; 180 181 /* for each glyph, parse the glyph charstring and extract */ 182 /* the advance width */ 183 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) 184 { 185 /* now get load the unscaled outline */ 186 error = T1_Parse_Glyph( &decoder, glyph_index ); 187 if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance ) 188 *max_advance = decoder.builder.advance.x; 189 190 /* ignore the error if one occured - skip to next glyph */ 191 } 192 193 return T1_Err_Ok; 194 } 195 196 197 /*************************************************************************/ 198 /*************************************************************************/ 199 /*************************************************************************/ 200 /********** *********/ 201 /********** UNHINTED GLYPH LOADER *********/ 202 /********** *********/ 203 /********** The following code is in charge of loading a *********/ 204 /********** single outline. It completely ignores hinting *********/ 205 /********** and is used when FT_LOAD_NO_HINTING is set. *********/ 206 /********** *********/ 207 /********** The Type 1 hinter is located in `t1hint.c' *********/ 208 /********** *********/ 209 /*************************************************************************/ 210 /*************************************************************************/ 211 /*************************************************************************/ 212 213 214 FT_LOCAL_DEF( FT_Error ) T1_Load_Glyph(T1_GlyphSlot glyph,T1_Size size,FT_UInt glyph_index,FT_Int32 load_flags)215 T1_Load_Glyph( T1_GlyphSlot glyph, 216 T1_Size size, 217 FT_UInt glyph_index, 218 FT_Int32 load_flags ) 219 { 220 FT_Error error; 221 T1_DecoderRec decoder; 222 T1_Face face = (T1_Face)glyph->root.face; 223 FT_Bool hinting; 224 T1_Font type1 = &face->type1; 225 PSAux_Service psaux = (PSAux_Service)face->psaux; 226 const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; 227 228 FT_Matrix font_matrix; 229 FT_Vector font_offset; 230 FT_Data glyph_data; 231 FT_Bool glyph_data_loaded = 0; 232 233 234 if ( load_flags & FT_LOAD_NO_RECURSE ) 235 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 236 237 glyph->x_scale = size->root.metrics.x_scale; 238 glyph->y_scale = size->root.metrics.y_scale; 239 240 glyph->root.outline.n_points = 0; 241 glyph->root.outline.n_contours = 0; 242 243 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && 244 ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 245 246 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; 247 248 error = decoder_funcs->init( &decoder, 249 (FT_Face)face, 250 (FT_Size)size, 251 (FT_GlyphSlot)glyph, 252 (FT_Byte**)type1->glyph_names, 253 face->blend, 254 FT_BOOL( hinting ), 255 FT_LOAD_TARGET_MODE(load_flags), 256 T1_Parse_Glyph ); 257 if ( error ) 258 goto Exit; 259 260 decoder.builder.no_recurse = FT_BOOL( 261 ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); 262 263 decoder.num_subrs = type1->num_subrs; 264 decoder.subrs = type1->subrs; 265 decoder.subrs_len = type1->subrs_len; 266 267 /* now load the unscaled outline */ 268 error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, 269 &glyph_data ); 270 if ( error ) 271 goto Exit; 272 glyph_data_loaded = 1; 273 274 font_matrix = decoder.font_matrix; 275 font_offset = decoder.font_offset; 276 277 /* save new glyph tables */ 278 decoder_funcs->done( &decoder ); 279 280 /* now, set the metrics -- this is rather simple, as */ 281 /* the left side bearing is the xMin, and the top side */ 282 /* bearing the yMax */ 283 if ( !error ) 284 { 285 glyph->root.outline.flags &= FT_OUTLINE_OWNER; 286 glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; 287 288 /* for composite glyphs, return only left side bearing and */ 289 /* advance width */ 290 if ( load_flags & FT_LOAD_NO_RECURSE ) 291 { 292 FT_Slot_Internal internal = glyph->root.internal; 293 294 295 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; 296 glyph->root.metrics.horiAdvance = decoder.builder.advance.x; 297 internal->glyph_matrix = font_matrix; 298 internal->glyph_delta = font_offset; 299 internal->glyph_transformed = 1; 300 } 301 else 302 { 303 FT_BBox cbox; 304 FT_Glyph_Metrics* metrics = &glyph->root.metrics; 305 306 307 /* copy the _unscaled_ advance width */ 308 metrics->horiAdvance = decoder.builder.advance.x; 309 glyph->root.linearHoriAdvance = decoder.builder.advance.x; 310 glyph->root.internal->glyph_transformed = 0; 311 312 /* make up vertical metrics */ 313 metrics->vertBearingX = 0; 314 metrics->vertBearingY = 0; 315 metrics->vertAdvance = 0; 316 317 glyph->root.linearVertAdvance = 0; 318 319 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; 320 321 if ( size && size->root.metrics.y_ppem < 24 ) 322 glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; 323 324 #if 1 325 /* apply the font matrix, if any */ 326 FT_Outline_Transform( &glyph->root.outline, &font_matrix ); 327 328 FT_Outline_Translate( &glyph->root.outline, 329 font_offset.x, 330 font_offset.y ); 331 #endif 332 333 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) 334 { 335 /* scale the outline and the metrics */ 336 FT_Int n; 337 FT_Outline* cur = decoder.builder.base; 338 FT_Vector* vec = cur->points; 339 FT_Fixed x_scale = glyph->x_scale; 340 FT_Fixed y_scale = glyph->y_scale; 341 342 343 /* First of all, scale the points, if we are not hinting */ 344 if ( !hinting ) 345 for ( n = cur->n_points; n > 0; n--, vec++ ) 346 { 347 vec->x = FT_MulFix( vec->x, x_scale ); 348 vec->y = FT_MulFix( vec->y, y_scale ); 349 } 350 351 FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 352 353 /* Then scale the metrics */ 354 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 355 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 356 357 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); 358 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); 359 360 if ( hinting ) 361 { 362 metrics->horiAdvance = ( metrics->horiAdvance + 32 ) & -64; 363 metrics->vertAdvance = ( metrics->vertAdvance + 32 ) & -64; 364 365 metrics->vertBearingX = ( metrics->vertBearingX + 32 ) & -64; 366 metrics->vertBearingY = ( metrics->vertBearingY + 32 ) & -64; 367 } 368 } 369 370 /* compute the other metrics */ 371 FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 372 373 /* grid fit the bounding box if necessary */ 374 if ( hinting ) 375 { 376 cbox.xMin &= -64; 377 cbox.yMin &= -64; 378 cbox.xMax = ( cbox.xMax+63 ) & -64; 379 cbox.yMax = ( cbox.yMax+63 ) & -64; 380 } 381 382 metrics->width = cbox.xMax - cbox.xMin; 383 metrics->height = cbox.yMax - cbox.yMin; 384 385 metrics->horiBearingX = cbox.xMin; 386 metrics->horiBearingY = cbox.yMax; 387 } 388 389 /* Set control data to the glyph charstrings. Note that this is */ 390 /* _not_ zero-terminated. */ 391 glyph->root.control_data = (FT_Byte*)glyph_data.pointer; 392 glyph->root.control_len = glyph_data.length; 393 } 394 395 396 Exit: 397 398 #ifdef FT_CONFIG_OPTION_INCREMENTAL 399 if ( glyph_data_loaded && face->root.internal->incremental_interface ) 400 { 401 face->root.internal->incremental_interface->funcs->free_glyph_data( 402 face->root.internal->incremental_interface->object, 403 &glyph_data ); 404 405 /* Set the control data to null - it is no longer available if */ 406 /* loaded incrementally. */ 407 glyph->root.control_data = 0; 408 glyph->root.control_len = 0; 409 } 410 #endif 411 412 return error; 413 } 414 415 416 /* END */ 417