ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cidload.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  cidload.c                                                              */
00004 /*                                                                         */
00005 /*    CID-keyed Type1 font loader (body).                                  */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2009 by             */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021 #include FT_CONFIG_CONFIG_H
00022 #include FT_MULTIPLE_MASTERS_H
00023 #include FT_INTERNAL_TYPE1_TYPES_H
00024 
00025 #include "cidload.h"
00026 
00027 #include "ciderrs.h"
00028 
00029 
00030   /*************************************************************************/
00031   /*                                                                       */
00032   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00033   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00034   /* messages during execution.                                            */
00035   /*                                                                       */
00036 #undef  FT_COMPONENT
00037 #define FT_COMPONENT  trace_cidload
00038 
00039 
00040   /* read a single offset */
00041   FT_LOCAL_DEF( FT_Long )
00042   cid_get_offset( FT_Byte*  *start,
00043                   FT_Byte    offsize )
00044   {
00045     FT_Long   result;
00046     FT_Byte*  p = *start;
00047 
00048 
00049     for ( result = 0; offsize > 0; offsize-- )
00050     {
00051       result <<= 8;
00052       result  |= *p++;
00053     }
00054 
00055     *start = p;
00056     return result;
00057   }
00058 
00059 
00060   /*************************************************************************/
00061   /*************************************************************************/
00062   /*****                                                               *****/
00063   /*****                    TYPE 1 SYMBOL PARSING                      *****/
00064   /*****                                                               *****/
00065   /*************************************************************************/
00066   /*************************************************************************/
00067 
00068 
00069   static FT_Error
00070   cid_load_keyword( CID_Face        face,
00071                     CID_Loader*     loader,
00072                     const T1_Field  keyword )
00073   {
00074     FT_Error      error;
00075     CID_Parser*   parser = &loader->parser;
00076     FT_Byte*      object;
00077     void*         dummy_object;
00078     CID_FaceInfo  cid = &face->cid;
00079 
00080 
00081     /* if the keyword has a dedicated callback, call it */
00082     if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
00083     {
00084       keyword->reader( (FT_Face)face, parser );
00085       error = parser->root.error;
00086       goto Exit;
00087     }
00088 
00089     /* we must now compute the address of our target object */
00090     switch ( keyword->location )
00091     {
00092     case T1_FIELD_LOCATION_CID_INFO:
00093       object = (FT_Byte*)cid;
00094       break;
00095 
00096     case T1_FIELD_LOCATION_FONT_INFO:
00097       object = (FT_Byte*)&cid->font_info;
00098       break;
00099 
00100     case T1_FIELD_LOCATION_FONT_EXTRA:
00101       object = (FT_Byte*)&face->font_extra;
00102       break;
00103 
00104     case T1_FIELD_LOCATION_BBOX:
00105       object = (FT_Byte*)&cid->font_bbox;
00106       break;
00107 
00108     default:
00109       {
00110         CID_FaceDict  dict;
00111 
00112 
00113         if ( parser->num_dict < 0 )
00114         {
00115           FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n",
00116                      keyword->ident ));
00117           error = CID_Err_Syntax_Error;
00118           goto Exit;
00119         }
00120 
00121         dict = cid->font_dicts + parser->num_dict;
00122         switch ( keyword->location )
00123         {
00124         case T1_FIELD_LOCATION_PRIVATE:
00125           object = (FT_Byte*)&dict->private_dict;
00126           break;
00127 
00128         default:
00129           object = (FT_Byte*)dict;
00130         }
00131       }
00132     }
00133 
00134     dummy_object = object;
00135 
00136     /* now, load the keyword data in the object's field(s) */
00137     if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
00138          keyword->type == T1_FIELD_TYPE_FIXED_ARRAY   )
00139       error = cid_parser_load_field_table( &loader->parser, keyword,
00140                                            &dummy_object );
00141     else
00142       error = cid_parser_load_field( &loader->parser,
00143                                      keyword, &dummy_object );
00144   Exit:
00145     return error;
00146   }
00147 
00148 
00149   FT_CALLBACK_DEF( FT_Error )
00150   parse_font_matrix( CID_Face     face,
00151                      CID_Parser*  parser )
00152   {
00153     FT_Matrix*    matrix;
00154     FT_Vector*    offset;
00155     CID_FaceDict  dict;
00156     FT_Face       root = (FT_Face)&face->root;
00157     FT_Fixed      temp[6];
00158     FT_Fixed      temp_scale;
00159 
00160 
00161     if ( parser->num_dict >= 0 )
00162     {
00163       dict   = face->cid.font_dicts + parser->num_dict;
00164       matrix = &dict->font_matrix;
00165       offset = &dict->font_offset;
00166 
00167       (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );
00168 
00169       temp_scale = FT_ABS( temp[3] );
00170 
00171       /* Set units per EM based on FontMatrix values.  We set the value to */
00172       /* `1000/temp_scale', because temp_scale was already multiplied by   */
00173       /* 1000 (in `t1_tofixed', from psobjs.c).                            */
00174       root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
00175                                         FT_DivFix( temp_scale, 1000 ) ) );
00176 
00177       /* we need to scale the values by 1.0/temp[3] */
00178       if ( temp_scale != 0x10000L )
00179       {
00180         temp[0] = FT_DivFix( temp[0], temp_scale );
00181         temp[1] = FT_DivFix( temp[1], temp_scale );
00182         temp[2] = FT_DivFix( temp[2], temp_scale );
00183         temp[4] = FT_DivFix( temp[4], temp_scale );
00184         temp[5] = FT_DivFix( temp[5], temp_scale );
00185         temp[3] = 0x10000L;
00186       }
00187 
00188       matrix->xx = temp[0];
00189       matrix->yx = temp[1];
00190       matrix->xy = temp[2];
00191       matrix->yy = temp[3];
00192 
00193       /* note that the font offsets are expressed in integer font units */
00194       offset->x  = temp[4] >> 16;
00195       offset->y  = temp[5] >> 16;
00196     }
00197 
00198     return CID_Err_Ok;      /* this is a callback function; */
00199                             /* we must return an error code */
00200   }
00201 
00202 
00203   FT_CALLBACK_DEF( FT_Error )
00204   parse_fd_array( CID_Face     face,
00205                   CID_Parser*  parser )
00206   {
00207     CID_FaceInfo  cid    = &face->cid;
00208     FT_Memory     memory = face->root.memory;
00209     FT_Error      error  = CID_Err_Ok;
00210     FT_Long       num_dicts;
00211 
00212 
00213     num_dicts = cid_parser_to_int( parser );
00214 
00215     if ( !cid->font_dicts )
00216     {
00217       FT_Int  n;
00218 
00219 
00220       if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
00221         goto Exit;
00222 
00223       cid->num_dicts = (FT_UInt)num_dicts;
00224 
00225       /* don't forget to set a few defaults */
00226       for ( n = 0; n < cid->num_dicts; n++ )
00227       {
00228         CID_FaceDict  dict = cid->font_dicts + n;
00229 
00230 
00231         /* default value for lenIV */
00232         dict->private_dict.lenIV = 4;
00233       }
00234     }
00235 
00236   Exit:
00237     return error;
00238   }
00239 
00240 
00241   /* by mistake, `expansion_factor' appears both in PS_PrivateRec */
00242   /* and CID_FaceDictRec (both are public header files and can't  */
00243   /* changed); we simply copy the value                           */
00244 
00245   FT_CALLBACK_DEF( FT_Error )
00246   parse_expansion_factor( CID_Face     face,
00247                           CID_Parser*  parser )
00248   {
00249     CID_FaceDict  dict;
00250 
00251 
00252     if ( parser->num_dict >= 0 )
00253     {
00254       dict = face->cid.font_dicts + parser->num_dict;
00255 
00256       dict->expansion_factor              = cid_parser_to_fixed( parser, 0 );
00257       dict->private_dict.expansion_factor = dict->expansion_factor;
00258     }
00259 
00260     return CID_Err_Ok;
00261   }
00262 
00263 
00264   static
00265   const T1_FieldRec  cid_field_records[] =
00266   {
00267 
00268 #include "cidtoken.h"
00269 
00270     T1_FIELD_CALLBACK( "FDArray",         parse_fd_array, 0 )
00271     T1_FIELD_CALLBACK( "FontMatrix",      parse_font_matrix, 0 )
00272     T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
00273 
00274     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
00275   };
00276 
00277 
00278   static FT_Error
00279   cid_parse_dict( CID_Face     face,
00280                   CID_Loader*  loader,
00281                   FT_Byte*     base,
00282                   FT_Long      size )
00283   {
00284     CID_Parser*  parser = &loader->parser;
00285 
00286 
00287     parser->root.cursor = base;
00288     parser->root.limit  = base + size;
00289     parser->root.error  = CID_Err_Ok;
00290 
00291     {
00292       FT_Byte*  cur   = base;
00293       FT_Byte*  limit = cur + size;
00294 
00295 
00296       for (;;)
00297       {
00298         FT_Byte*  newlimit;
00299 
00300 
00301         parser->root.cursor = cur;
00302         cid_parser_skip_spaces( parser );
00303 
00304         if ( parser->root.cursor >= limit )
00305           newlimit = limit - 1 - 17;
00306         else
00307           newlimit = parser->root.cursor - 17;
00308 
00309         /* look for `%ADOBeginFontDict' */
00310         for ( ; cur < newlimit; cur++ )
00311         {
00312           if ( *cur == '%'                                            &&
00313                ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
00314           {
00315             /* if /FDArray was found, then cid->num_dicts is > 0, and */
00316             /* we can start increasing parser->num_dict               */
00317             if ( face->cid.num_dicts > 0 )
00318               parser->num_dict++;
00319           }
00320         }
00321 
00322         cur = parser->root.cursor;
00323         /* no error can occur in cid_parser_skip_spaces */
00324         if ( cur >= limit )
00325           break;
00326 
00327         cid_parser_skip_PS_token( parser );
00328         if ( parser->root.cursor >= limit || parser->root.error )
00329           break;
00330 
00331         /* look for immediates */
00332         if ( *cur == '/' && cur + 2 < limit )
00333         {
00334           FT_PtrDist  len;
00335 
00336 
00337           cur++;
00338           len = parser->root.cursor - cur;
00339 
00340           if ( len > 0 && len < 22 )
00341           {
00342             /* now compare the immediate name to the keyword table */
00343             T1_Field  keyword = (T1_Field)cid_field_records;
00344 
00345 
00346             for (;;)
00347             {
00348               FT_Byte*  name;
00349 
00350 
00351               name = (FT_Byte*)keyword->ident;
00352               if ( !name )
00353                 break;
00354 
00355               if ( cur[0] == name[0]                                 &&
00356                    len == (FT_PtrDist)ft_strlen( (const char*)name ) )
00357               {
00358                 FT_PtrDist  n;
00359 
00360 
00361                 for ( n = 1; n < len; n++ )
00362                   if ( cur[n] != name[n] )
00363                     break;
00364 
00365                 if ( n >= len )
00366                 {
00367                   /* we found it - run the parsing callback */
00368                   parser->root.error = cid_load_keyword( face,
00369                                                          loader,
00370                                                          keyword );
00371                   if ( parser->root.error )
00372                     return parser->root.error;
00373                   break;
00374                 }
00375               }
00376               keyword++;
00377             }
00378           }
00379         }
00380 
00381         cur = parser->root.cursor;
00382       }
00383     }
00384     return parser->root.error;
00385   }
00386 
00387 
00388   /* read the subrmap and the subrs of each font dict */
00389   static FT_Error
00390   cid_read_subrs( CID_Face  face )
00391   {
00392     CID_FaceInfo   cid    = &face->cid;
00393     FT_Memory      memory = face->root.memory;
00394     FT_Stream      stream = face->cid_stream;
00395     FT_Error       error;
00396     FT_Int         n;
00397     CID_Subrs      subr;
00398     FT_UInt        max_offsets = 0;
00399     FT_ULong*      offsets = 0;
00400     PSAux_Service  psaux = (PSAux_Service)face->psaux;
00401 
00402 
00403     if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
00404       goto Exit;
00405 
00406     subr = face->subrs;
00407     for ( n = 0; n < cid->num_dicts; n++, subr++ )
00408     {
00409       CID_FaceDict  dict  = cid->font_dicts + n;
00410       FT_Int        lenIV = dict->private_dict.lenIV;
00411       FT_UInt       count, num_subrs = dict->num_subrs;
00412       FT_ULong      data_len;
00413       FT_Byte*      p;
00414 
00415 
00416       /* reallocate offsets array if needed */
00417       if ( num_subrs + 1 > max_offsets )
00418       {
00419         FT_UInt  new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
00420 
00421 
00422         if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
00423           goto Fail;
00424 
00425         max_offsets = new_max;
00426       }
00427 
00428       /* read the subrmap's offsets */
00429       if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
00430            FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes )      )
00431         goto Fail;
00432 
00433       p = (FT_Byte*)stream->cursor;
00434       for ( count = 0; count <= num_subrs; count++ )
00435         offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
00436 
00437       FT_FRAME_EXIT();
00438 
00439       /* now, compute the size of subrs charstrings, */
00440       /* allocate, and read them                     */
00441       data_len = offsets[num_subrs] - offsets[0];
00442 
00443       if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
00444                FT_ALLOC( subr->code[0], data_len )   )
00445         goto Fail;
00446 
00447       if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
00448            FT_STREAM_READ( subr->code[0], data_len )  )
00449         goto Fail;
00450 
00451       /* set up pointers */
00452       for ( count = 1; count <= num_subrs; count++ )
00453       {
00454         FT_ULong  len;
00455 
00456 
00457         len               = offsets[count] - offsets[count - 1];
00458         subr->code[count] = subr->code[count - 1] + len;
00459       }
00460 
00461       /* decrypt subroutines, but only if lenIV >= 0 */
00462       if ( lenIV >= 0 )
00463       {
00464         for ( count = 0; count < num_subrs; count++ )
00465         {
00466           FT_ULong  len;
00467 
00468 
00469           len = offsets[count + 1] - offsets[count];
00470           psaux->t1_decrypt( subr->code[count], len, 4330 );
00471         }
00472       }
00473 
00474       subr->num_subrs = num_subrs;
00475     }
00476 
00477   Exit:
00478     FT_FREE( offsets );
00479     return error;
00480 
00481   Fail:
00482     if ( face->subrs )
00483     {
00484       for ( n = 0; n < cid->num_dicts; n++ )
00485       {
00486         if ( face->subrs[n].code )
00487           FT_FREE( face->subrs[n].code[0] );
00488 
00489         FT_FREE( face->subrs[n].code );
00490       }
00491       FT_FREE( face->subrs );
00492     }
00493     goto Exit;
00494   }
00495 
00496 
00497   static void
00498   t1_init_loader( CID_Loader*  loader,
00499                   CID_Face     face )
00500   {
00501     FT_UNUSED( face );
00502 
00503     FT_MEM_ZERO( loader, sizeof ( *loader ) );
00504   }
00505 
00506 
00507   static void
00508   t1_done_loader( CID_Loader*  loader )
00509   {
00510     CID_Parser*  parser = &loader->parser;
00511 
00512 
00513     /* finalize parser */
00514     cid_parser_done( parser );
00515   }
00516 
00517 
00518   static FT_Error
00519   cid_hex_to_binary( FT_Byte*  data,
00520                      FT_Long   data_len,
00521                      FT_ULong  offset,
00522                      CID_Face  face )
00523   {
00524     FT_Stream  stream = face->root.stream;
00525     FT_Error   error;
00526 
00527     FT_Byte    buffer[256];
00528     FT_Byte   *p, *plimit;
00529     FT_Byte   *d, *dlimit;
00530     FT_Byte    val;
00531 
00532     FT_Bool    upper_nibble, done;
00533 
00534 
00535     if ( FT_STREAM_SEEK( offset ) )
00536       goto Exit;
00537 
00538     d      = data;
00539     dlimit = d + data_len;
00540     p      = buffer;
00541     plimit = p;
00542 
00543     upper_nibble = 1;
00544     done         = 0;
00545 
00546     while ( d < dlimit )
00547     {
00548       if ( p >= plimit )
00549       {
00550         FT_ULong  oldpos = FT_STREAM_POS();
00551         FT_ULong  size   = stream->size - oldpos;
00552 
00553 
00554         if ( size == 0 )
00555         {
00556           error = CID_Err_Syntax_Error;
00557           goto Exit;
00558         }
00559 
00560         if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
00561           goto Exit;
00562         p      = buffer;
00563         plimit = p + FT_STREAM_POS() - oldpos;
00564       }
00565 
00566       if ( ft_isdigit( *p ) )
00567         val = (FT_Byte)( *p - '0' );
00568       else if ( *p >= 'a' && *p <= 'f' )
00569         val = (FT_Byte)( *p - 'a' );
00570       else if ( *p >= 'A' && *p <= 'F' )
00571         val = (FT_Byte)( *p - 'A' + 10 );
00572       else if ( *p == ' '  ||
00573                 *p == '\t' ||
00574                 *p == '\r' ||
00575                 *p == '\n' ||
00576                 *p == '\f' ||
00577                 *p == '\0' )
00578       {
00579         p++;
00580         continue;
00581       }
00582       else if ( *p == '>' )
00583       {
00584         val  = 0;
00585         done = 1;
00586       }
00587       else
00588       {
00589         error = CID_Err_Syntax_Error;
00590         goto Exit;
00591       }
00592 
00593       if ( upper_nibble )
00594         *d = (FT_Byte)( val << 4 );
00595       else
00596       {
00597         *d = (FT_Byte)( *d + val );
00598         d++;
00599       }
00600 
00601       upper_nibble = (FT_Byte)( 1 - upper_nibble );
00602 
00603       if ( done )
00604         break;
00605 
00606       p++;
00607     }
00608 
00609     error = CID_Err_Ok;
00610 
00611   Exit:
00612     return error;
00613   }
00614 
00615 
00616   FT_LOCAL_DEF( FT_Error )
00617   cid_face_open( CID_Face  face,
00618                  FT_Int    face_index )
00619   {
00620     CID_Loader   loader;
00621     CID_Parser*  parser;
00622     FT_Memory    memory = face->root.memory;
00623     FT_Error     error;
00624 
00625 
00626     t1_init_loader( &loader, face );
00627 
00628     parser = &loader.parser;
00629     error = cid_parser_new( parser, face->root.stream, face->root.memory,
00630                             (PSAux_Service)face->psaux );
00631     if ( error )
00632       goto Exit;
00633 
00634     error = cid_parse_dict( face, &loader,
00635                             parser->postscript,
00636                             parser->postscript_len );
00637     if ( error )
00638       goto Exit;
00639 
00640     if ( face_index < 0 )
00641       goto Exit;
00642 
00643     if ( FT_NEW( face->cid_stream ) )
00644       goto Exit;
00645 
00646     if ( parser->binary_length )
00647     {
00648       /* we must convert the data section from hexadecimal to binary */
00649       if ( FT_ALLOC( face->binary_data, parser->binary_length )         ||
00650            cid_hex_to_binary( face->binary_data, parser->binary_length,
00651                               parser->data_offset, face )               )
00652         goto Exit;
00653 
00654       FT_Stream_OpenMemory( face->cid_stream,
00655                             face->binary_data, parser->binary_length );
00656       face->cid.data_offset = 0;
00657     }
00658     else
00659     {
00660       *face->cid_stream     = *face->root.stream;
00661       face->cid.data_offset = loader.parser.data_offset;
00662     }
00663 
00664     error = cid_read_subrs( face );
00665 
00666   Exit:
00667     t1_done_loader( &loader );
00668     return error;
00669   }
00670 
00671 
00672 /* END */

Generated on Sat May 26 2012 04:32:41 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.