Example #1
0
  /* read an offset from the index's stream current position */
  static FT_ULong
  cff_index_read_offset( CFF_Index  idx,
                         FT_Error  *errorp )
  {
    FT_Error   error;
    FT_Stream  stream = idx->stream;
    FT_Byte    tmp[4];
    FT_ULong   result = 0;


    if ( !FT_STREAM_READ( tmp, idx->off_size ) )
    {
      FT_Int  nn;


      for ( nn = 0; nn < idx->off_size; nn++ )
        result = ( result << 8 ) | tmp[nn];
    }

    *errorp = error;
    return result;
  }
Example #2
0
  /* check and skip .bz2 header - we don't support `transparent' compression */
  static FT_Error
  ft_bzip2_check_header( FT_Stream  stream )
  {
    FT_Error  error = FT_Err_Ok;
    FT_Byte   head[4];


    if ( FT_STREAM_SEEK( 0 )       ||
         FT_STREAM_READ( head, 4 ) )
      goto Exit;

    /* head[0] && head[1] are the magic numbers;    */
    /* head[2] is the version, and head[3] the blocksize */
    if ( head[0] != 0x42  ||
         head[1] != 0x5a  ||
         head[2] != 0x68  )  /* only support bzip2 (huffman) */
    {
      error = FT_THROW( Invalid_File_Format );
      goto Exit;
    }

  Exit:
    return error;
  }
Example #3
0
static FT_Error
tt_face_get_name(TT_Face face,
                 FT_UShort nameid,
                 FT_String **name)
{
    FT_Memory       memory  = face->root.memory;
    FT_Error        error   = SFNT_Err_Ok;
    FT_String       *result = NULL;
    FT_UShort       n;
    TT_NameEntryRec *rec;
    FT_Int          found_apple         = -1;
    FT_Int          found_apple_roman   = -1;
    FT_Int          found_apple_english = -1;
    FT_Int          found_win           = -1;
    FT_Int          found_unicode       = -1;

    FT_Bool is_english = 0;

    TT_NameEntry_ConvertFunc convert;


    FT_ASSERT(name);

    rec = face->name_table.names;

    for (n = 0; n < face->num_names; n++, rec++)
    {
        /* According to the OpenType 1.3 specification, only Microsoft or  */
        /* Apple platform IDs might be used in the `name' table.  The      */
        /* `Unicode' platform is reserved for the `cmap' table, and the    */
        /* `ISO' one is deprecated.                                        */
        /*                                                                 */
        /* However, the Apple TrueType specification doesn't say the same  */
        /* thing and goes to suggest that all Unicode `name' table entries */
        /* should be coded in UTF-16 (in big-endian format I suppose).     */
        /*                                                                 */
        if (rec->nameID == nameid && rec->stringLength > 0)
        {
            switch (rec->platformID)
            {
            case TT_PLATFORM_APPLE_UNICODE:
            case TT_PLATFORM_ISO:
                /* there is `languageID' to check there.  We should use this */
                /* field only as a last solution when nothing else is        */
                /* available.                                                */
                /*                                                           */
                found_unicode = n;
                break;

            case TT_PLATFORM_MACINTOSH:
                /* This is a bit special because some fonts will use either    */
                /* an English language id, or a Roman encoding id, to indicate */
                /* the English version of its font name.                       */
                /*                                                             */
                if (rec->languageID == TT_MAC_LANGID_ENGLISH)
                    found_apple_english = n;
                else if (rec->encodingID == TT_MAC_ID_ROMAN)
                    found_apple_roman = n;

                break;

            case TT_PLATFORM_MICROSOFT:
                /* we only take a non-English name when there is nothing */
                /* else available in the font                            */
                /*                                                       */
                if (found_win == -1 || (rec->languageID & 0x3FF) == 0x009)
                {
                    switch (rec->encodingID)
                    {
                    case TT_MS_ID_SYMBOL_CS:
                    case TT_MS_ID_UNICODE_CS:
                    case TT_MS_ID_UCS_4:
                        is_english = FT_BOOL((rec->languageID & 0x3FF) == 0x009);
                        found_win  = n;
                        break;

                    default:
                        ;
                    }
                }

                break;

            default:
                ;
            }
        }
    }

    found_apple = found_apple_roman;
    if (found_apple_english >= 0)
        found_apple = found_apple_english;

    /* some fonts contain invalid Unicode or Macintosh formatted entries; */
    /* we will thus favor names encoded in Windows formats if available   */
    /* (provided it is an English name)                                   */
    /*                                                                    */
    convert = NULL;
    if (found_win >= 0 && !(found_apple >= 0 && !is_english))
    {
        rec = face->name_table.names + found_win;

        switch (rec->encodingID)
        {
        /* all Unicode strings are encoded using UTF-16BE */
        case TT_MS_ID_UNICODE_CS:
        case TT_MS_ID_SYMBOL_CS:
            convert = tt_name_entry_ascii_from_utf16;
            break;

        case TT_MS_ID_UCS_4:
            /* Apparently, if this value is found in a name table entry, it is */
            /* documented as `full Unicode repertoire'.  Experience with the   */
            /* MsGothic font shipped with Windows Vista shows that this really */
            /* means UTF-16 encoded names (UCS-4 values are only used within   */
            /* charmaps).                                                      */
            convert = tt_name_entry_ascii_from_utf16;
            break;

        default:
            ;
        }
    }
    else if (found_apple >= 0)
    {
        rec     = face->name_table.names + found_apple;
        convert = tt_name_entry_ascii_from_other;
    }
    else if (found_unicode >= 0)
    {
        rec     = face->name_table.names + found_unicode;
        convert = tt_name_entry_ascii_from_utf16;
    }

    if (rec && convert)
    {
        if (rec->string == NULL)
        {
            FT_Stream stream = face->name_table.stream;


            if (FT_QNEW_ARRAY (rec->string, rec->stringLength) ||
                FT_STREAM_SEEK(rec->stringOffset) ||
                FT_STREAM_READ(rec->string, rec->stringLength))
            {
                FT_FREE(rec->string);
                rec->stringLength = 0;
                result            = NULL;
                goto Exit;
            }
        }

        result = convert(rec, memory);
    }

Exit:
    *name = result;
    return error;
}
Example #4
0
  static FT_Error
  load_format_25( TT_Face    face,
                  FT_Stream  stream,
                  FT_ULong   post_limit )
  {
    FT_Memory  memory = stream->memory;
    FT_Error   error;

    FT_Int     num_glyphs;
    FT_Char*   offset_table = NULL;

    FT_UNUSED( post_limit );


    /* UNDOCUMENTED!  This value appears only in the Apple TT specs. */
    if ( FT_READ_USHORT( num_glyphs ) )
      goto Exit;

    /* check the number of glyphs */
    if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
    {
      error = FT_THROW( Invalid_File_Format );
      goto Exit;
    }

    if ( FT_NEW_ARRAY( offset_table, num_glyphs )   ||
         FT_STREAM_READ( offset_table, num_glyphs ) )
      goto Fail;

    /* now check the offset table */
    {
      FT_Int  n;


      for ( n = 0; n < num_glyphs; n++ )
      {
        FT_Long  idx = (FT_Long)n + offset_table[n];


        if ( idx < 0 || idx > num_glyphs )
        {
          error = FT_THROW( Invalid_File_Format );
          goto Fail;
        }
      }
    }

    /* OK, set table fields and exit successfully */
    {
      TT_Post_25  table = &face->postscript_names.names.format_25;


      table->num_glyphs = (FT_UShort)num_glyphs;
      table->offsets    = offset_table;
    }

    return FT_Err_Ok;

  Fail:
    FT_FREE( offset_table );

  Exit:
    return error;
  }
