⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 afmparse.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
             AFM_STATUS_EOC( stream )  )
          continue;

        break;
      }
    }

    if ( len )
      *len = ( key ) ? AFM_STREAM_KEY_LEN( stream, key )
                     : 0;

    return key;
  }


  static AFM_Token
  afm_tokenize( const char*  key,
                FT_UInt      len )
  {
    int  n;


    for ( n = 0; n < N_AFM_TOKENS; n++ )
    {
      if ( *( afm_key_table[n] ) == *key )
      {
        for ( ; n < N_AFM_TOKENS; n++ )
        {
          if ( *( afm_key_table[n] ) != *key )
            return AFM_TOKEN_UNKNOWN;

          if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
            return (AFM_Token) n;
        }
      }
    }

    return AFM_TOKEN_UNKNOWN;
  }


  FT_LOCAL_DEF( FT_Error )
  afm_parser_init( AFM_Parser  parser,
                   FT_Memory   memory,
                   FT_Byte*    base,
                   FT_Byte*    limit )
  {
    AFM_Stream  stream;
    FT_Error    error;


    if ( FT_NEW( stream ) )
      return error;

    stream->cursor = stream->base = base;
    stream->limit  = limit;

    /* don't skip the first line during the first call */
    stream->status = AFM_STREAM_STATUS_EOL;

    parser->memory    = memory;
    parser->stream    = stream;
    parser->FontInfo  = NULL;
    parser->get_index = NULL;

    return PSaux_Err_Ok;
  }


  FT_LOCAL( void )
  afm_parser_done( AFM_Parser  parser )
  {
    FT_Memory  memory = parser->memory;


    FT_FREE( parser->stream );
  }


  FT_LOCAL_DEF( FT_Error )
  afm_parser_read_int( AFM_Parser  parser,
                       FT_Int*     aint )
  {
    AFM_ValueRec  val;


    val.type = AFM_VALUE_TYPE_INTEGER;

    if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
    {
      *aint = val.u.i;

      return PSaux_Err_Ok;
    }
    else
      return PSaux_Err_Syntax_Error;
  }


  static FT_Error
  afm_parse_track_kern( AFM_Parser  parser )
  {
    AFM_FontInfo   fi = parser->FontInfo;
    AFM_TrackKern  tk;
    char*          key;
    FT_UInt        len;
    int            n = -1;


    if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
        goto Fail;

    if ( fi->NumTrackKern )
    {
      FT_Memory  memory = parser->memory;
      FT_Error   error;


      if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
        return error;
    }

    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
    {
      AFM_ValueRec  shared_vals[5];


      switch ( afm_tokenize( key, len ) )
      {
      case AFM_TOKEN_TRACKKERN:
        n++;

        if ( n >= fi->NumTrackKern )
          goto Fail;

        tk = fi->TrackKerns + n;

        shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
        shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
        shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
        shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
        shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
        if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
          goto Fail;

        tk->degree     = shared_vals[0].u.i;
        tk->min_ptsize = shared_vals[1].u.f;
        tk->min_kern   = shared_vals[2].u.f;
        tk->max_ptsize = shared_vals[3].u.f;
        tk->max_kern   = shared_vals[4].u.f;

        /* is this correct? */
        if ( tk->degree < 0 && tk->min_kern > 0 )
          tk->min_kern = -tk->min_kern;
        break;

      case AFM_TOKEN_ENDTRACKKERN:
      case AFM_TOKEN_ENDKERNDATA:
      case AFM_TOKEN_ENDFONTMETRICS:
        fi->NumTrackKern = n + 1;
        return PSaux_Err_Ok;
        break;

      case AFM_TOKEN_UNKNOWN:
        break;

      default:
        goto Fail;
        break;
      }
    }

  Fail:
    return PSaux_Err_Syntax_Error;
  }


