psobjs.c

来自「一个类似windows」· C语言 代码 · 共 1,794 行 · 第 1/4 页

C
1,794
字号

  FT_LOCAL_DEF( void )
  ps_parser_skip_PS_token( PS_Parser  parser )
  {
    /* Note: PostScript allows any non-delimiting, non-whitespace        */
    /*       character in a name (PS Ref Manual, 3rd ed, p31).           */
    /*       PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */

    FT_Byte*  cur   = parser->cursor;
    FT_Byte*  limit = parser->limit;


    skip_spaces( &cur, limit );             /* this also skips comments */
    if ( cur >= limit )
      goto Exit;

    /* self-delimiting, single-character tokens */
    if ( *cur == '[' || *cur == ']' ||
         *cur == '{' || *cur == '}' )
    {
      cur++;
      goto Exit;
    }

    if ( *cur == '(' )                              /* (...) */
    {
      skip_literal_string( &cur, limit );
      goto Exit;
    }

    if ( *cur == '<' )                              /* <...> */
    {
      if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
      {
        cur++;
        cur++;
        goto Exit;
      }
      parser->cursor = cur;
      skip_string( parser );
      return;
    }

    if ( *cur == '>' )
    {
      cur++;
      if ( cur >= limit || *cur != '>' )             /* >> */
      {
        FT_ERROR(( "ps_parser_skip_PS_token: "
                   "unexpected closing delimiter `>'\n" ));
        parser->error = PSaux_Err_Invalid_File_Format;
        goto Exit;
      }
      cur++;
      goto Exit;
    }

    if ( *cur == '/' )
      cur++;

    /* anything else */
    while ( cur < limit )
    {
      if ( IS_T1_SPACE( *cur )        ||
           *cur == '('                ||
           *cur == '/'                ||
           *cur == '%'                ||
           *cur == '[' || *cur == ']' ||
           *cur == '{' || *cur == '}' ||
           *cur == '<' || *cur == '>' )
        break;

      if ( *cur == ')' )
      {
        FT_ERROR(( "ps_parser_skip_PS_token: "
                   "unexpected closing delimiter `)'\n" ));
        parser->error = PSaux_Err_Invalid_File_Format;
        goto Exit;
      }

      cur++;
    }

  Exit:
    parser->cursor = cur;
  }


  FT_LOCAL_DEF( void )
  ps_parser_skip_spaces( PS_Parser  parser )
  {
    skip_spaces( &parser->cursor, parser->limit );
  }


  /* `token' here means either something between balanced delimiters */
  /* or the next token; the delimiters are not removed.              */

  FT_LOCAL_DEF( void )
  ps_parser_to_token( PS_Parser  parser,
                      T1_Token   token )
  {
    FT_Byte*  cur;
    FT_Byte*  limit;
    FT_Byte   starter, ender;
    FT_Int    embed;


    token->type  = T1_TOKEN_TYPE_NONE;
    token->start = 0;
    token->limit = 0;

    /* first of all, skip leading whitespace */
    ps_parser_skip_spaces( parser );

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

    if ( cur >= limit )
      return;

    switch ( *cur )
    {
      /************* check for literal string *****************/
    case '(':
      token->type  = T1_TOKEN_TYPE_STRING;
      token->start = cur;
      skip_literal_string( &cur, limit );
      if ( cur < limit )
        token->limit = cur;
      break;

      /************* check for programs/array *****************/
    case '{':
      token->type = T1_TOKEN_TYPE_ARRAY;
      ender = '}';
      goto Lookup_Ender;

      /************* check for table/array ********************/
    case '[':
      token->type = T1_TOKEN_TYPE_ARRAY;
      ender = ']';
      /* fall through */

    Lookup_Ender:
      embed        = 1;
      starter      = *cur;
      token->start = cur++;

      /* we need this to catch `[ ]' */
      parser->cursor = cur;
      ps_parser_skip_spaces( parser );
      cur = parser->cursor;

      while ( cur < limit && !parser->error )
      {
        if ( *cur == starter )
          embed++;
        else if ( *cur == ender )
        {
          embed--;
          if ( embed <= 0 )
          {
            token->limit = ++cur;
            break;
          }
        }

        parser->cursor = cur;
        ps_parser_skip_PS_token( parser );
        /* we need this to catch `[XXX ]' */
        ps_parser_skip_spaces  ( parser );
        cur = parser->cursor;
      }
      break;

      /* ************ otherwise, it is any token **************/
    default:
      token->start = cur;
      token->type  = T1_TOKEN_TYPE_ANY;
      ps_parser_skip_PS_token( parser );
      cur = parser->cursor;
      if ( !parser->error )
        token->limit = cur;
    }

    if ( !token->limit )
    {
      token->start = 0;
      token->type  = T1_TOKEN_TYPE_NONE;
    }

    parser->cursor = cur;
  }


  FT_LOCAL_DEF( void )
  ps_parser_to_token_array( PS_Parser  parser,
                            T1_Token   tokens,
                            FT_UInt    max_tokens,
                            FT_Int*    pnum_tokens )
  {
    T1_TokenRec  master;


    *pnum_tokens = -1;

    /* this also handles leading whitespace */
    ps_parser_to_token( parser, &master );

    if ( master.type == T1_TOKEN_TYPE_ARRAY )
    {
      FT_Byte*  old_cursor = parser->cursor;
      FT_Byte*  old_limit  = parser->limit;
      T1_Token  cur        = tokens;
      T1_Token  limit      = cur + max_tokens;


      /* don't include outermost delimiters */
      parser->cursor = master.start + 1;
      parser->limit  = master.limit - 1;

      while ( parser->cursor < parser->limit )
      {
        T1_TokenRec  token;


        ps_parser_to_token( parser, &token );
        if ( !token.type )
          break;

        if ( cur < limit )
          *cur = token;

        cur++;
      }

      *pnum_tokens = (FT_Int)( cur - tokens );

      parser->cursor = old_cursor;
      parser->limit  = old_limit;
    }
  }


  /* first character must be already part of the number */

  static FT_Long
  ps_radix( FT_Long    radixBase,
            FT_Byte*  *acur,
            FT_Byte*   limit )
  {
    FT_Long   result = 0;
    FT_Byte*  cur    = *acur;


    if ( radixBase < 2 || radixBase > 36 )
      return 0;

    while ( cur < limit )
    {
      int  d;


      if ( *cur OP 0x80 )
        break;

      d = ft_char_table[*cur & 0x7F];
      if ( d < 0 || d >= radixBase )
        break;

      result = result * radixBase + d;

      cur++;
    }

    *acur = cur;

    return result;
  }


  /* first character must be already part of the number */

  static FT_Long
  ps_toint( FT_Byte*  *acur,
            FT_Byte*   limit )
  {
    FT_Long   result = 0;
    FT_Byte*  cur    = *acur;
    FT_Byte   c;


    if ( cur >= limit )
      goto Exit;

    c = *cur;
    if ( c == '-' )
      cur++;

    while ( cur < limit )
    {
      int  d;


      if ( *cur == '#' )
      {
        cur++;
        result = ps_radix( result, &cur, limit );
        break;
      }

      if ( *cur OP 0x80 )
        break;

      d = ft_char_table[*cur & 0x7F];
      if ( d < 0 || d >= 10 )
        break;
      result = result * 10 + d;

      cur++;
    };

    if ( c == '-' )
      result = -result;

  Exit:
    *acur = cur;
    return result;
  }


  /* first character must be `<' if `delimiters' is non-zero */

  static FT_Error
  ps_tobytes( FT_Byte*  *acur,
              FT_Byte*   limit,
              FT_Long    max_bytes,
              FT_Byte*   bytes,
              FT_Long*   pnum_bytes,
              FT_Bool    delimiters )
  {
    FT_Error  error = PSaux_Err_Ok;

    FT_Byte*  cur = *acur;
    FT_Long   n   = 0;


    if ( cur >= limit )
      goto Exit;

    if ( delimiters )
    {
      if ( *cur != '<' )
      {
        FT_ERROR(( "ps_tobytes: Missing starting delimiter `<'\n" ));
        error = PSaux_Err_Invalid_File_Format;
        goto Exit;
      }

      cur++;
    }

    max_bytes = max_bytes * 2;

    for ( n = 0; cur < limit; n++, cur++ )
    {
      int  d;


      if ( n >= max_bytes )
        /* buffer is full */
        goto Exit;

      /* All whitespace characters are ignored. */
      skip_spaces( &cur, limit );
      if ( cur >= limit )
        break;

      if ( *cur OP 0x80 )
        break;

      d = ft_char_table[*cur & 0x7F];
      if ( d < 0 || d >= 16 )
        break;

      /* <f> == <f0> != <0f> */
      bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + d
                                          : d * 16 );
    }

    if ( delimiters )
    {
      if ( cur < limit && *cur != '>' )
      {
        FT_ERROR(( "ps_tobytes: Missing closing delimiter `>'\n" ));
        error = PSaux_Err_Invalid_File_Format;
        goto Exit;
      }

      cur++;
    }

    *acur = cur;

  Exit:
    *pnum_bytes = ( n + 1 ) / 2;

    return error;
  }


  /* first character must be already part of the number */

  static FT_Long
  ps_tofixed( FT_Byte*  *acur,
              FT_Byte*   limit,
              FT_Long    power_ten )
  {
    FT_Byte*  cur  = *acur;
    FT_Long   num, divider, result;
    FT_Int    sign = 0;


    if ( cur >= limit )
      return 0;

    /* first of all, check the sign */
    if ( *cur == '-' && cur + 1 < limit )
    {
      sign = 1;
      cur++;
    }

    /* then, read the integer part, if any */
    if ( *cur != '.' )
      result = ps_toint( &cur, limit ) << 16;
    else
      result = 0;

    num     = 0;
    divider = 1;

    if ( cur >= limit )
      goto Exit;

    /* read decimal part, if any */
    if ( *cur == '.' && cur + 1 < limit )
    {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?