Example #5
0
  static FT_Error
  load_format_20( TT_Face    face,
                  FT_Stream  stream,
                  FT_ULong   post_limit )
  {
    FT_Memory   memory = stream->memory;
    FT_Error    error;

    FT_Int      num_glyphs;
    FT_UShort   num_names;

    FT_UShort*  glyph_indices = NULL;
    FT_Char**   name_strings  = NULL;


    if ( FT_READ_USHORT( num_glyphs ) )
      goto Exit;

    /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */
    /* than the value in the maxp table (cf. cyberbit.ttf).             */

    /* There already exist fonts which have more than 32768 glyph names */
    /* in this table, so the test for this threshold has been dropped.  */

    if ( num_glyphs > face->max_profile.numGlyphs )
    {
      error = FT_THROW( Invalid_File_Format );
      goto Exit;
    }

    /* load the indices */
    {
      FT_Int  n;


      if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
           FT_FRAME_ENTER( num_glyphs * 2L )          )
        goto Fail;

      for ( n = 0; n < num_glyphs; n++ )
        glyph_indices[n] = FT_GET_USHORT();

      FT_FRAME_EXIT();
    }

    /* compute number of names stored in table */
    {
      FT_Int  n;


      num_names = 0;

      for ( n = 0; n < num_glyphs; n++ )
      {
        FT_Int  idx;


        idx = glyph_indices[n];
        if ( idx >= 258 )
        {
          idx -= 257;
          if ( idx > num_names )
            num_names = (FT_UShort)idx;
        }
      }
    }

    /* now load the name strings */
    {
      FT_UShort  n;


      if ( FT_NEW_ARRAY( name_strings, num_names ) )
        goto Fail;

      for ( n = 0; n < num_names; n++ )
      {
        FT_UInt  len;


        if ( FT_STREAM_POS() >= post_limit )
          break;
        else
        {
          FT_TRACE6(( "load_format_20: %d byte left in post table\n",
                      post_limit - FT_STREAM_POS() ));

          if ( FT_READ_BYTE( len ) )
            goto Fail1;
        }

        if ( len > post_limit                   ||
             FT_STREAM_POS() > post_limit - len )
        {
          FT_Int  d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS();


          FT_ERROR(( "load_format_20:"
                     " exceeding string length (%d),"
                     " truncating at end of post table (%d byte left)\n",
                     len, d ));
          len = (FT_UInt)FT_MAX( 0, d );
        }

        if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
             FT_STREAM_READ( name_strings[n], len   ) )
          goto Fail1;

        name_strings[n][len] = '\0';
      }

      if ( n < num_names )
      {
        FT_ERROR(( "load_format_20:"
                   " all entries in post table are already parsed,"
                   " using NULL names for gid %d - %d\n",
                    n, num_names - 1 ));
        for ( ; n < num_names; n++ )
          if ( FT_NEW_ARRAY( name_strings[n], 1 ) )
            goto Fail1;
          else
            name_strings[n][0] = '\0';
      }
    }

    /* all right, set table fields and exit successfully */
    {
      TT_Post_20  table = &face->postscript_names.names.format_20;


      table->num_glyphs    = (FT_UShort)num_glyphs;
      table->num_names     = (FT_UShort)num_names;
      table->glyph_indices = glyph_indices;
      table->glyph_names   = name_strings;
    }
    return FT_Err_Ok;

  Fail1:
    {
      FT_UShort  n;


      for ( n = 0; n < num_names; n++ )
        FT_FREE( name_strings[n] );
    }

  Fail:
    FT_FREE( name_strings );
    FT_FREE( glyph_indices );

  Exit:
    return error;
  }
Example #6
0
  static FT_String*
  tt_face_get_name( TT_Face    face,
                    FT_UShort  nameid )
  {
    FT_Memory         memory = face->root.memory;
    FT_String*        result = NULL;
    FT_UShort         n;
    TT_NameEntryRec*  rec;
    FT_Int            found_apple   = -1;
    FT_Int            found_win     = -1;
    FT_Int            found_unicode = -1;

    FT_Bool           is_english = 0;

    TT_NameEntry_ConvertFunc  convert;


    rec = face->name_table.names;
    for ( n = 0; n < face->num_names; n++, rec++ )
    {
      /* According to the OpenType 1.3 specification, only Microsoft or  */
      /* Apple platform IDs might be used in the `name' table.  The      */
      /* `Unicode' platform is reserved for the `cmap' table, and the    */
      /* `Iso' one is deprecated.                                        */
      /*                                                                 */
      /* However, the Apple TrueType specification doesn't say the same  */
      /* thing and goes to suggest that all Unicode `name' table entries */
      /* should be coded in UTF-16 (in big-endian format I suppose).     */
      /*                                                                 */
      if ( rec->nameID == nameid && rec->stringLength > 0 )
      {
        switch ( rec->platformID )
        {
        case TT_PLATFORM_APPLE_UNICODE:
        case TT_PLATFORM_ISO:
          /* there is `languageID' to check there.  We should use this */
          /* field only as a last solution when nothing else is        */
          /* available.                                                */
          /*                                                           */
          found_unicode = n;
          break;

        case TT_PLATFORM_MACINTOSH:
          if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
            found_apple = n;

          break;

        case TT_PLATFORM_MICROSOFT:
          /* we only take a non-English name when there is nothing */
          /* else available in the font                            */
          /*                                                       */
          if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
          {
            switch ( rec->encodingID )
            {
            case TT_MS_ID_SYMBOL_CS:
            case TT_MS_ID_UNICODE_CS:
            case TT_MS_ID_UCS_4:
              is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
              found_win  = n;
              break;

            default:
              ;
            }
          }
          break;

        default:
          ;
        }
      }
    }

    /* some fonts contain invalid Unicode or Macintosh formatted entries; */
    /* we will thus favor names encoded in Windows formats if available   */
    /* (provided it is an English name)                                   */
    /*                                                                    */
    convert = NULL;
    if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
    {
      rec = face->name_table.names + found_win;
      switch ( rec->encodingID )
      {
      case TT_MS_ID_UNICODE_CS:
      case TT_MS_ID_SYMBOL_CS:
        convert = tt_name_entry_ascii_from_utf16;
        break;

      case TT_MS_ID_UCS_4:
        convert = tt_name_entry_ascii_from_ucs4;
        break;

      default:
        ;
      }
    }
    else if ( found_apple >= 0 )
    {
      rec     = face->name_table.names + found_apple;
      convert = tt_name_entry_ascii_from_other;
    }
    else if ( found_unicode >= 0 )
    {
      rec     = face->name_table.names + found_unicode;
      convert = tt_name_entry_ascii_from_utf16;
    }

    if ( rec && convert )
    {
      if ( rec->string == NULL )
      {
        FT_Error   error  = SFNT_Err_Ok;
        FT_Stream  stream = face->name_table.stream;

        FT_UNUSED( error );


        if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
             FT_STREAM_SEEK( rec->stringOffset )              ||
             FT_STREAM_READ( rec->string, rec->stringLength ) )
        {
          FT_FREE( rec->string );
          rec->stringLength = 0;
          result            = NULL;
          goto Exit;
        }
      }

      result = convert( rec, memory );
    }

  Exit:
    return result;
  }
Example #7
0
  t42_parser_init( T42_Parser     parser,
                   FT_Stream      stream,
                   FT_Memory      memory,
                   PSAux_Service  psaux )
  {
    FT_Error  error = FT_Err_Ok;
    FT_Long   size;


    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );

    parser->stream    = stream;
    parser->base_len  = 0;
    parser->base_dict = 0;
    parser->in_memory = 0;

    /*******************************************************************/
    /*                                                                 */
    /* Here a short summary of what is going on:                       */
    /*                                                                 */
    /*   When creating a new Type 42 parser, we try to locate and load */
    /*   the base dictionary, loading the whole font into memory.      */
    /*                                                                 */
    /*   When `loading' the base dictionary, we only set up pointers   */
    /*   in the case of a memory-based stream.  Otherwise, we allocate */
    /*   and load the base dictionary in it.                           */
    /*                                                                 */
    /*   parser->in_memory is set if we have a memory stream.          */
    /*                                                                 */

    if ( FT_STREAM_SEEK( 0L ) ||
         FT_FRAME_ENTER( 17 ) )
      goto Exit;

    if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )
    {
      FT_TRACE2(( "  not a Type42 font\n" ));
      error = FT_THROW( Unknown_File_Format );
    }

    FT_FRAME_EXIT();

    if ( error || FT_STREAM_SEEK( 0 ) )
      goto Exit;

    size = stream->size;

    /* now, try to load `size' bytes of the `base' dictionary we */
    /* found previously                                          */

    /* if it is a memory-based resource, set up pointers */
    if ( !stream->read )
    {
      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
      parser->base_len  = size;
      parser->in_memory = 1;

      /* check that the `size' field is valid */
      if ( FT_STREAM_SKIP( size ) )
        goto Exit;
    }
    else
    {
      /* read segment in memory */
      if ( FT_ALLOC( parser->base_dict, size )       ||
           FT_STREAM_READ( parser->base_dict, size ) )
        goto Exit;

      parser->base_len = size;
    }

    parser->root.base   = parser->base_dict;
    parser->root.cursor = parser->base_dict;
    parser->root.limit  = parser->root.cursor + parser->base_len;

  Exit:
    if ( error && !parser->in_memory )
      FT_FREE( parser->base_dict );

    return error;
  }