#undef  KERN_INDEX
#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )


  /* compare two kerning pairs */
  FT_CALLBACK_DEF( int )
  afm_compare_kern_pairs( const void*  a,
                          const void*  b )
  {
    AFM_KernPair  kp1 = (AFM_KernPair)a;
    AFM_KernPair  kp2 = (AFM_KernPair)b;

    FT_ULong  index1 = KERN_INDEX( kp1->index1, kp1->index2 );
    FT_ULong  index2 = KERN_INDEX( kp2->index1, kp2->index2 );


    return (int)( index1 - index2 );
  }


  static FT_Error
  afm_parse_kern_pairs( AFM_Parser  parser )
  {
    AFM_FontInfo  fi = parser->FontInfo;
    AFM_KernPair  kp;
    char*         key;
    FT_UInt       len;
    int           n = -1;


    if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
      goto Fail;

    if ( fi->NumKernPair )
    {
      FT_Memory  memory = parser->memory;
      FT_Error   error;


      if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
        return error;
    }

    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
    {
      AFM_Token  token = afm_tokenize( key, len );


      switch ( token )
      {
      case AFM_TOKEN_KP:
      case AFM_TOKEN_KPX:
      case AFM_TOKEN_KPY:
        {
          FT_Int        r;
          AFM_ValueRec  shared_vals[4];


          n++;

          if ( n >= fi->NumKernPair )
            goto Fail;

          kp = fi->KernPairs + n;

          shared_vals[0].type = AFM_VALUE_TYPE_INDEX;
          shared_vals[1].type = AFM_VALUE_TYPE_INDEX;
          shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;
          shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
          r = afm_parser_read_vals( parser, shared_vals, 4 );
          if ( r < 3 )
            goto Fail;

          kp->index1 = shared_vals[0].u.i;
          kp->index2 = shared_vals[1].u.i;
          if ( token == AFM_TOKEN_KPY )
          {
            kp->x = 0;
            kp->y = shared_vals[2].u.i;
          }
          else
          {
            kp->x = shared_vals[2].u.i;
            kp->y = ( token == AFM_TOKEN_KP && r == 4 )
                      ? shared_vals[3].u.i : 0;
          }
        }
        break;

      case AFM_TOKEN_ENDKERNPAIRS:
      case AFM_TOKEN_ENDKERNDATA:
      case AFM_TOKEN_ENDFONTMETRICS:
        fi->NumKernPair = n + 1;
        ft_qsort( fi->KernPairs, fi->NumKernPair,
                  sizeof( AFM_KernPairRec ),
                  afm_compare_kern_pairs );
        return PSaux_Err_Ok;

      case AFM_TOKEN_UNKNOWN:
        break;

      default:
        goto Fail;
        break;
      }
    }

  Fail:
    return PSaux_Err_Syntax_Error;
  }


  static FT_Error
  afm_parse_kern_data( AFM_Parser  parser )
  {
    FT_Error  error;
    char*     key;
    FT_UInt   len;


    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
    {
      switch ( afm_tokenize( key, len ) )
      {
      case AFM_TOKEN_STARTTRACKKERN:
        error = afm_parse_track_kern( parser );
        if ( error )
          return error;
        break;

      case AFM_TOKEN_STARTKERNPAIRS:
      case AFM_TOKEN_STARTKERNPAIRS0:
        error = afm_parse_kern_pairs( parser );
        if ( error )
          return error;
        break;

      case AFM_TOKEN_ENDKERNDATA:
      case AFM_TOKEN_ENDFONTMETRICS:
        return PSaux_Err_Ok;

      case AFM_TOKEN_UNKNOWN:
        break;

      default:
        goto Fail;
        break;
      }
    }

  Fail:
    return PSaux_Err_Syntax_Error;
  }


  static FT_Error
  afm_parser_skip_section( AFM_Parser  parser,
                           FT_UInt     n,
                           AFM_Token   end_section )
  {
    char*    key;
    FT_UInt  len;


    while ( n-- > 0 )
    {
      key = afm_parser_next_key( parser, 1, NULL );
      if ( !key )
        goto Fail;
    }

    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
    {
      AFM_Token  token = afm_tokenize( key, len );


      if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
        return PSaux_Err_Ok;
    }

  Fail:
    return PSaux_Err_Syntax_Error;
  }


  FT_LOCAL_DEF( FT_Error )
  afm_parser_parse( AFM_Parser  parser )
  {
    FT_Memory     memory = parser->memory;
    AFM_FontInfo  fi     = parser->FontInfo;
    FT_Error      error  = PSaux_Err_Syntax_Error;
    char*         key;
    FT_UInt       len;
    FT_Int        metrics_sets = 0;


    if ( !fi )
      return PSaux_Err_Invalid_Argument;

    key = afm_parser_next_key( parser, 1, &len );
    if ( !key || len != 16                              ||
         ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )
      return PSaux_Err_Unknown_File_Format;

    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
    {
      AFM_ValueRec  shared_vals[4];


      switch ( afm_tokenize( key, len ) )
      {
      case AFM_TOKEN_METRICSSETS:
        if ( afm_parser_read_int( parser, &metrics_sets ) )
          goto Fail;

        if ( metrics_sets != 0 && metrics_sets != 2 )
        {
          error = PSaux_Err_Unimplemented_Feature;

          goto Fail;
        }
        break;

      case AFM_TOKEN_ISCIDFONT:
        shared_vals[0].type = AFM_VALUE_TYPE_BOOL;
        if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
          goto Fail;

        fi->IsCIDFont = shared_vals[0].u.b;
        break;

      case AFM_TOKEN_FONTBBOX:
        shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
        shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
        shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
        shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
        if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )
          goto Fail;

        fi->FontBBox.xMin = shared_vals[0].u.f;
        fi->FontBBox.yMin = shared_vals[1].u.f;
        fi->FontBBox.xMax = shared_vals[2].u.f;
        fi->FontBBox.yMax = shared_vals[3].u.f;
        break;

      case AFM_TOKEN_ASCENDER:
        shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
        if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
          goto Fail;

        fi->Ascender = shared_vals[0].u.f;
        break;

      case AFM_TOKEN_DESCENDER:
        shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
        if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
          goto Fail;

        fi->Descender = shared_vals[0].u.f;
        break;

      case AFM_TOKEN_STARTCHARMETRICS:
        {
          FT_Int  n;


          if ( afm_parser_read_int( parser, &n ) )
            goto Fail;

          error = afm_parser_skip_section( parser, n,
                                           AFM_TOKEN_ENDCHARMETRICS );
          if ( error )
            return error;
        }
        break;

      case AFM_TOKEN_STARTKERNDATA:
        error = afm_parse_kern_data( parser );
        if ( error )
          goto Fail;
        /* fall through since we only support kern data */

      case AFM_TOKEN_ENDFONTMETRICS:
        return PSaux_Err_Ok;
        break;

      default:
        break;
      }
    }

  Fail:
    FT_FREE( fi->TrackKerns );
    fi->NumTrackKern = 0;

    FT_FREE( fi->KernPairs );
    fi->NumKernPair = 0;

    fi->IsCIDFont = 0;

    return error;
  }


/* END */

⌨️ 快捷键说明

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