Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  cidload.c                                                              */
  4. /*                                                                         */
  5. /*    CID-keyed Type1 font loader (body).                                  */
  6. /*                                                                         */
  7. /*  Copyright 1996-2006, 2009, 2011-2013 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_DEBUG_H
  21. #include FT_CONFIG_CONFIG_H
  22. #include FT_MULTIPLE_MASTERS_H
  23. #include FT_INTERNAL_TYPE1_TYPES_H
  24.  
  25. #include "cidload.h"
  26.  
  27. #include "ciderrs.h"
  28.  
  29.  
  30.   /*************************************************************************/
  31.   /*                                                                       */
  32.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  33.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  34.   /* messages during execution.                                            */
  35.   /*                                                                       */
  36. #undef  FT_COMPONENT
  37. #define FT_COMPONENT  trace_cidload
  38.  
  39.  
  40.   /* read a single offset */
  41.   FT_LOCAL_DEF( FT_Long )
  42.   cid_get_offset( FT_Byte*  *start,
  43.                   FT_Byte    offsize )
  44.   {
  45.     FT_ULong  result;
  46.     FT_Byte*  p = *start;
  47.  
  48.  
  49.     for ( result = 0; offsize > 0; offsize-- )
  50.     {
  51.       result <<= 8;
  52.       result  |= *p++;
  53.     }
  54.  
  55.     *start = p;
  56.     return (FT_Long)result;
  57.   }
  58.  
  59.  
  60.   /*************************************************************************/
  61.   /*************************************************************************/
  62.   /*****                                                               *****/
  63.   /*****                    TYPE 1 SYMBOL PARSING                      *****/
  64.   /*****                                                               *****/
  65.   /*************************************************************************/
  66.   /*************************************************************************/
  67.  
  68.  
  69.   static FT_Error
  70.   cid_load_keyword( CID_Face        face,
  71.                     CID_Loader*     loader,
  72.                     const T1_Field  keyword )
  73.   {
  74.     FT_Error      error;
  75.     CID_Parser*   parser = &loader->parser;
  76.     FT_Byte*      object;
  77.     void*         dummy_object;
  78.     CID_FaceInfo  cid = &face->cid;
  79.  
  80.  
  81.     /* if the keyword has a dedicated callback, call it */
  82.     if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
  83.     {
  84.       keyword->reader( (FT_Face)face, parser );
  85.       error = parser->root.error;
  86.       goto Exit;
  87.     }
  88.  
  89.     /* we must now compute the address of our target object */
  90.     switch ( keyword->location )
  91.     {
  92.     case T1_FIELD_LOCATION_CID_INFO:
  93.       object = (FT_Byte*)cid;
  94.       break;
  95.  
  96.     case T1_FIELD_LOCATION_FONT_INFO:
  97.       object = (FT_Byte*)&cid->font_info;
  98.       break;
  99.  
  100.     case T1_FIELD_LOCATION_FONT_EXTRA:
  101.       object = (FT_Byte*)&face->font_extra;
  102.       break;
  103.  
  104.     case T1_FIELD_LOCATION_BBOX:
  105.       object = (FT_Byte*)&cid->font_bbox;
  106.       break;
  107.  
  108.     default:
  109.       {
  110.         CID_FaceDict  dict;
  111.  
  112.  
  113.         if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts )
  114.         {
  115.           FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n",
  116.                      keyword->ident ));
  117.           error = FT_THROW( Syntax_Error );
  118.           goto Exit;
  119.         }
  120.  
  121.         dict = cid->font_dicts + parser->num_dict;
  122.         switch ( keyword->location )
  123.         {
  124.         case T1_FIELD_LOCATION_PRIVATE:
  125.           object = (FT_Byte*)&dict->private_dict;
  126.           break;
  127.  
  128.         default:
  129.           object = (FT_Byte*)dict;
  130.         }
  131.       }
  132.     }
  133.  
  134.     dummy_object = object;
  135.  
  136.     /* now, load the keyword data in the object's field(s) */
  137.     if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
  138.          keyword->type == T1_FIELD_TYPE_FIXED_ARRAY   )
  139.       error = cid_parser_load_field_table( &loader->parser, keyword,
  140.                                            &dummy_object );
  141.     else
  142.       error = cid_parser_load_field( &loader->parser,
  143.                                      keyword, &dummy_object );
  144.   Exit:
  145.     return error;
  146.   }
  147.  
  148.  
  149.   FT_CALLBACK_DEF( FT_Error )
  150.   cid_parse_font_matrix( CID_Face     face,
  151.                          CID_Parser*  parser )
  152.   {
  153.     FT_Matrix*    matrix;
  154.     FT_Vector*    offset;
  155.     CID_FaceDict  dict;
  156.     FT_Face       root = (FT_Face)&face->root;
  157.     FT_Fixed      temp[6];
  158.     FT_Fixed      temp_scale;
  159.  
  160.  
  161.     if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
  162.     {
  163.       dict   = face->cid.font_dicts + parser->num_dict;
  164.       matrix = &dict->font_matrix;
  165.       offset = &dict->font_offset;
  166.  
  167.       (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );
  168.  
  169.       temp_scale = FT_ABS( temp[3] );
  170.  
  171.       /* Set Units per EM based on FontMatrix values.  We set the value to */
  172.       /* 1000 / temp_scale, because temp_scale was already multiplied by   */
  173.       /* 1000 (in t1_tofixed, from psobjs.c).                              */
  174.  
  175.       root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
  176.  
  177.       /* we need to scale the values by 1.0/temp[3] */
  178.       if ( temp_scale != 0x10000L )
  179.       {
  180.         temp[0] = FT_DivFix( temp[0], temp_scale );
  181.         temp[1] = FT_DivFix( temp[1], temp_scale );
  182.         temp[2] = FT_DivFix( temp[2], temp_scale );
  183.         temp[4] = FT_DivFix( temp[4], temp_scale );
  184.         temp[5] = FT_DivFix( temp[5], temp_scale );
  185.         temp[3] = 0x10000L;
  186.       }
  187.  
  188.       matrix->xx = temp[0];
  189.       matrix->yx = temp[1];
  190.       matrix->xy = temp[2];
  191.       matrix->yy = temp[3];
  192.  
  193.       /* note that the font offsets are expressed in integer font units */
  194.       offset->x  = temp[4] >> 16;
  195.       offset->y  = temp[5] >> 16;
  196.     }
  197.  
  198.     return FT_Err_Ok;      /* this is a callback function; */
  199.                             /* we must return an error code */
  200.   }
  201.  
  202.  
  203.   FT_CALLBACK_DEF( FT_Error )
  204.   parse_fd_array( CID_Face     face,
  205.                   CID_Parser*  parser )
  206.   {
  207.     CID_FaceInfo  cid    = &face->cid;
  208.     FT_Memory     memory = face->root.memory;
  209.     FT_Error      error  = FT_Err_Ok;
  210.     FT_Long       num_dicts;
  211.  
  212.  
  213.     num_dicts = cid_parser_to_int( parser );
  214.  
  215.     if ( !cid->font_dicts )
  216.     {
  217.       FT_Int  n;
  218.  
  219.  
  220.       if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
  221.         goto Exit;
  222.  
  223.       cid->num_dicts = (FT_UInt)num_dicts;
  224.  
  225.       /* don't forget to set a few defaults */
  226.       for ( n = 0; n < cid->num_dicts; n++ )
  227.       {
  228.         CID_FaceDict  dict = cid->font_dicts + n;
  229.  
  230.  
  231.         /* default value for lenIV */
  232.         dict->private_dict.lenIV = 4;
  233.       }
  234.     }
  235.  
  236.   Exit:
  237.     return error;
  238.   }
  239.  
  240.  
  241.   /* by mistake, `expansion_factor' appears both in PS_PrivateRec */
  242.   /* and CID_FaceDictRec (both are public header files and can't  */
  243.   /* changed); we simply copy the value                           */
  244.  
  245.   FT_CALLBACK_DEF( FT_Error )
  246.   parse_expansion_factor( CID_Face     face,
  247.                           CID_Parser*  parser )
  248.   {
  249.     CID_FaceDict  dict;
  250.  
  251.  
  252.     if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
  253.     {
  254.       dict = face->cid.font_dicts + parser->num_dict;
  255.  
  256.       dict->expansion_factor              = cid_parser_to_fixed( parser, 0 );
  257.       dict->private_dict.expansion_factor = dict->expansion_factor;
  258.     }
  259.  
  260.     return FT_Err_Ok;
  261.   }
  262.  
  263.  
  264.   static
  265.   const T1_FieldRec  cid_field_records[] =
  266.   {
  267.  
  268. #include "cidtoken.h"
  269.  
  270.     T1_FIELD_CALLBACK( "FDArray",         parse_fd_array, 0 )
  271.     T1_FIELD_CALLBACK( "FontMatrix",      cid_parse_font_matrix, 0 )
  272.     T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
  273.  
  274.     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
  275.   };
  276.  
  277.  
  278.   static FT_Error
  279.   cid_parse_dict( CID_Face     face,
  280.                   CID_Loader*  loader,
  281.                   FT_Byte*     base,
  282.                   FT_Long      size )
  283.   {
  284.     CID_Parser*  parser = &loader->parser;
  285.  
  286.  
  287.     parser->root.cursor = base;
  288.     parser->root.limit  = base + size;
  289.     parser->root.error  = FT_Err_Ok;
  290.  
  291.     {
  292.       FT_Byte*  cur   = base;
  293.       FT_Byte*  limit = cur + size;
  294.  
  295.  
  296.       for (;;)
  297.       {
  298.         FT_Byte*  newlimit;
  299.  
  300.  
  301.         parser->root.cursor = cur;
  302.         cid_parser_skip_spaces( parser );
  303.  
  304.         if ( parser->root.cursor >= limit )
  305.           newlimit = limit - 1 - 17;
  306.         else
  307.           newlimit = parser->root.cursor - 17;
  308.  
  309.         /* look for `%ADOBeginFontDict' */
  310.         for ( ; cur < newlimit; cur++ )
  311.         {
  312.           if ( *cur == '%'                                            &&
  313.                ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
  314.           {
  315.             /* if /FDArray was found, then cid->num_dicts is > 0, and */
  316.             /* we can start increasing parser->num_dict               */
  317.             if ( face->cid.num_dicts > 0 )
  318.               parser->num_dict++;
  319.           }
  320.         }
  321.  
  322.         cur = parser->root.cursor;
  323.         /* no error can occur in cid_parser_skip_spaces */
  324.         if ( cur >= limit )
  325.           break;
  326.  
  327.         cid_parser_skip_PS_token( parser );
  328.         if ( parser->root.cursor >= limit || parser->root.error )
  329.           break;
  330.  
  331.         /* look for immediates */
  332.         if ( *cur == '/' && cur + 2 < limit )
  333.         {
  334.           FT_PtrDist  len;
  335.  
  336.  
  337.           cur++;
  338.           len = parser->root.cursor - cur;
  339.  
  340.           if ( len > 0 && len < 22 )
  341.           {
  342.             /* now compare the immediate name to the keyword table */
  343.             T1_Field  keyword = (T1_Field)cid_field_records;
  344.  
  345.  
  346.             for (;;)
  347.             {
  348.               FT_Byte*  name;
  349.  
  350.  
  351.               name = (FT_Byte*)keyword->ident;
  352.               if ( !name )
  353.                 break;
  354.  
  355.               if ( cur[0] == name[0]                                 &&
  356.                    len == (FT_PtrDist)ft_strlen( (const char*)name ) )
  357.               {
  358.                 FT_PtrDist  n;
  359.  
  360.  
  361.                 for ( n = 1; n < len; n++ )
  362.                   if ( cur[n] != name[n] )
  363.                     break;
  364.  
  365.                 if ( n >= len )
  366.                 {
  367.                   /* we found it - run the parsing callback */
  368.                   parser->root.error = cid_load_keyword( face,
  369.                                                          loader,
  370.                                                          keyword );
  371.                   if ( parser->root.error )
  372.                     return parser->root.error;
  373.                   break;
  374.                 }
  375.               }
  376.               keyword++;
  377.             }
  378.           }
  379.         }
  380.  
  381.         cur = parser->root.cursor;
  382.       }
  383.     }
  384.     return parser->root.error;
  385.   }
  386.  
  387.  
  388.   /* read the subrmap and the subrs of each font dict */
  389.   static FT_Error
  390.   cid_read_subrs( CID_Face  face )
  391.   {
  392.     CID_FaceInfo   cid    = &face->cid;
  393.     FT_Memory      memory = face->root.memory;
  394.     FT_Stream      stream = face->cid_stream;
  395.     FT_Error       error;
  396.     FT_Int         n;
  397.     CID_Subrs      subr;
  398.     FT_UInt        max_offsets = 0;
  399.     FT_ULong*      offsets = 0;
  400.     PSAux_Service  psaux = (PSAux_Service)face->psaux;
  401.  
  402.  
  403.     if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
  404.       goto Exit;
  405.  
  406.     subr = face->subrs;
  407.     for ( n = 0; n < cid->num_dicts; n++, subr++ )
  408.     {
  409.       CID_FaceDict  dict  = cid->font_dicts + n;
  410.       FT_Int        lenIV = dict->private_dict.lenIV;
  411.       FT_UInt       count, num_subrs = dict->num_subrs;
  412.       FT_ULong      data_len;
  413.       FT_Byte*      p;
  414.  
  415.  
  416.       /* Check for possible overflow. */
  417.       if ( num_subrs == FT_UINT_MAX )
  418.       {
  419.         error = FT_THROW( Syntax_Error );
  420.         goto Fail;
  421.       }
  422.  
  423.       /* reallocate offsets array if needed */
  424.       if ( num_subrs + 1 > max_offsets )
  425.       {
  426.         FT_UInt  new_max = FT_PAD_CEIL( num_subrs + 1, 4 );
  427.  
  428.  
  429.         if ( new_max <= max_offsets )
  430.         {
  431.           error = FT_THROW( Syntax_Error );
  432.           goto Fail;
  433.         }
  434.  
  435.         if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
  436.           goto Fail;
  437.  
  438.         max_offsets = new_max;
  439.       }
  440.  
  441.       /* read the subrmap's offsets */
  442.       if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
  443.            FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes )      )
  444.         goto Fail;
  445.  
  446.       p = (FT_Byte*)stream->cursor;
  447.       for ( count = 0; count <= num_subrs; count++ )
  448.         offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
  449.  
  450.       FT_FRAME_EXIT();
  451.  
  452.       /* offsets must be ordered */
  453.       for ( count = 1; count <= num_subrs; count++ )
  454.         if ( offsets[count - 1] > offsets[count] )
  455.           goto Fail;
  456.  
  457.       /* now, compute the size of subrs charstrings, */
  458.       /* allocate, and read them                     */
  459.       data_len = offsets[num_subrs] - offsets[0];
  460.  
  461.       if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
  462.                FT_ALLOC( subr->code[0], data_len )   )
  463.         goto Fail;
  464.  
  465.       if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
  466.            FT_STREAM_READ( subr->code[0], data_len )  )
  467.         goto Fail;
  468.  
  469.       /* set up pointers */
  470.       for ( count = 1; count <= num_subrs; count++ )
  471.       {
  472.         FT_ULong  len;
  473.  
  474.  
  475.         len               = offsets[count] - offsets[count - 1];
  476.         subr->code[count] = subr->code[count - 1] + len;
  477.       }
  478.  
  479.       /* decrypt subroutines, but only if lenIV >= 0 */
  480.       if ( lenIV >= 0 )
  481.       {
  482.         for ( count = 0; count < num_subrs; count++ )
  483.         {
  484.           FT_ULong  len;
  485.  
  486.  
  487.           len = offsets[count + 1] - offsets[count];
  488.           psaux->t1_decrypt( subr->code[count], len, 4330 );
  489.         }
  490.       }
  491.  
  492.       subr->num_subrs = num_subrs;
  493.     }
  494.  
  495.   Exit:
  496.     FT_FREE( offsets );
  497.     return error;
  498.  
  499.   Fail:
  500.     if ( face->subrs )
  501.     {
  502.       for ( n = 0; n < cid->num_dicts; n++ )
  503.       {
  504.         if ( face->subrs[n].code )
  505.           FT_FREE( face->subrs[n].code[0] );
  506.  
  507.         FT_FREE( face->subrs[n].code );
  508.       }
  509.       FT_FREE( face->subrs );
  510.     }
  511.     goto Exit;
  512.   }
  513.  
  514.  
  515.   static void
  516.   cid_init_loader( CID_Loader*  loader,
  517.                    CID_Face     face )
  518.   {
  519.     FT_UNUSED( face );
  520.  
  521.     FT_MEM_ZERO( loader, sizeof ( *loader ) );
  522.   }
  523.  
  524.  
  525.   static  void
  526.   cid_done_loader( CID_Loader*  loader )
  527.   {
  528.     CID_Parser*  parser = &loader->parser;
  529.  
  530.  
  531.     /* finalize parser */
  532.     cid_parser_done( parser );
  533.   }
  534.  
  535.  
  536.   static FT_Error
  537.   cid_hex_to_binary( FT_Byte*  data,
  538.                      FT_Long   data_len,
  539.                      FT_ULong  offset,
  540.                      CID_Face  face )
  541.   {
  542.     FT_Stream  stream = face->root.stream;
  543.     FT_Error   error;
  544.  
  545.     FT_Byte    buffer[256];
  546.     FT_Byte   *p, *plimit;
  547.     FT_Byte   *d, *dlimit;
  548.     FT_Byte    val;
  549.  
  550.     FT_Bool    upper_nibble, done;
  551.  
  552.  
  553.     if ( FT_STREAM_SEEK( offset ) )
  554.       goto Exit;
  555.  
  556.     d      = data;
  557.     dlimit = d + data_len;
  558.     p      = buffer;
  559.     plimit = p;
  560.  
  561.     upper_nibble = 1;
  562.     done         = 0;
  563.  
  564.     while ( d < dlimit )
  565.     {
  566.       if ( p >= plimit )
  567.       {
  568.         FT_ULong  oldpos = FT_STREAM_POS();
  569.         FT_ULong  size   = stream->size - oldpos;
  570.  
  571.  
  572.         if ( size == 0 )
  573.         {
  574.           error = FT_THROW( Syntax_Error );
  575.           goto Exit;
  576.         }
  577.  
  578.         if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) )
  579.           goto Exit;
  580.         p      = buffer;
  581.         plimit = p + FT_STREAM_POS() - oldpos;
  582.       }
  583.  
  584.       if ( ft_isdigit( *p ) )
  585.         val = (FT_Byte)( *p - '0' );
  586.       else if ( *p >= 'a' && *p <= 'f' )
  587.         val = (FT_Byte)( *p - 'a' );
  588.       else if ( *p >= 'A' && *p <= 'F' )
  589.         val = (FT_Byte)( *p - 'A' + 10 );
  590.       else if ( *p == ' '  ||
  591.                 *p == '\t' ||
  592.                 *p == '\r' ||
  593.                 *p == '\n' ||
  594.                 *p == '\f' ||
  595.                 *p == '\0' )
  596.       {
  597.         p++;
  598.         continue;
  599.       }
  600.       else if ( *p == '>' )
  601.       {
  602.         val  = 0;
  603.         done = 1;
  604.       }
  605.       else
  606.       {
  607.         error = FT_THROW( Syntax_Error );
  608.         goto Exit;
  609.       }
  610.  
  611.       if ( upper_nibble )
  612.         *d = (FT_Byte)( val << 4 );
  613.       else
  614.       {
  615.         *d = (FT_Byte)( *d + val );
  616.         d++;
  617.       }
  618.  
  619.       upper_nibble = (FT_Byte)( 1 - upper_nibble );
  620.  
  621.       if ( done )
  622.         break;
  623.  
  624.       p++;
  625.     }
  626.  
  627.     error = FT_Err_Ok;
  628.  
  629.   Exit:
  630.     return error;
  631.   }
  632.  
  633.  
  634.   FT_LOCAL_DEF( FT_Error )
  635.   cid_face_open( CID_Face  face,
  636.                  FT_Int    face_index )
  637.   {
  638.     CID_Loader   loader;
  639.     CID_Parser*  parser;
  640.     FT_Memory    memory = face->root.memory;
  641.     FT_Error     error;
  642.  
  643.  
  644.     cid_init_loader( &loader, face );
  645.  
  646.     parser = &loader.parser;
  647.     error = cid_parser_new( parser, face->root.stream, face->root.memory,
  648.                             (PSAux_Service)face->psaux );
  649.     if ( error )
  650.       goto Exit;
  651.  
  652.     error = cid_parse_dict( face, &loader,
  653.                             parser->postscript,
  654.                             parser->postscript_len );
  655.     if ( error )
  656.       goto Exit;
  657.  
  658.     if ( face_index < 0 )
  659.       goto Exit;
  660.  
  661.     if ( FT_NEW( face->cid_stream ) )
  662.       goto Exit;
  663.  
  664.     if ( parser->binary_length )
  665.     {
  666.       /* we must convert the data section from hexadecimal to binary */
  667.       if ( FT_ALLOC( face->binary_data, parser->binary_length )         ||
  668.            cid_hex_to_binary( face->binary_data, parser->binary_length,
  669.                               parser->data_offset, face )               )
  670.         goto Exit;
  671.  
  672.       FT_Stream_OpenMemory( face->cid_stream,
  673.                             face->binary_data, parser->binary_length );
  674.       face->cid.data_offset = 0;
  675.     }
  676.     else
  677.     {
  678.       *face->cid_stream     = *face->root.stream;
  679.       face->cid.data_offset = loader.parser.data_offset;
  680.     }
  681.  
  682.     error = cid_read_subrs( face );
  683.  
  684.   Exit:
  685.     cid_done_loader( &loader );
  686.     return error;
  687.   }
  688.  
  689.  
  690. /* END */
  691.