Example #8
0
  cid_parser_new( CID_Parser*    parser,
                  FT_Stream      stream,
                  FT_Memory      memory,
                  PSAux_Service  psaux )
  {
    FT_Error  error;
    FT_ULong  base_offset, offset, ps_len;
    FT_Byte   *cur, *limit;
    FT_Byte   *arg1, *arg2;


    FT_ZERO( parser );
    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );

    parser->stream = stream;

    base_offset = FT_STREAM_POS();

    /* first of all, check the font format in the header */
    if ( FT_FRAME_ENTER( 31 ) )
      goto Exit;

    if ( ft_strncmp( (char *)stream->cursor,
                     "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
    {
      FT_TRACE2(( "  not a CID-keyed font\n" ));
      error = FT_THROW( Unknown_File_Format );
    }

    FT_FRAME_EXIT();
    if ( error )
      goto Exit;

  Again:
    /* now, read the rest of the file until we find */
    /* `StartData' or `/sfnts'                      */
    {
      /*
       * The algorithm is as follows (omitting the case with less than 256
       * bytes to fill for simplicity).
       *
       * 1. Fill the buffer with 256 + STARTDATA_LEN bytes.
       *
       * 2. Search for the STARTDATA and SFNTS strings at positions
       *    buffer[0], buffer[1], ...,
       *    buffer[255 + STARTDATA_LEN - SFNTS_LEN].
       *
       * 3. Move the last STARTDATA_LEN bytes to buffer[0].
       *
       * 4. Fill the buffer with 256 bytes, starting at STARTDATA_LEN.
       *
       * 5. Repeat with step 2.
       *
       */
      FT_Byte  buffer[256 + STARTDATA_LEN + 1];

      /* values for the first loop */
      FT_ULong  read_len    = 256 + STARTDATA_LEN;
      FT_ULong  read_offset = 0;
      FT_Byte*  p           = buffer;


      for ( offset = FT_STREAM_POS(); ; offset += 256 )
      {
        FT_ULong  stream_len;


        stream_len = stream->size - FT_STREAM_POS();

        read_len = FT_MIN( read_len, stream_len );
        if ( FT_STREAM_READ( p, read_len ) )
          goto Exit;

        /* ensure that we do not compare with data beyond the buffer */
        p[read_len] = '\0';

        limit = p + read_len - SFNTS_LEN;

        for ( p = buffer; p < limit; p++ )
        {
          if ( p[0] == 'S'                                           &&
               ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
          {
            /* save offset of binary data after `StartData' */
            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
            goto Found;
          }
          else if ( p[1] == 's'                                   &&
                    ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
          {
            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
            goto Found;
          }
        }

        if ( read_offset + read_len < STARTDATA_LEN )
        {
          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
          error = FT_THROW( Invalid_File_Format );
          goto Exit;
        }

        FT_MEM_MOVE( buffer,
                     buffer + read_offset + read_len - STARTDATA_LEN,
                     STARTDATA_LEN );

        /* values for the next loop */
        read_len    = 256;
        read_offset = STARTDATA_LEN;
        p           = buffer + read_offset;
      }
    }

  Found:
    /* We have found the start of the binary data or the `/sfnts' token. */
    /* Now rewind and extract the frame corresponding to this PostScript */
    /* section.                                                          */

    ps_len = offset - base_offset;
    if ( FT_STREAM_SEEK( base_offset )                  ||
         FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
      goto Exit;

    parser->data_offset    = offset;
    parser->postscript_len = ps_len;
    parser->root.base      = parser->postscript;
    parser->root.cursor    = parser->postscript;
    parser->root.limit     = parser->root.cursor + ps_len;
    parser->num_dict       = -1;

    /* Finally, we check whether `StartData' or `/sfnts' was real --  */
    /* it could be in a comment or string.  We also get the arguments */
    /* of `StartData' to find out whether the data is represented in  */
    /* binary or hex format.                                          */

    arg1 = parser->root.cursor;
    cid_parser_skip_PS_token( parser );
    cid_parser_skip_spaces  ( parser );
    arg2 = parser->root.cursor;
    cid_parser_skip_PS_token( parser );
    cid_parser_skip_spaces  ( parser );

    limit = parser->root.limit;
    cur   = parser->root.cursor;

    while ( cur <= limit - SFNTS_LEN )
    {
      if ( parser->root.error )
      {
        error = parser->root.error;
        goto Exit;
      }

      if ( cur[0] == 'S'                                           &&
           cur <= limit - STARTDATA_LEN                            &&
           ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 )
      {
        if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
        {
          FT_Long  tmp = ft_strtol( (const char *)arg2, NULL, 10 );


          if ( tmp < 0 )
          {
            FT_ERROR(( "cid_parser_new: invalid length of hex data\n" ));
            error = FT_THROW( Invalid_File_Format );
          }
          else
            parser->binary_length = (FT_ULong)tmp;
        }

        goto Exit;
      }
      else if ( cur[1] == 's'                                   &&
                ft_strncmp( (char*)cur, SFNTS, SFNTS_LEN ) == 0 )
      {
        FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
        error = FT_THROW( Unknown_File_Format );
        goto Exit;
      }

      cid_parser_skip_PS_token( parser );
      cid_parser_skip_spaces  ( parser );
      arg1 = arg2;
      arg2 = cur;
      cur  = parser->root.cursor;
    }

    /* we haven't found the correct `StartData'; go back and continue */
    /* searching                                                      */
    FT_FRAME_RELEASE( parser->postscript );
    if ( !FT_STREAM_SEEK( offset ) )
      goto Again;

  Exit:
    return error;
  }
  T1_Get_Private_Dict( T1_Parser      parser,
                       PSAux_Service  psaux )
  {
    FT_Stream  stream = parser->stream;
    FT_Memory  memory = parser->root.memory;
    FT_Error   error  = FT_Err_Ok;
    FT_ULong   size;


    if ( parser->in_pfb )
    {
      /* in the case of the PFB format, the private dictionary can be  */
      /* made of several segments.  We thus first read the number of   */
      /* segments to compute the total size of the private dictionary  */
      /* then re-read them into memory.                                */
      FT_Long    start_pos = FT_STREAM_POS();
      FT_UShort  tag;


      parser->private_len = 0;
      for (;;)
      {
        error = read_pfb_tag( stream, &tag, &size );
        if ( error )
          goto Fail;

        if ( tag != 0x8002U )
          break;

        parser->private_len += size;

        if ( FT_STREAM_SKIP( size ) )
          goto Fail;
      }

      /* Check that we have a private dictionary there */
      /* and allocate private dictionary buffer        */
      if ( parser->private_len == 0 )
      {
        FT_ERROR(( "T1_Get_Private_Dict:"
                   " invalid private dictionary section\n" ));
        error = FT_THROW( Invalid_File_Format );
        goto Fail;
      }

      if ( FT_STREAM_SEEK( start_pos )                           ||
           FT_ALLOC( parser->private_dict, parser->private_len ) )
        goto Fail;

      parser->private_len = 0;
      for (;;)
      {
        error = read_pfb_tag( stream, &tag, &size );
        if ( error || tag != 0x8002U )
        {
          error = FT_Err_Ok;
          break;
        }

        if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
                             size ) )
          goto Fail;

        parser->private_len += size;
      }
    }
    else
    {
      /* We have already `loaded' the whole PFA font file into memory; */
      /* if this is a memory resource, allocate a new block to hold    */
      /* the private dict.  Otherwise, simply overwrite into the base  */
      /* dictionary block in the heap.                                 */

      /* first of all, look at the `eexec' keyword */
      FT_Byte*  cur   = parser->base_dict;
      FT_Byte*  limit = cur + parser->base_len;
      FT_Byte   c;


    Again:
      for (;;)
      {
        c = cur[0];
        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
                                            /* whitespace + 4 chars        */
        {
          if ( cur[1] == 'e' &&
               cur[2] == 'x' &&
               cur[3] == 'e' &&
               cur[4] == 'c' )
            break;
        }
        cur++;
        if ( cur >= limit )
        {
          FT_ERROR(( "T1_Get_Private_Dict:"
                     " could not find `eexec' keyword\n" ));
          error = FT_THROW( Invalid_File_Format );
          goto Exit;
        }
      }

      /* check whether `eexec' was real -- it could be in a comment */
      /* or string (as e.g. in u003043t.gsf from ghostscript)       */

      parser->root.cursor = parser->base_dict;
      /* set limit to `eexec' + whitespace + 4 characters */
      parser->root.limit  = cur + 10;

      cur   = parser->root.cursor;
      limit = parser->root.limit;

      while ( cur < limit )
      {
        if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
          goto Found;

        T1_Skip_PS_Token( parser );
        if ( parser->root.error )
          break;
        T1_Skip_Spaces  ( parser );
        cur = parser->root.cursor;
      }

      /* we haven't found the correct `eexec'; go back and continue */
      /* searching                                                  */

      cur   = limit;
      limit = parser->base_dict + parser->base_len;
      goto Again;

      /* now determine where to write the _encrypted_ binary private  */
      /* dictionary.  We overwrite the base dictionary for disk-based */
      /* resources and allocate a new block otherwise                 */

    Found:
      parser->root.limit = parser->base_dict + parser->base_len;

      T1_Skip_PS_Token( parser );
      cur   = parser->root.cursor;
      limit = parser->root.limit;

      /* according to the Type1 spec, the first cipher byte must not be  */
      /* an ASCII whitespace character code (blank, tab, carriage return */
      /* or line feed).  We have seen Type 1 fonts with two line feed    */
      /* characters...  So skip now all whitespace character codes.      */
      /* SumatraPDF: stop at \r if it's not used for EOL - cf. https://code.google.com/p/sumatrapdf/issues/detail?id=2408 */
      c = !memchr(cur, '\n', limit - cur) || memchr(cur, '\n', limit - cur) > memchr(cur, '\r', limit - cur);
      while ( cur < limit       &&
              ( *cur == ' '  ||
                *cur == '\t' ||
                ( c && *cur == '\r' ) ||
                *cur == '\n' ) )
        ++cur;
      if ( cur >= limit )
      {
        FT_ERROR(( "T1_Get_Private_Dict:"
                   " `eexec' not properly terminated\n" ));
        error = FT_THROW( Invalid_File_Format );
        goto Exit;
      }

      size = (FT_ULong)( parser->base_len - ( cur - parser->base_dict ) );

      if ( parser->in_memory )
      {
        /* note that we allocate one more byte to put a terminating `0' */
        if ( FT_ALLOC( parser->private_dict, size + 1 ) )
          goto Fail;
        parser->private_len = size;
      }
      else
      {
        parser->single_block = 1;
        parser->private_dict = parser->base_dict;
        parser->private_len  = size;
        parser->base_dict    = 0;
        parser->base_len     = 0;
      }

      /* now determine whether the private dictionary is encoded in binary */
      /* or hexadecimal ASCII format -- decode it accordingly              */

      /* we need to access the next 4 bytes (after the final whitespace */
      /* following the `eexec' keyword); if they all are hexadecimal    */
      /* digits, then we have a case of ASCII storage                   */

      if ( cur + 3 < limit                                &&
           ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
           ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
      {
        /* ASCII hexadecimal encoding */
        FT_Long  len;


        parser->root.cursor = cur;
        (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
                                                parser->private_dict,
                                                parser->private_len,
                                                &len,
                                                0 );
        parser->private_len = len;

        /* put a safeguard */
        parser->private_dict[len] = '\0';
      }
      else
        /* binary encoding -- copy the private dict */
        FT_MEM_MOVE( parser->private_dict, cur, size );
    }

    /* we now decrypt the encoded binary private dictionary */
    psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );

    if ( parser->private_len < 4 )
    {
      FT_ERROR(( "T1_Get_Private_Dict:"
                 " invalid private dictionary section\n" ));
      error = FT_THROW( Invalid_File_Format );
      goto Fail;
    }

    /* replace the four random bytes at the beginning with whitespace */
    parser->private_dict[0] = ' ';
    parser->private_dict[1] = ' ';
    parser->private_dict[2] = ' ';
    parser->private_dict[3] = ' ';

    parser->root.base   = parser->private_dict;
    parser->root.cursor = parser->private_dict;
    parser->root.limit  = parser->root.cursor + parser->private_len;

  Fail:
  Exit:
    return error;
  }
Example #10
0
  cid_parser_new( CID_Parser*    parser,
                  FT_Stream      stream,
                  FT_Memory      memory,
                  PSAux_Service  psaux )
  {
    FT_Error  error;
    FT_ULong  base_offset, offset, ps_len;
    FT_Byte   buffer[256 + 10];
    FT_Int    buff_len;
    FT_Byte   *cur, *limit;
    FT_Byte   *arg1, *arg2;


    FT_MEM_ZERO( parser, sizeof ( *parser ) );
    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );

    parser->stream = stream;

    base_offset = FT_STREAM_POS();

    /* first of all, check the font format in the header */
    if ( FT_FRAME_ENTER( 31 ) )
      goto Exit;

    if ( ft_strncmp( (char *)stream->cursor,
                     "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
    {
      FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
      error = CID_Err_Unknown_File_Format;
    }

    FT_FRAME_EXIT();
    if ( error )
      goto Exit;

  Again:
    /* now, read the rest of the file until we find a `StartData' */
    buff_len = 256;
    for (;;)
    {
      FT_Byte*  p;
      FT_ULong  top_position;


      /* fill input buffer */
      limit     = buffer + 256;
      buff_len -= 256;
      if ( buff_len > 0 )
        FT_MEM_MOVE( buffer, limit, buff_len );

      p = buffer + buff_len;

      if ( FT_STREAM_READ( p, 256 + 10 - buff_len ) )
        goto Exit;

      top_position = FT_STREAM_POS() - buff_len;
      buff_len     = 256 + 10;

      /* look for `StartData' */
      for ( p = buffer; p < limit; p++ )
      {
        if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
        {
          /* save offset of binary data after `StartData' */
          offset = (FT_ULong)( top_position - ( limit - p ) + 10 );
          goto Found;
        }
      }
    }

  Found:
    /* we have found the start of the binary data.  We will now     */
    /* rewind and extract the frame corresponding to the PostScript */
    /* section                                                      */

    ps_len = offset - base_offset;
    if ( FT_STREAM_SEEK( base_offset )                  ||
         FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
      goto Exit;

    parser->data_offset    = offset;
    parser->postscript_len = ps_len;
    parser->root.base      = parser->postscript;
    parser->root.cursor    = parser->postscript;
    parser->root.limit     = parser->root.cursor + ps_len;
    parser->num_dict       = -1;

    /* Finally, we check whether `StartData' was real -- it could be  */
    /* in a comment or string.  We also get its arguments to find out */
    /* whether the data is represented in binary or hex format.       */

    arg1 = parser->root.cursor;
    cid_parser_skip_PS_token( parser );
    cid_parser_skip_spaces  ( parser );
    arg2 = parser->root.cursor;
    cid_parser_skip_PS_token( parser );
    cid_parser_skip_spaces  ( parser );

    limit = parser->root.limit;
    cur   = parser->root.cursor;

    while ( cur < limit )
    {
      if ( parser->root.error )
        break;

      if ( *cur == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
      {
        if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
          parser->binary_length = ft_atol( (const char *)arg2 );

        limit = parser->root.limit;
        cur   = parser->root.cursor;
        goto Exit;
      }

      cid_parser_skip_PS_token( parser );
      cid_parser_skip_spaces  ( parser );
      arg1 = arg2;
      arg2 = cur;
      cur  = parser->root.cursor;
    }

    /* we haven't found the correct `StartData'; go back and continue */
    /* searching                                                      */
    FT_FRAME_RELEASE( parser->postscript );
    if ( !FT_STREAM_SEEK( offset ) )
      goto Again;

  Exit:
    return error;
  }
Example #11
0
cid_parser_new( CID_Parser*    parser,
                FT_Stream      stream,
                FT_Memory      memory,
                PSAux_Service  psaux )
{
    FT_Error  error;
    FT_ULong  base_offset, offset, ps_len;
    FT_Byte   *cur, *limit;
    FT_Byte   *arg1, *arg2;


    FT_MEM_ZERO( parser, sizeof ( *parser ) );
    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );

    parser->stream = stream;

    base_offset = FT_STREAM_POS();

    /* first of all, check the font format in the header */
    if ( FT_FRAME_ENTER( 31 ) )
        goto Exit;

    if ( ft_strncmp( (char *)stream->cursor,
                     "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
    {
        FT_TRACE2(( "  not a CID-keyed font\n" ));
        error = FT_THROW( Unknown_File_Format );
    }

    FT_FRAME_EXIT();
    if ( error )
        goto Exit;

Again:
    /* now, read the rest of the file until we find */
    /* `StartData' or `/sfnts'                      */
    {
        FT_Byte   buffer[256 + 10];
        FT_ULong  read_len = 256 + 10;
        FT_Byte*  p        = buffer;


        for ( offset = FT_STREAM_POS(); ; offset += 256 )
        {
            FT_ULong  stream_len;


            stream_len = stream->size - FT_STREAM_POS();
            if ( stream_len == 0 )
            {
                FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
                error = FT_THROW( Invalid_File_Format );
                goto Exit;
            }

            read_len = FT_MIN( read_len, stream_len );
            if ( FT_STREAM_READ( p, read_len ) )
                goto Exit;

            if ( read_len < 256 )
                p[read_len]  = '\0';

            limit = p + read_len - 10;

            for ( p = buffer; p < limit; p++ )
            {
                if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
                {
                    /* save offset of binary data after `StartData' */
                    offset += (FT_ULong)( p - buffer + 10 );
                    goto Found;
                }
                else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 )
                {
                    offset += (FT_ULong)( p - buffer + 7 );
                    goto Found;
                }
            }

            FT_MEM_MOVE( buffer, p, 10 );
            read_len = 256;
            p = buffer + 10;
        }
    }

Found:
    /* We have found the start of the binary data or the `/sfnts' token. */
    /* Now rewind and extract the frame corresponding to this PostScript */
    /* section.                                                          */

    ps_len = offset - base_offset;
    if ( FT_STREAM_SEEK( base_offset )                  ||
            FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
        goto Exit;

    parser->data_offset    = offset;
    parser->postscript_len = ps_len;
    parser->root.base      = parser->postscript;
    parser->root.cursor    = parser->postscript;
    parser->root.limit     = parser->root.cursor + ps_len;
    parser->num_dict       = -1;

    /* Finally, we check whether `StartData' or `/sfnts' was real --  */
    /* it could be in a comment or string.  We also get the arguments */
    /* of `StartData' to find out whether the data is represented in  */
    /* binary or hex format.                                          */

    arg1 = parser->root.cursor;
    cid_parser_skip_PS_token( parser );
    cid_parser_skip_spaces  ( parser );
    arg2 = parser->root.cursor;
    cid_parser_skip_PS_token( parser );
    cid_parser_skip_spaces  ( parser );

    limit = parser->root.limit;
    cur   = parser->root.cursor;

    while ( cur < limit )
    {
        if ( parser->root.error )
        {
            error = parser->root.error;
            goto Exit;
        }

        if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
        {
            if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
            {
                FT_Long  tmp = ft_atol( (const char *)arg2 );


                if ( tmp < 0 )
                {
                    FT_ERROR(( "cid_parser_new: invalid length of hex data\n" ));
                    error = FT_THROW( Invalid_File_Format );
                }
                else
                    parser->binary_length = (FT_ULong)tmp;
            }

            goto Exit;
        }
        else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 )
        {
            FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
            error = FT_THROW( Unknown_File_Format );
            goto Exit;
        }

        cid_parser_skip_PS_token( parser );
        cid_parser_skip_spaces  ( parser );
        arg1 = arg2;
        arg2 = cur;
        cur  = parser->root.cursor;
    }

    /* we haven't found the correct `StartData'; go back and continue */
    /* searching                                                      */
    FT_FRAME_RELEASE( parser->postscript );
    if ( !FT_STREAM_SEEK( offset ) )
        goto Again;

Exit:
    return error;
}
Example #12
0
File: ttpost.c Project: 1tgr/mobius
  static FT_Error
  load_format_20( TT_Face    face,
                  FT_Stream  stream )
  {
    FT_Memory   memory = stream->memory;
    FT_Error    error;

    FT_Int      num_glyphs;
    FT_UShort   num_names;

    FT_UShort*  glyph_indices = 0;
    FT_Char**   name_strings  = 0;


    if ( FT_READ_USHORT( num_glyphs ) )
      goto Exit;

    /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */
    /* than the value in the maxp table (cf. cyberbit.ttf).             */

    /* There already exist fonts which have more than 32768 glyph names */
    /* in this table, so the test for this threshold has been dropped.  */

    if ( num_glyphs > face->root.num_glyphs )
    {
      error = SFNT_Err_Invalid_File_Format;
      goto Exit;
    }

    /* load the indices */
    {
      FT_Int  n;


      if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
           FT_FRAME_ENTER( num_glyphs * 2L )          )
        goto Fail;

      for ( n = 0; n < num_glyphs; n++ )
        glyph_indices[n] = FT_GET_USHORT();

      FT_FRAME_EXIT();
    }

    /* compute number of names stored in table */
    {
      FT_Int  n;


      num_names = 0;

      for ( n = 0; n < num_glyphs; n++ )
      {
        FT_Int  idx;


        idx = glyph_indices[n];
        if ( idx >= 258 )
        {
          idx -= 257;
          if ( idx > num_names )
            num_names = (FT_UShort)idx;
        }
      }
    }

    /* now load the name strings */
    {
      FT_UShort  n;


      if ( FT_NEW_ARRAY( name_strings, num_names ) )
        goto Fail;

      for ( n = 0; n < num_names; n++ )
      {
        FT_UInt  len;


        if ( FT_READ_BYTE  ( len )                    ||
             FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
             FT_STREAM_READ  ( name_strings[n], len ) )
          goto Fail1;

        name_strings[n][len] = '\0';
      }
    }

    /* all right, set table fields and exit successfuly */
    {
      TT_Post_20  table = &face->postscript_names.names.format_20;


      table->num_glyphs    = (FT_UShort)num_glyphs;
      table->num_names     = (FT_UShort)num_names;
      table->glyph_indices = glyph_indices;
      table->glyph_names   = name_strings;
    }
    return SFNT_Err_Ok;

  Fail1:
    {
      FT_UShort  n;


      for ( n = 0; n < num_names; n++ )
        FT_FREE( name_strings[n] );
    }

  Fail:
    FT_FREE( name_strings );
    FT_FREE( glyph_indices );

  Exit:
    return error;
  }
Example #13
0
File: t1parse.c Project: 8l/inferno
  T1_Get_Private_Dict( T1_Parser      parser,
                       PSAux_Service  psaux )
  {
    FT_Stream  stream = parser->stream;
    FT_Memory  memory = parser->root.memory;
    FT_Error   error  = 0;
    FT_Long    size;


    if ( parser->in_pfb )
    {
      /* in the case of the PFB format, the private dictionary can be  */
      /* made of several segments.  We thus first read the number of   */
      /* segments to compute the total size of the private dictionary  */
      /* then re-read them into memory.                                */
      FT_Long    start_pos = FT_STREAM_POS();
      FT_UShort  tag;


      parser->private_len = 0;
      for (;;)
      {
        error = read_pfb_tag( stream, &tag, &size );
        if ( error )
          goto Fail;

        if ( tag != 0x8002U )
          break;

        parser->private_len += size;

        if ( FT_STREAM_SKIP( size ) )
          goto Fail;
      }

      /* Check that we have a private dictionary there */
      /* and allocate private dictionary buffer        */
      if ( parser->private_len == 0 )
      {
        FT_ERROR(( "T1_Get_Private_Dict:" ));
        FT_ERROR(( " invalid private dictionary section\n" ));
        error = T1_Err_Invalid_File_Format;
        goto Fail;
      }

      if ( FT_STREAM_SEEK( start_pos )                             ||
           FT_ALLOC( parser->private_dict, parser->private_len ) )
        goto Fail;

      parser->private_len = 0;
      for (;;)
      {
        error = read_pfb_tag( stream, &tag, &size );
        if ( error || tag != 0x8002U )
        {
          error = T1_Err_Ok;
          break;
        }

        if ( FT_STREAM_READ( parser->private_dict + parser->private_len, size ) )
          goto Fail;

        parser->private_len += size;
      }
    }
    else
    {
      /* we have already `loaded' the whole PFA font file into memory; */
      /* if this is a memory resource, allocate a new block to hold    */
      /* the private dict. Otherwise, simply overwrite into the base   */
      /* dictionary block in the heap.                                 */

      /* first of all, look at the `eexec' keyword */
      FT_Byte*  cur   = parser->base_dict;
      FT_Byte*  limit = cur + parser->base_len;
      FT_Byte   c;


      for (;;)
      {
        c = cur[0];
        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
                                            /* newline + 4 chars           */
        {
          if ( cur[1] == 'e' && cur[2] == 'x' &&
               cur[3] == 'e' && cur[4] == 'c' )
          {
            cur += 6; /* we skip the newling after the `eexec' */

            /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
            /*      skip the extra \n if we find it                     */
            if ( cur[0] == '\n' )
              cur++;

            break;
          }
        }
        cur++;
        if ( cur >= limit )
        {
          FT_ERROR(( "T1_Get_Private_Dict:" ));
          FT_ERROR(( " could not find `eexec' keyword\n" ));
          error = T1_Err_Invalid_File_Format;
          goto Exit;
        }
      }

      /* now determine where to write the _encrypted_ binary private  */
      /* dictionary.  We overwrite the base dictionary for disk-based */
      /* resources and allocate a new block otherwise                 */

      size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );

      if ( parser->in_memory )
      {
        /* note that we allocate one more byte to put a terminating `0' */
        if ( FT_ALLOC( parser->private_dict, size + 1 ) )
          goto Fail;
        parser->private_len = size;
      }
      else
      {
        parser->single_block = 1;
        parser->private_dict = parser->base_dict;
        parser->private_len  = size;
        parser->base_dict    = 0;
        parser->base_len     = 0;
      }

      /* now determine whether the private dictionary is encoded in binary */
      /* or hexadecimal ASCII format -- decode it accordingly              */

      /* we need to access the next 4 bytes (after the final \r following */
      /* the `eexec' keyword); if they all are hexadecimal digits, then   */
      /* we have a case of ASCII storage                                  */

      if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
             hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )

        /* binary encoding -- `simply' copy the private dict */
        FT_MEM_COPY( parser->private_dict, cur, size );

      else
      {
        /* ASCII hexadecimal encoding */

        FT_Byte*  write;
        FT_Int    count;


        write = parser->private_dict;
        count = 0;

        for ( ;cur < limit; cur++ )
        {
          int  hex1;


          /* check for newline */
          if ( cur[0] == '\r' || cur[0] == '\n' )
            continue;

          /* exit if we have a non-hexadecimal digit that isn't a newline */
          hex1 = hexa_value( cur[0] );
          if ( hex1 < 0 || cur + 1 >= limit )
            break;

          /* otherwise, store byte */
          *write++ = (FT_Byte)( ( hex1 << 4 ) | hexa_value( cur[1] ) );
          count++;
          cur++;
        }

        /* put a safeguard */
        parser->private_len = write - parser->private_dict;
        *write++ = 0;
      }
    }

    /* we now decrypt the encoded binary private dictionary */
    psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
    parser->root.base   = parser->private_dict;
    parser->root.cursor = parser->private_dict;
    parser->root.limit  = parser->root.cursor + parser->private_len;

  Fail:
  Exit:
    return error;
  }
Example #14
0
/* check and skip .gz header - we don't support `transparent' compression */
static FT_Error
ft_gzip_check_header( FT_Stream  stream )
{
    FT_Error  error;
    FT_Byte   head[4];


    if ( FT_STREAM_SEEK( 0 )       ||
            FT_STREAM_READ( head, 4 ) )
        goto Exit;

    /* head[0] && head[1] are the magic numbers;    */
    /* head[2] is the method, and head[3] the flags */
    if ( head[0] != 0x1f              ||
            head[1] != 0x8b              ||
            head[2] != Z_DEFLATED        ||
            (head[3] & FT_GZIP_RESERVED)  )
    {
        error = Gzip_Err_Invalid_File_Format;
        goto Exit;
    }

    /* skip time, xflags and os code */
    (void)FT_STREAM_SKIP( 6 );

    /* skip the extra field */
    if ( head[3] & FT_GZIP_EXTRA_FIELD )
    {
        FT_UInt  len;


        if ( FT_READ_USHORT_LE( len ) ||
                FT_STREAM_SKIP( len )    )
            goto Exit;
    }

    /* skip original file name */
    if ( head[3] & FT_GZIP_ORIG_NAME )
        for (;;)
        {
            FT_UInt  c;


            if ( FT_READ_BYTE( c ) )
                goto Exit;

            if ( c == 0 )
                break;
        }

    /* skip .gz comment */
    if ( head[3] & FT_GZIP_COMMENT )
        for (;;)
        {
            FT_UInt  c;


            if ( FT_READ_BYTE( c ) )
                goto Exit;

            if ( c == 0 )
                break;
        }

    /* skip CRC */
    if ( head[3] & FT_GZIP_HEAD_CRC )
        if ( FT_STREAM_SKIP( 2 ) )
            goto Exit;

Exit:
    return error;
}
Example #15
0
  CID_New_Parser( CID_Parser*    parser,
                  FT_Stream      stream,
                  FT_Memory      memory,
                  PSAux_Service  psaux )
  {
    FT_Error  error;
    FT_ULong  base_offset, offset, ps_len;
    FT_Byte   buffer[256 + 10];
    FT_Int    buff_len;


    FT_MEM_SET( parser, 0, sizeof ( *parser ) );
    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );

    parser->stream = stream;

    base_offset = FT_STREAM_POS();

    /* first of all, check the font format in the  header */
    if ( FT_FRAME_ENTER( 31 ) )
      goto Exit;

    if ( ft_strncmp( (char *)stream->cursor,
                     "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
    {
      FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
      error = CID_Err_Unknown_File_Format;
    }

    FT_FRAME_EXIT();
    if ( error )
      goto Exit;

    /* now, read the rest of the file, until we find a `StartData' */
    buff_len = 256;
    for (;;)
    {
      FT_Byte   *p, *limit = buffer + 256;
      FT_ULong  top_position;


      /* fill input buffer */
      buff_len -= 256;
      if ( buff_len > 0 )
        FT_MEM_MOVE( buffer, limit, buff_len );

      p = buffer + buff_len;

      if ( FT_STREAM_READ( p, 256 + 10 - buff_len ) )
        goto Exit;

      top_position = FT_STREAM_POS() - buff_len;
      buff_len = 256 + 10;

      /* look for `StartData' */
      for ( p = buffer; p < limit; p++ )
      {
        if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
        {
          /* save offset of binary data after `StartData' */
          offset = (FT_ULong)( top_position - ( limit - p ) + 10 );
          goto Found;
        }
      }
    }

  Found:
    /* we have found the start of the binary data.  We will now        */
    /* rewind and extract the frame of corresponding to the Postscript */
    /* section                                                         */

    ps_len = offset - base_offset;
    if ( FT_STREAM_SEEK( base_offset )                    ||
         FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
      goto Exit;

    parser->data_offset    = offset;
    parser->postscript_len = ps_len;
    parser->root.base      = parser->postscript;
    parser->root.cursor    = parser->postscript;
    parser->root.limit     = parser->root.cursor + ps_len;
    parser->num_dict       = -1;

  Exit:
    return error;
  }
  T1_New_Parser( T1_Parser      parser,
                 FT_Stream      stream,
                 FT_Memory      memory,
                 PSAux_Service  psaux )
  {
    FT_Error   error;
    FT_UShort  tag;
    FT_ULong   size;


    psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );

    parser->stream       = stream;
    parser->base_len     = 0;
    parser->base_dict    = 0;
    parser->private_len  = 0;
    parser->private_dict = 0;
    parser->in_pfb       = 0;
    parser->in_memory    = 0;
    parser->single_block = 0;

    /* check the header format */
    error = check_type1_format( stream, "%!PS-AdobeFont", 14 );
    if ( error )
    {
      if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
        goto Exit;

      error = check_type1_format( stream, "%!FontType", 10 );
      if ( error )
      {
        FT_TRACE2(( "  not a Type 1 font\n" ));
        goto Exit;
      }
    }

    /******************************************************************/
    /*                                                                */
    /* Here a short summary of what is going on:                      */
    /*                                                                */
    /*   When creating a new Type 1 parser, we try to locate and load */
    /*   the base dictionary if this is possible (i.e., for PFB       */
    /*   files).  Otherwise, we load the whole font into memory.      */
    /*                                                                */
    /*   When `loading' the base dictionary, we only setup pointers   */
    /*   in the case of a memory-based stream.  Otherwise, we         */
    /*   allocate and load the base dictionary in it.                 */
    /*                                                                */
    /*   parser->in_pfb is set if we are in a binary (`.pfb') font.   */
    /*   parser->in_memory is set if we have a memory stream.         */
    /*                                                                */

    /* try to compute the size of the base dictionary;     */
    /* look for a Postscript binary file tag, i.e., 0x8001 */
    if ( FT_STREAM_SEEK( 0L ) )
      goto Exit;

    error = read_pfb_tag( stream, &tag, &size );
    if ( error )
      goto Exit;

    if ( tag != 0x8001U )
    {
      /* assume that this is a PFA file for now; an error will */
      /* be produced later when more things are checked        */
      if ( FT_STREAM_SEEK( 0L ) )
        goto Exit;
      size = stream->size;
    }
    else
      parser->in_pfb = 1;

    /* now, try to load `size' bytes of the `base' dictionary we */
    /* found previously                                          */

    /* if it is a memory-based resource, set up pointers */
    if ( !stream->read )
    {
      parser->base_dict = (FT_Byte*)stream->base + stream->pos;
      parser->base_len  = size;
      parser->in_memory = 1;

      /* check that the `size' field is valid */
      if ( FT_STREAM_SKIP( size ) )
        goto Exit;
    }
    else
    {
      /* read segment in memory -- this is clumsy, but so does the format */
      if ( FT_ALLOC( parser->base_dict, size )       ||
           FT_STREAM_READ( parser->base_dict, size ) )
        goto Exit;
      parser->base_len = size;
    }

    parser->root.base   = parser->base_dict;
    parser->root.cursor = parser->base_dict;
    parser->root.limit  = parser->root.cursor + parser->base_len;

  Exit:
    if ( error && !parser->in_memory )
      FT_FREE( parser->base_dict );

    return error;
  }
Example #17
0
  static FT_Error
  PCF_Glyph_Load( FT_GlyphSlot  slot,
                  FT_Size       size,
                  FT_UInt       glyph_index,
                  FT_Int32      load_flags )
  {
    PCF_Face    face   = (PCF_Face)FT_SIZE_FACE( size );
    FT_Stream   stream = face->root.stream;
    FT_Error    error  = PCF_Err_Ok;
    FT_Bitmap*  bitmap = &slot->bitmap;
    PCF_Metric  metric;
    int         bytes;

    FT_UNUSED( load_flags );


    FT_TRACE4(( "load_glyph %d ---", glyph_index ));

    if ( !face )
    {
      error = PCF_Err_Invalid_Argument;
      goto Exit;
    }

    if ( glyph_index > 0 )
      glyph_index--;

    metric = face->metrics + glyph_index;

    bitmap->rows       = metric->ascent + metric->descent;
    bitmap->width      = metric->rightSideBearing - metric->leftSideBearing;
    bitmap->num_grays  = 1;
    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;

    FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n",
                  PCF_BIT_ORDER( face->bitmapsFormat ),
                  PCF_BYTE_ORDER( face->bitmapsFormat ),
                  PCF_GLYPH_PAD( face->bitmapsFormat ) ));

    switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) )
    {
    case 1:
      bitmap->pitch = ( bitmap->width + 7 ) >> 3;
      break;

    case 2:
      bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1;
      break;

    case 4:
      bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2;
      break;

    case 8:
      bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3;
      break;

    default:
      return PCF_Err_Invalid_File_Format;
    }

    /* XXX: to do: are there cases that need repadding the bitmap? */
    bytes = bitmap->pitch * bitmap->rows;

    error = ft_glyphslot_alloc_bitmap( slot, bytes );
    if ( error )
      goto Exit;

    if ( FT_STREAM_SEEK( metric->bits )          ||
         FT_STREAM_READ( bitmap->buffer, bytes ) )
      goto Exit;

    if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst )
      BitOrderInvert( bitmap->buffer, bytes );

    if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) !=
           PCF_BIT_ORDER( face->bitmapsFormat )  ) )
    {
      switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) )
      {
      case 1:
        break;

      case 2:
        TwoByteSwap( bitmap->buffer, bytes );
        break;

      case 4:
        FourByteSwap( bitmap->buffer, bytes );
        break;
      }
    }

    slot->bitmap_left = metric->leftSideBearing;
    slot->bitmap_top  = metric->ascent;

    slot->metrics.horiAdvance  = metric->characterWidth << 6;
    slot->metrics.horiBearingX = metric->leftSideBearing << 6;
    slot->metrics.horiBearingY = metric->ascent << 6;
    slot->metrics.width        = ( metric->rightSideBearing -
                                   metric->leftSideBearing ) << 6;
    slot->metrics.height       = bitmap->rows << 6;

    slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16;
    slot->format            = FT_GLYPH_FORMAT_BITMAP;

    FT_TRACE4(( " --- ok\n" ));

  Exit:
    return error;
  }
