1 /***************************************************************************/ 2 /* */ 3 /* ftgloadr.c */ 4 /* */ 5 /* The FreeType glyph loader (body). */ 6 /* */ 7 /* Copyright 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 FT_INTERNAL_GLYPH_LOADER_H 21 #include FT_INTERNAL_MEMORY_H 22 23 #undef FT_COMPONENT 24 #define FT_COMPONENT trace_gloader 25 26 27 /*************************************************************************/ 28 /*************************************************************************/ 29 /*************************************************************************/ 30 /***** *****/ 31 /***** *****/ 32 /***** G L Y P H L O A D E R *****/ 33 /***** *****/ 34 /***** *****/ 35 /*************************************************************************/ 36 /*************************************************************************/ 37 /*************************************************************************/ 38 39 /*************************************************************************/ 40 /* */ 41 /* The glyph loader is a simple object which is used to load a set of */ 42 /* glyphs easily. It is critical for the correct loading of composites. */ 43 /* */ 44 /* Ideally, one can see it as a stack of abstract `glyph' objects. */ 45 /* */ 46 /* loader.base Is really the bottom of the stack. It describes a */ 47 /* single glyph image made of the juxtaposition of */ 48 /* several glyphs (those `in the stack'). */ 49 /* */ 50 /* loader.current Describes the top of the stack, on which a new */ 51 /* glyph can be loaded. */ 52 /* */ 53 /* Rewind Clears the stack. */ 54 /* Prepare Set up `loader.current' for addition of a new glyph */ 55 /* image. */ 56 /* Add Add the `current' glyph image to the `base' one, */ 57 /* and prepare for another one. */ 58 /* */ 59 /* The glyph loader is now a base object. Each driver used to */ 60 /* re-implement it in one way or the other, which wasted code and */ 61 /* energy. */ 62 /* */ 63 /*************************************************************************/ 64 65 66 /* create a new glyph loader */ 67 FT_BASE_DEF( FT_Error ) 68 FT_GlyphLoader_New( FT_Memory memory, 69 FT_GlyphLoader *aloader ) 70 { 71 FT_GlyphLoader loader; 72 FT_Error error; 73 74 75 if ( !FT_NEW( loader ) ) 76 { 77 loader->memory = memory; 78 *aloader = loader; 79 } 80 return error; 81 } 82 83 84 /* rewind the glyph loader - reset counters to 0 */ 85 FT_BASE_DEF( void ) 86 FT_GlyphLoader_Rewind( FT_GlyphLoader loader ) 87 { 88 FT_GlyphLoad base = &loader->base; 89 FT_GlyphLoad current = &loader->current; 90 91 92 base->outline.n_points = 0; 93 base->outline.n_contours = 0; 94 base->num_subglyphs = 0; 95 96 *current = *base; 97 } 98 99 100 /* reset the glyph loader, frees all allocated tables */ 101 /* and starts from zero */ 102 FT_BASE_DEF( void ) 103 FT_GlyphLoader_Reset( FT_GlyphLoader loader ) 104 { 105 FT_Memory memory = loader->memory; 106 107 108 FT_FREE( loader->base.outline.points ); 109 FT_FREE( loader->base.outline.tags ); 110 FT_FREE( loader->base.outline.contours ); 111 FT_FREE( loader->base.extra_points ); 112 FT_FREE( loader->base.subglyphs ); 113 114 loader->max_points = 0; 115 loader->max_contours = 0; 116 loader->max_subglyphs = 0; 117 118 FT_GlyphLoader_Rewind( loader ); 119 } 120 121 122 /* delete a glyph loader */ 123 FT_BASE_DEF( void ) 124 FT_GlyphLoader_Done( FT_GlyphLoader loader ) 125 { 126 if ( loader ) 127 { 128 FT_Memory memory = loader->memory; 129 130 131 FT_GlyphLoader_Reset( loader ); 132 FT_FREE( loader ); 133 } 134 } 135 136 137 /* re-adjust the `current' outline fields */ 138 static void 139 FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader ) 140 { 141 FT_Outline* base = &loader->base.outline; 142 FT_Outline* current = &loader->current.outline; 143 144 145 current->points = base->points + base->n_points; 146 current->tags = base->tags + base->n_points; 147 current->contours = base->contours + base->n_contours; 148 149 /* handle extra points table - if any */ 150 if ( loader->use_extra ) 151 loader->current.extra_points = 152 loader->base.extra_points + base->n_points; 153 } 154 155 156 FT_BASE_DEF( FT_Error ) 157 FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ) 158 { 159 FT_Error error; 160 FT_Memory memory = loader->memory; 161 162 163 if ( !FT_NEW_ARRAY( loader->base.extra_points, loader->max_points ) ) 164 { 165 loader->use_extra = 1; 166 FT_GlyphLoader_Adjust_Points( loader ); 167 } 168 return error; 169 } 170 171 172 /* re-adjust the `current' subglyphs field */ 173 static void 174 FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader ) 175 { 176 FT_GlyphLoad base = &loader->base; 177 FT_GlyphLoad current = &loader->current; 178 179 180 current->subglyphs = base->subglyphs + base->num_subglyphs; 181 } 182 183 184 /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */ 185 /* function reallocates its outline tables if necessary. Note that it */ 186 /* DOESN'T change the number of points within the loader! */ 187 /* */ 188 FT_BASE_DEF( FT_Error ) 189 FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, 190 FT_UInt n_points, 191 FT_UInt n_contours ) 192 { 193 FT_Memory memory = loader->memory; 194 FT_Error error = FT_Err_Ok; 195 FT_Outline* base = &loader->base.outline; 196 FT_Outline* current = &loader->current.outline; 197 FT_Bool adjust = 1; 198 199 FT_UInt new_max, old_max; 200 201 202 /* check points & tags */ 203 new_max = base->n_points + current->n_points + n_points; 204 old_max = loader->max_points; 205 206 if ( new_max > old_max ) 207 { 208 new_max = ( new_max + 7 ) & -8; 209 210 if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || 211 FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) 212 goto Exit; 213 214 if ( loader->use_extra && 215 FT_RENEW_ARRAY( loader->base.extra_points, old_max, new_max ) ) 216 goto Exit; 217 218 adjust = 1; 219 loader->max_points = new_max; 220 } 221 222 /* check contours */ 223 old_max = loader->max_contours; 224 new_max = base->n_contours + current->n_contours + 225 n_contours; 226 if ( new_max > old_max ) 227 { 228 new_max = ( new_max + 3 ) & -4; 229 if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) 230 goto Exit; 231 232 adjust = 1; 233 loader->max_contours = new_max; 234 } 235 236 if ( adjust ) 237 FT_GlyphLoader_Adjust_Points( loader ); 238 239 Exit: 240 return error; 241 } 242 243 244 /* Ensure that we can add `n_subglyphs' to our glyph. this function */ 245 /* reallocates its subglyphs table if necessary. Note that it DOES */ 246 /* NOT change the number of subglyphs within the loader! */ 247 /* */ 248 FT_BASE_DEF( FT_Error ) 249 FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, 250 FT_UInt n_subs ) 251 { 252 FT_Memory memory = loader->memory; 253 FT_Error error = FT_Err_Ok; 254 FT_UInt new_max, old_max; 255 256 FT_GlyphLoad base = &loader->base; 257 FT_GlyphLoad current = &loader->current; 258 259 260 new_max = base->num_subglyphs + current->num_subglyphs + n_subs; 261 old_max = loader->max_subglyphs; 262 if ( new_max > old_max ) 263 { 264 new_max = ( new_max + 1 ) & -2; 265 if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) ) 266 goto Exit; 267 268 loader->max_subglyphs = new_max; 269 270 FT_GlyphLoader_Adjust_Subglyphs( loader ); 271 } 272 273 Exit: 274 return error; 275 } 276 277 278 /* prepare loader for the addition of a new glyph on top of the base one */ 279 FT_BASE_DEF( void ) 280 FT_GlyphLoader_Prepare( FT_GlyphLoader loader ) 281 { 282 FT_GlyphLoad current = &loader->current; 283 284 285 current->outline.n_points = 0; 286 current->outline.n_contours = 0; 287 current->num_subglyphs = 0; 288 289 FT_GlyphLoader_Adjust_Points ( loader ); 290 FT_GlyphLoader_Adjust_Subglyphs( loader ); 291 } 292 293 294 /* add current glyph to the base image - and prepare for another */ 295 FT_BASE_DEF( void ) 296 FT_GlyphLoader_Add( FT_GlyphLoader loader ) 297 { 298 FT_GlyphLoad base = &loader->base; 299 FT_GlyphLoad current = &loader->current; 300 301 FT_UInt n_curr_contours = current->outline.n_contours; 302 FT_UInt n_base_points = base->outline.n_points; 303 FT_UInt n; 304 305 306 base->outline.n_points = 307 (short)( base->outline.n_points + current->outline.n_points ); 308 base->outline.n_contours = 309 (short)( base->outline.n_contours + current->outline.n_contours ); 310 311 base->num_subglyphs += current->num_subglyphs; 312 313 /* adjust contours count in newest outline */ 314 for ( n = 0; n < n_curr_contours; n++ ) 315 current->outline.contours[n] = 316 (short)( current->outline.contours[n] + n_base_points ); 317 318 /* prepare for another new glyph image */ 319 FT_GlyphLoader_Prepare( loader ); 320 } 321 322 323 FT_BASE_DEF( FT_Error ) 324 FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, 325 FT_GlyphLoader source ) 326 { 327 FT_Error error; 328 FT_UInt num_points = source->base.outline.n_points; 329 FT_UInt num_contours = source->base.outline.n_contours; 330 331 332 error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours ); 333 if ( !error ) 334 { 335 FT_Outline* out = &target->base.outline; 336 FT_Outline* in = &source->base.outline; 337 338 339 FT_MEM_COPY( out->points, in->points, 340 num_points * sizeof ( FT_Vector ) ); 341 FT_MEM_COPY( out->tags, in->tags, 342 num_points * sizeof ( char ) ); 343 FT_MEM_COPY( out->contours, in->contours, 344 num_contours * sizeof ( short ) ); 345 346 /* do we need to copy the extra points? */ 347 if ( target->use_extra && source->use_extra ) 348 FT_MEM_COPY( target->base.extra_points, source->base.extra_points, 349 num_points * sizeof ( FT_Vector ) ); 350 351 out->n_points = (short)num_points; 352 out->n_contours = (short)num_contours; 353 354 FT_GlyphLoader_Adjust_Points( target ); 355 } 356 357 return error; 358 } 359 360 361 /* END */ 362