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

📄 afmparse.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************/
/*                                                                         */
/*  afmparse.c                                                             */
/*                                                                         */
/*    AFM parser (body).                                                   */
/*                                                                         */
/*  Copyright 2006 by                                                      */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_INTERNAL_DEBUG_H

#include "afmparse.h"
#include "psconv.h"

#include "psauxerr.h"


/***************************************************************************/
/*                                                                         */
/*    AFM_Stream                                                           */
/*                                                                         */
/* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib.  */
/*                                                                         */
/*                                                                         */

  enum
  {
    AFM_STREAM_STATUS_NORMAL,
    AFM_STREAM_STATUS_EOC,
    AFM_STREAM_STATUS_EOL,
    AFM_STREAM_STATUS_EOF
  };


  typedef struct  AFM_StreamRec_
  {
    FT_Byte*  cursor;
    FT_Byte*  base;
    FT_Byte*  limit;

    FT_Int    status;

  } AFM_StreamRec;


#ifndef EOF
#define EOF -1
#endif


  /* this works because empty lines are ignored */
#define AFM_IS_NEWLINE( ch )  ( (ch) == '\r' || (ch) == '\n' )

#define AFM_IS_EOF( ch )      ( (ch) == EOF  || (ch) == '\x1a' )
#define AFM_IS_SPACE( ch )    ( (ch) == ' '  || (ch) == '\t' )

  /* column separator; there is no `column' in the spec actually */
#define AFM_IS_SEP( ch )      ( (ch) == ';' )

#define AFM_GETC()                                                       \
          ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
                                                   : EOF )

#define AFM_STREAM_KEY_BEGIN( stream )    \
          (char*)( (stream)->cursor - 1 )

#define AFM_STREAM_KEY_LEN( stream, key )       \
          ( (char*)(stream)->cursor - key - 1 )

#define AFM_STATUS_EOC( stream ) \
          ( (stream)->status >= AFM_STREAM_STATUS_EOC )

#define AFM_STATUS_EOL( stream ) \
          ( (stream)->status >= AFM_STREAM_STATUS_EOL )