Example #18
0
  static const char*
  get_sfnt_postscript_name( TT_Face  face )
  {
    FT_Int       n, found_win, found_apple;
    const char*  result = NULL;


    /* shouldn't happen, but just in case to avoid memory leaks */
    if ( face->root.internal->postscript_name )
      return face->root.internal->postscript_name;

    /* scan the name table to see whether we have a Postscript name here, */
    /* either in Macintosh or Windows platform encodings                  */
    found_win   = -1;
    found_apple = -1;

    for ( n = 0; n < face->num_names; n++ )
    {
      TT_NameEntryRec*  name = face->name_table.names + n;


      if ( name->nameID == 6 && name->stringLength > 0 )
      {
        if ( name->platformID == 3     &&
             name->encodingID == 1     &&
             name->languageID == 0x409 )
          found_win = n;

        if ( name->platformID == 1 &&
             name->encodingID == 0 &&
             name->languageID == 0 )
          found_apple = n;
      }
    }

    if ( found_win != -1 )
    {
      FT_Memory         memory = face->root.memory;
      TT_NameEntryRec*  name   = face->name_table.names + found_win;
      FT_UInt           len    = name->stringLength / 2;
      FT_Error          error;


      if ( !FT_ALLOC( result, name->stringLength + 1 ) )
      {
        FT_Stream   stream = face->name_table.stream;
        FT_String*  r      = (FT_String*)result;
        FT_Byte*    p      = (FT_Byte*)name->string;


        if ( FT_STREAM_SEEK( name->stringOffset ) ||
             FT_FRAME_ENTER( name->stringLength ) )
        {
          FT_FREE( result );
          name->stringLength = 0;
          name->stringOffset = 0;
          FT_FREE( name->string );

          goto Exit;
        }

        p = (FT_Byte*)stream->cursor;

        for ( ; len > 0; len--, p += 2 )
        {
          if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
            *r++ = p[1];
        }
        *r = '\0';

        FT_FRAME_EXIT();
      }
      goto Exit;
    }

    if ( found_apple != -1 )
    {
      FT_Memory         memory = face->root.memory;
      TT_NameEntryRec*  name   = face->name_table.names + found_apple;
      FT_UInt           len    = name->stringLength;
      FT_Error          error;


      if ( !FT_ALLOC( result, len + 1 ) )
      {
        FT_Stream  stream = face->name_table.stream;


        if ( FT_STREAM_SEEK( name->stringOffset ) ||
             FT_STREAM_READ( result, len )        )
        {
          name->stringOffset = 0;
          name->stringLength = 0;
          FT_FREE( name->string );
          FT_FREE( result );
          goto Exit;
        }
        ((char*)result)[len] = '\0';
      }
    }

  Exit:
    face->root.internal->postscript_name = result;
    return result;
  }
Example #19
0
  TT_CharMap_Load( TT_Face       face,
                   TT_CMapTable  cmap,
                   FT_Stream     stream )
  {
    FT_Error     error;
    FT_Memory    memory;
    FT_UShort    num_SH, num_Seg, i;
    FT_ULong     j, n;

    FT_UShort    u, l;

    TT_CMap0     cmap0;
    TT_CMap2     cmap2;
    TT_CMap4     cmap4;
    TT_CMap6     cmap6;
    TT_CMap8_12  cmap8_12;
    TT_CMap10    cmap10;

    TT_CMap2SubHeader  cmap2sub;
    TT_CMap4Segment    segments;
    TT_CMapGroup       groups;


    if ( cmap->loaded )
      return SFNT_Err_Ok;

    memory = stream->memory;

    if ( FT_STREAM_SEEK( cmap->offset ) )
      return error;

    switch ( cmap->format )
    {
    case 0:
      cmap0 = &cmap->c.cmap0;

      if ( FT_READ_USHORT( cmap0->language )           ||
           FT_ALLOC( cmap0->glyphIdArray, 256L )       ||
           FT_STREAM_READ( cmap0->glyphIdArray, 256L ) )
        goto Fail;

      cmap->get_index     = code_to_index0;
      cmap->get_next_char = code_to_next0;
      break;

    case 2:
      num_SH = 0;
      cmap2  = &cmap->c.cmap2;

      /* allocate subheader keys */

      if ( FT_NEW_ARRAY( cmap2->subHeaderKeys, 256 ) ||
           FT_FRAME_ENTER( 2L + 512L )               )
        goto Fail;

      cmap2->language = FT_GET_USHORT();

      for ( i = 0; i < 256; i++ )
      {
        u = (FT_UShort)( FT_GET_USHORT() / 8 );
        cmap2->subHeaderKeys[i] = u;

        if ( num_SH < u )
          num_SH = u;
      }

      FT_FRAME_EXIT();

      /* load subheaders */

      cmap2->numGlyphId = l = (FT_UShort)(
        ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFFU ) / 2 );

      if ( FT_NEW_ARRAY( cmap2->subHeaders, num_SH + 1 ) ||
           FT_FRAME_ENTER( ( num_SH + 1 ) * 8L )         )
      {
        FT_FREE( cmap2->subHeaderKeys );
        goto Fail;
      }

      cmap2sub = cmap2->subHeaders;

      for ( i = 0; i <= num_SH; i++ )
      {
        cmap2sub->firstCode     = FT_GET_USHORT();
        cmap2sub->entryCount    = FT_GET_USHORT();
        cmap2sub->idDelta       = FT_GET_SHORT();
        /* we apply the location offset immediately */
        cmap2sub->idRangeOffset = (FT_UShort)(
          FT_GET_USHORT() - ( num_SH - i ) * 8 - 2 );

        cmap2sub++;
      }

      FT_FRAME_EXIT();

      /* load glyph IDs */

      if ( FT_NEW_ARRAY( cmap2->glyphIdArray, l ) ||
           FT_FRAME_ENTER( l * 2L )               )
      {
        FT_FREE( cmap2->subHeaders );
        FT_FREE( cmap2->subHeaderKeys );
        goto Fail;
      }

      for ( i = 0; i < l; i++ )
        cmap2->glyphIdArray[i] = FT_GET_USHORT();

      FT_FRAME_EXIT();

      cmap->get_index = code_to_index2;
      cmap->get_next_char = code_to_next2;
      break;

    case 4:
      cmap4 = &cmap->c.cmap4;

      /* load header */

      if ( FT_FRAME_ENTER( 10L ) )
        goto Fail;

      cmap4->language      = FT_GET_USHORT();
      cmap4->segCountX2    = FT_GET_USHORT();
      cmap4->searchRange   = FT_GET_USHORT();
      cmap4->entrySelector = FT_GET_USHORT();
      cmap4->rangeShift    = FT_GET_USHORT();

      num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 );

      FT_FRAME_EXIT();

      /* load segments */

      if ( FT_NEW_ARRAY( cmap4->segments, num_Seg )   ||
           FT_FRAME_ENTER( ( num_Seg * 4 + 1 ) * 2L ) )
        goto Fail;

      segments = cmap4->segments;

      for ( i = 0; i < num_Seg; i++ )
        segments[i].endCount = FT_GET_USHORT();

      (void)FT_GET_USHORT();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].startCount = FT_GET_USHORT();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].idDelta = FT_GET_SHORT();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].idRangeOffset = FT_GET_USHORT();

      FT_FRAME_EXIT();

      cmap4->numGlyphId = l = (FT_UShort)(
        ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFFU ) / 2 );

      /* load IDs */

      if ( FT_NEW_ARRAY( cmap4->glyphIdArray, l ) ||
           FT_FRAME_ENTER( l * 2L )               )
      {
        FT_FREE( cmap4->segments );
        goto Fail;
      }

      for ( i = 0; i < l; i++ )
        cmap4->glyphIdArray[i] = FT_GET_USHORT();

      FT_FRAME_EXIT();

      cmap4->last_segment = cmap4->segments;

      cmap->get_index     = code_to_index4;
      cmap->get_next_char = code_to_next4;
      break;

    case 6:
      cmap6 = &cmap->c.cmap6;

      if ( FT_FRAME_ENTER( 6L ) )
        goto Fail;

      cmap6->language   = FT_GET_USHORT();
      cmap6->firstCode  = FT_GET_USHORT();
      cmap6->entryCount = FT_GET_USHORT();

      FT_FRAME_EXIT();

      l = cmap6->entryCount;

      if ( FT_NEW_ARRAY( cmap6->glyphIdArray, l ) ||
           FT_FRAME_ENTER( l * 2L )               )
        goto Fail;

      for ( i = 0; i < l; i++ )
        cmap6->glyphIdArray[i] = FT_GET_USHORT();

      FT_FRAME_EXIT();
      cmap->get_index     = code_to_index6;
      cmap->get_next_char = code_to_next6;
      break;

    case 8:
    case 12:
      cmap8_12 = &cmap->c.cmap8_12;

      if ( FT_FRAME_ENTER( 8L ) )
        goto Fail;

      cmap->length       = FT_GET_ULONG();
      cmap8_12->language = FT_GET_ULONG();

      FT_FRAME_EXIT();

      if ( cmap->format == 8 )
        if ( FT_STREAM_SKIP( 8192L ) )
          goto Fail;

      if ( FT_READ_ULONG( cmap8_12->nGroups ) )
        goto Fail;

      n = cmap8_12->nGroups;

      if ( FT_NEW_ARRAY( cmap8_12->groups, n ) ||
           FT_FRAME_ENTER( n * 3 * 4L )        )
        goto Fail;

      groups = cmap8_12->groups;

      for ( j = 0; j < n; j++ )
      {
        groups[j].startCharCode = FT_GET_ULONG();
        groups[j].endCharCode   = FT_GET_ULONG();
        groups[j].startGlyphID  = FT_GET_ULONG();
      }

      FT_FRAME_EXIT();

      cmap8_12->last_group = cmap8_12->groups;

      cmap->get_index     = code_to_index8_12;
      cmap->get_next_char = code_to_next8_12;
      break;

    case 10:
      cmap10 = &cmap->c.cmap10;

      if ( FT_FRAME_ENTER( 16L ) )
        goto Fail;

      cmap->length          = FT_GET_ULONG();
      cmap10->language      = FT_GET_ULONG();
      cmap10->startCharCode = FT_GET_ULONG();
      cmap10->numChars      = FT_GET_ULONG();

      FT_FRAME_EXIT();

      n = cmap10->numChars;

      if ( FT_NEW_ARRAY( cmap10->glyphs, n ) ||
           FT_FRAME_ENTER( n * 2L )          )
        goto Fail;

      for ( j = 0; j < n; j++ )
        cmap10->glyphs[j] = FT_GET_USHORT();

      FT_FRAME_EXIT();
      cmap->get_index     = code_to_index10;
      cmap->get_next_char = code_to_next10;
      break;

    default:   /* corrupt character mapping table */
      return SFNT_Err_Invalid_CharMap_Format;

    }

    return SFNT_Err_Ok;

  Fail:
    TT_CharMap_Free( face, cmap );
    return error;
  }