#define AFM_STATUS_EOF( stream ) \
          ( (stream)->status >= AFM_STREAM_STATUS_EOF )


  static int
  afm_stream_skip_spaces( AFM_Stream  stream )
  {
    int  ch = 0;  /* make stupid compiler happy */


    if ( AFM_STATUS_EOC( stream ) )
      return ';';

    while ( 1 )
    {
      ch = AFM_GETC();
      if ( !AFM_IS_SPACE( ch ) )
        break;
    }

    if ( AFM_IS_NEWLINE( ch ) )
      stream->status = AFM_STREAM_STATUS_EOL;
    else if ( AFM_IS_SEP( ch ) )
      stream->status = AFM_STREAM_STATUS_EOC;
    else if ( AFM_IS_EOF( ch ) )
      stream->status = AFM_STREAM_STATUS_EOF;

    return ch;
  }


  /* read a key or value in current column */
  static char*
  afm_stream_read_one( AFM_Stream  stream )
  {
    char*  str;
    int    ch;


    afm_stream_skip_spaces( stream );
    if ( AFM_STATUS_EOC( stream ) )
      return NULL;

    str = AFM_STREAM_KEY_BEGIN( stream );

    while ( 1 )
    {
      ch = AFM_GETC();
      if ( AFM_IS_SPACE( ch ) )
        break;
      else if ( AFM_IS_NEWLINE( ch ) )
      {
        stream->status = AFM_STREAM_STATUS_EOL;
        break;
      }
      else if ( AFM_IS_SEP( ch ) )
      {
        stream->status = AFM_STREAM_STATUS_EOC;
        break;
      }
      else if ( AFM_IS_EOF( ch ) )
      {
        stream->status = AFM_STREAM_STATUS_EOF;
        break;
      }
    }

    return str;
  }


  /* read a string (i.e., read to EOL) */
  static char*
  afm_stream_read_string( AFM_Stream  stream )
  {
    char*  str;
    int    ch;


    afm_stream_skip_spaces( stream );
    if ( AFM_STATUS_EOL( stream ) )
      return NULL;

    str = AFM_STREAM_KEY_BEGIN( stream );

    /* scan to eol */
    while ( 1 )
    {
      ch = AFM_GETC();
      if ( AFM_IS_NEWLINE( ch ) )
      {
        stream->status = AFM_STREAM_STATUS_EOL;
        break;
      }
      else if ( AFM_IS_EOF( ch ) )
      {
        stream->status = AFM_STREAM_STATUS_EOF;
        break;
      }
    }

    return str;
  }


  /*************************************************************************/
  /*                                                                       */
  /*    AFM_Parser                                                         */
  /*                                                                       */
  /*                                                                       */

  /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
  typedef enum  AFM_Token_
  {
    AFM_TOKEN_ASCENDER,
    AFM_TOKEN_AXISLABEL,
    AFM_TOKEN_AXISTYPE,
    AFM_TOKEN_B,
    AFM_TOKEN_BLENDAXISTYPES,
    AFM_TOKEN_BLENDDESIGNMAP,
    AFM_TOKEN_BLENDDESIGNPOSITIONS,
    AFM_TOKEN_C,
    AFM_TOKEN_CC,
    AFM_TOKEN_CH,
    AFM_TOKEN_CAPHEIGHT,
    AFM_TOKEN_CHARWIDTH,
    AFM_TOKEN_CHARACTERSET,
    AFM_TOKEN_CHARACTERS,
    AFM_TOKEN_DESCENDER,
    AFM_TOKEN_ENCODINGSCHEME,
    AFM_TOKEN_ENDAXIS,
    AFM_TOKEN_ENDCHARMETRICS,
    AFM_TOKEN_ENDCOMPOSITES,
    AFM_TOKEN_ENDDIRECTION,
    AFM_TOKEN_ENDFONTMETRICS,
    AFM_TOKEN_ENDKERNDATA,
    AFM_TOKEN_ENDKERNPAIRS,
    AFM_TOKEN_ENDTRACKKERN,
    AFM_TOKEN_ESCCHAR,
    AFM_TOKEN_FAMILYNAME,
    AFM_TOKEN_FONTBBOX,
    AFM_TOKEN_FONTNAME,
    AFM_TOKEN_FULLNAME,
    AFM_TOKEN_ISBASEFONT,
    AFM_TOKEN_ISCIDFONT,
    AFM_TOKEN_ISFIXEDPITCH,
    AFM_TOKEN_ISFIXEDV,
    AFM_TOKEN_ITALICANGLE,
    AFM_TOKEN_KP,
    AFM_TOKEN_KPH,
    AFM_TOKEN_KPX,
    AFM_TOKEN_KPY,
    AFM_TOKEN_L,
    AFM_TOKEN_MAPPINGSCHEME,
    AFM_TOKEN_METRICSSETS,
    AFM_TOKEN_N,
    AFM_TOKEN_NOTICE,
    AFM_TOKEN_PCC,
    AFM_TOKEN_STARTAXIS,
    AFM_TOKEN_STARTCHARMETRICS,
    AFM_TOKEN_STARTCOMPOSITES,
    AFM_TOKEN_STARTDIRECTION,
    AFM_TOKEN_STARTFONTMETRICS,
    AFM_TOKEN_STARTKERNDATA,
    AFM_TOKEN_STARTKERNPAIRS,
    AFM_TOKEN_STARTKERNPAIRS0,
    AFM_TOKEN_STARTKERNPAIRS1,
    AFM_TOKEN_STARTTRACKKERN,
    AFM_TOKEN_STDHW,
    AFM_TOKEN_STDVW,
    AFM_TOKEN_TRACKKERN,
    AFM_TOKEN_UNDERLINEPOSITION,
    AFM_TOKEN_UNDERLINETHICKNESS,
    AFM_TOKEN_VV,
    AFM_TOKEN_VVECTOR,
    AFM_TOKEN_VERSION,
    AFM_TOKEN_W,
    AFM_TOKEN_W0,
    AFM_TOKEN_W0X,
    AFM_TOKEN_W0Y,
    AFM_TOKEN_W1,
    AFM_TOKEN_W1X,
    AFM_TOKEN_W1Y,
    AFM_TOKEN_WX,
    AFM_TOKEN_WY,
    AFM_TOKEN_WEIGHT,
    AFM_TOKEN_WEIGHTVECTOR,
    AFM_TOKEN_XHEIGHT,
    N_AFM_TOKENS,
    AFM_TOKEN_UNKNOWN

  } AFM_Token;


  static const char*  const afm_key_table[N_AFM_TOKENS] =
  {
    "Ascender",
    "AxisLabel",
    "AxisType",
    "B",
    "BlendAxisTypes",
    "BlendDesignMap",
    "BlendDesignPositions",
    "C",
    "CC",
    "CH",
    "CapHeight",
    "CharWidth",
    "CharacterSet",
    "Characters",
    "Descender",
    "EncodingScheme",
    "EndAxis",
    "EndCharMetrics",
    "EndComposites",
    "EndDirection",
    "EndFontMetrics",
    "EndKernData",
    "EndKernPairs",
    "EndTrackKern",
    "EscChar",
    "FamilyName",
    "FontBBox",
    "FontName",
    "FullName",
    "IsBaseFont",
    "IsCIDFont",
    "IsFixedPitch",
    "IsFixedV",
    "ItalicAngle",
    "KP",
    "KPH",
    "KPX",
    "KPY",
    "L",
    "MappingScheme",
    "MetricsSets",
    "N",
    "Notice",
    "PCC",
    "StartAxis",
    "StartCharMetrics",
    "StartComposites",
    "StartDirection",
    "StartFontMetrics",
    "StartKernData",
    "StartKernPairs",
    "StartKernPairs0",
    "StartKernPairs1",
    "StartTrackKern",
    "StdHW",
    "StdVW",
    "TrackKern",
    "UnderlinePosition",
    "UnderlineThickness",
    "VV",
    "VVector",
    "Version",
    "W",
    "W0",
    "W0X",
    "W0Y",
    "W1",
    "W1X",
    "W1Y",
    "WX",
    "WY",
    "Weight",
    "WeightVector",
    "XHeight"
  };


  /*
   * `afm_parser_read_vals' and `afm_parser_next_key' provide
   * high-level operations to an AFM_Stream.  The rest of the
   * parser functions should use them without accessing the
   * AFM_Stream directly.
   */

  FT_LOCAL_DEF( FT_Int )
  afm_parser_read_vals( AFM_Parser  parser,
                        AFM_Value   vals,
                        FT_Int      n )
  {
    AFM_Stream  stream = parser->stream;
    char*       str;
    FT_Int      i;


    if ( n > AFM_MAX_ARGUMENTS )
      return 0;

    for ( i = 0; i < n; i++ )
    {
      FT_UInt    len;
      AFM_Value  val = vals + i;


      if ( val->type == AFM_VALUE_TYPE_STRING )
        str = afm_stream_read_string( stream );
      else
        str = afm_stream_read_one( stream );

      if ( !str )
        break;

      len = AFM_STREAM_KEY_LEN( stream, str );

      switch ( val->type )
      {
      case AFM_VALUE_TYPE_STRING:
      case AFM_VALUE_TYPE_NAME:
        {
          FT_Memory  memory = parser->memory;
          FT_Error   error;


          if ( !FT_QALLOC( val->u.s, len + 1 ) )
          {
            ft_memcpy( val->u.s, str, len );
            val->u.s[len] = '\0';
          }
        }
        break;

      case AFM_VALUE_TYPE_FIXED:
        val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
                                    (FT_Byte*)str + len, 0 );
        break;

      case AFM_VALUE_TYPE_INTEGER:
        val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
                                  (FT_Byte*)str + len );
        break;

      case AFM_VALUE_TYPE_BOOL:
        val->u.b = FT_BOOL( len == 4                      &&
                            !ft_strncmp( str, "true", 4 ) );
        break;

      case AFM_VALUE_TYPE_INDEX:
        if ( parser->get_index )
          val->u.i = parser->get_index( str, len, parser->user_data );
        else
          val->u.i = 0;
        break;
      }
    }

    return i;
  }


  FT_LOCAL_DEF( char* )
  afm_parser_next_key( AFM_Parser  parser,
                       FT_Bool     line,
                       FT_UInt*    len )
  {
    AFM_Stream  stream = parser->stream;
    char*       key    = 0;  /* make stupid compiler happy */


    if ( line )
    {
      while ( 1 )
      {
        /* skip current line */
        if ( !AFM_STATUS_EOL( stream ) )
          afm_stream_read_string( stream );

        stream->status = AFM_STREAM_STATUS_NORMAL;
        key = afm_stream_read_one( stream );

        /* skip empty line */
        if ( !key                      &&
             !AFM_STATUS_EOF( stream ) &&
             AFM_STATUS_EOL( stream )  )
          continue;

        break;
      }
    }
    else
    {
      while ( 1 )
      {
        /* skip current column */
        while ( !AFM_STATUS_EOC( stream ) )
          afm_stream_read_one( stream );

        stream->status = AFM_STREAM_STATUS_NORMAL;
        key = afm_stream_read_one( stream );

        /* skip empty column */
        if ( !key                      &&
             !AFM_STATUS_EOF( stream ) &&

⌨️ 快捷键说明

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