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

📄 ftvalid.c

📁 Ftee type Demo for Linux open source
💻 C
字号:
/****************************************************************************/
/*                                                                          */
/*  The FreeType project -- a free and portable quality font engine         */
/*                                                                          */
/*  Copyright 2005 by                                                       */
/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
/*                                                                          */
/*  ftvalid: Validates layout related tables of OpenType.  This program     */
/*           calls `FT_OpenType_Validate' on a given file, and reports      */
/*           the validation result.                                         */
/*                                                                          */
/*  written by YAMATO Masatake and SUZUKI Toshiya.                          */
/*                                                                          */
/****************************************************************************/


#include <ft2build.h>

#include FT_FREETYPE_H
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_VALIDATE_H
#include FT_TRUETYPE_TABLES_H
#include FT_TRUETYPE_TAGS_H
#include FT_INTERNAL_MEMORY_H
#include FT_INTERNAL_OBJECTS_H

#include FT_OPENTYPE_VALIDATE_H


#include "common.h"


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


  static char*  execname;
  
  typedef struct  TableSpecRec_
  {
    FT_UInt  tag;
    FT_UInt  validation_flag;

  } TableSpecRec, *TableSpec;


  typedef enum 
  { 
#define OT_VALIDATOR_SYMBOL "ot" 
    OT_VALIDATE = 0,

  } ValidatorType;

  static const char*  validator_symbols[] = { OT_VALIDATOR_SYMBOL, };

  static ValidatorType  validator;

  
#define MAKE_TABLE_SPEC( x ) { TTAG_##x, FT_VALIDATE_##x }

  static const TableSpecRec  ot_table_spec[] = 
  {
    MAKE_TABLE_SPEC( BASE ),
    MAKE_TABLE_SPEC( GDEF ),
    MAKE_TABLE_SPEC( GPOS ),
    MAKE_TABLE_SPEC( GSUB ),
    MAKE_TABLE_SPEC( JSTF ),
  };
#define N_OT_TABLE_SPEC  ( sizeof ( ot_table_spec ) / sizeof ( TableSpecRec ) )


  static void
  panic( int          error,
         const char*  message )
  {
    fprintf( stderr, "%s\n  error = 0x%04x\n", message, error );
    exit( 1 );
  }


  static char*
  make_tag_chararray ( char     chararray[4],
                       FT_UInt  tag )
  {
    chararray[0] = (char)( ( tag >> 24 ) & 0xFF );
    chararray[1] = (char)( ( tag >> 16 ) & 0xFF );
    chararray[2] = (char)( ( tag >> 8  ) & 0xFF );
    chararray[3] = (char)( ( tag >> 0  ) & 0xFF );
    return chararray;
  }


  static void
  print_tag ( FILE*    stream,
              FT_UInt  tag )
  {
    char  buffer[5];


    buffer[4] = '\0';
    fprintf( stream, "%s", make_tag_chararray( buffer, tag ) );
  }


  static void
  print_usage( void )
  {
    unsigned int i;


    fprintf( stderr, "\n" );
    fprintf( stderr, "ftvalid: layout table validator -- part of the FreeType project\n" );
    fprintf( stderr, "---------------------------------------------------------------\n" );
    fprintf( stderr, "\n" );
    fprintf( stderr, "Usage: %s [options] fontfile\n", execname );
    fprintf( stderr, "\n" );
    fprintf( stderr, "  -t validator              select validator. \n");
    fprintf( stderr, "                            Currently only \"ot\" is available.\n" );
    fprintf( stderr, "\n" );
    fprintf( stderr, "  -T \"sfnt:tabl:enam:es  \"  select snft table names to be validated.\n" );
    fprintf( stderr, "                            `:' is for separating table names.\n" );
    fprintf( stderr, "                            Supported tables in ot validator are:\n" );

    fprintf( stderr, "                            " );

    for ( i = 0; i < N_OT_TABLE_SPEC; i++ )
    {
      print_tag( stderr, ot_table_spec[i].tag );
      fprintf( stderr, " " );
    }

    fprintf( stderr, "\n" );
    fprintf( stderr, "\n" );
    fprintf( stderr, "  -L                        list the layout related SFNT tables\n" );
    fprintf( stderr, "                            available in the font file. Choice of\n" );
    fprintf( stderr, "                            validator with -t option affects on the\n" );
    fprintf( stderr, "                            listing.\n" );
    fprintf( stderr, "\n" );
    fprintf( stderr, "  -v validation_level       validation level. \n" );
    fprintf( stderr, "                            validation_level = 0...2\n" );
    fprintf( stderr, "                            (0: default, 1: tight, 2: paranoid)\n" );

#if 0
    fprintf( stderr, "  -l trace_level            trace level for debug information.\n" );
    fprintf( stderr, "                            trace_level = 1...7\n" );
#endif /* 0 */

    fprintf( stderr, "-------------------------------------------------------------------\n" );
    fprintf( stderr, "\n" );
    fprintf( stderr, "Environment variable\n" );
    fprintf( stderr, "FT2_DEBUG: You can specify trace components and their levels[1-7]\n" );
    fprintf( stderr, "           to it like FT2_DEBUG=\"module1:level module2:level...\".\n" );
    fprintf( stderr, "           Available components for ot validator:\n" );
    fprintf( stderr, "           otvmodule otvcommon otvbase otvgdef otvgpos otvgsub otvjstf\n" );
    fprintf( stderr, "\n" );

    exit( 1 );
  }


  static FT_Error
  try_load( FT_Face   face,
            FT_ULong  tag )
  {
    FT_ULong  length;


    length = 0;
    return FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
  }


  static FT_UInt
  find_validation_flag( FT_UInt             tag,
                        const TableSpecRec  spec[],
                        int                 spec_count )
  {
    int i;


    for ( i = 0; i < spec_count; i++ )
    {
      if ( tag == spec[i].tag )
        return spec[i].validation_flag;
    }
    
    fprintf( stderr, "*** Wrong table name: " );
    print_tag( stderr, tag );
    fprintf( stderr, "\n" );

    print_usage();

    return 0;
  }


  static FT_UInt
  parse_table_specs( const char*         tables,
                     const TableSpecRec  spec[],
                     int                 spec_count )
  {
    FT_UInt  validation_flags;
    size_t   len;

    unsigned int  i;
    char          tag[4];
    

    validation_flags = 0;

    len = strlen( tables );
    if (( len % 5 ) != 4 )
    {
      fprintf( stderr, "*** Wrong length of table names\n" );
      print_usage();
    }
    
    for ( i = 0; i < len; i++ )
    {
      if ( ( ( i % 5 ) == 4 ) )
      {
        if ( tables[i] != ':' )
        {
          fprintf( stderr, "*** Wrong table separator: %c\n", tables[i] );
          print_usage();
        }
        i++;
      }

      tag[i % 5] = tables[i];
      if ( ( i % 5 ) == 3 )
        validation_flags |= find_validation_flag( FT_MAKE_TAG( tag[0],
                                                               tag[1],
                                                               tag[2],
                                                               tag[3] ), 
                                                  spec, 
                                                  spec_count );
    }

    return validation_flags;
  }


  static FT_UInt
  list_face_tables( FT_Face             face,
                    const TableSpecRec  spec[],
                    int                 spec_count )
  {
    FT_Error  error;

    FT_UInt  validation_flags;
    int      i;
    FT_UInt  tag;
    

    validation_flags = 0;
    
    for ( i = 0; i < spec_count; i++ )
    {
      tag   = spec[i].tag;
      error = try_load( face, tag );
      if ( error == 0 )
        validation_flags |= spec[i].validation_flag;
    }
    return validation_flags;
  }


  static FT_UInt
  make_table_specs( FT_Face             face,
                    const char*         request,
                    const TableSpecRec  spec[],
                    int                 spec_count )
  {
    if ( request == NULL || request[0] == '\0' )
      return list_face_tables ( face, spec, spec_count );
    else
      return parse_table_specs ( request, spec, spec_count );
  }


  static int
  print_tables( FILE*               stream,
                FT_UInt             validation_flags,
                const TableSpecRec  spec[],
                int                 spec_count )
  {
    int i;
    int n_print;
    

    for ( i = 0, n_print = 0; i < spec_count; i++ )
    {
      if ( spec[i].validation_flag & validation_flags )
      {
        if ( n_print != 0 )
          fprintf( stream, "%c", ':' );
        print_tag( stream, spec[i].tag );
        n_print++;
      }
    }
    
    fprintf( stream, "\n" );

    return !n_print;
  }


  static void
  report_header( FT_UInt             validation_flags,
                 const TableSpecRec  spec[],
                 int                 spec_count )
  {
    printf( "[%s:%s] validation targets: ",
            execname, validator_symbols[validator] );
    print_tables( stdout, validation_flags, spec, spec_count );
    printf( "-------------------------------------------------------------------\n" );
  }


  static void
  report_result( FT_Bytes            data[],
                 FT_UInt             validation_flags,
                 const TableSpecRec  spec[],
                 int                 spec_count )
  {
    int  i;
    int  n_passes;
    

    for ( i = 0, n_passes = 0; i < spec_count; i++ )
    {
      if ( ( spec[i].validation_flag & validation_flags ) &&
             data[i] != NULL                              )
      {
        printf( "[%s:%s] ", execname, validator_symbols[validator] );
        print_tag( stdout, spec[i].tag );
        fprintf( stdout, "...pass\n" );
        n_passes++;
      }
    }

    if ( n_passes == 0 )
    {
      printf( "[%s:%s] layout tables are not invalid.\n",
              execname, validator_symbols[validator] );
      printf( "[%s:%s] set FT2_DEBUG environment variable to \n",
              execname, validator_symbols[validator] );
      printf( "[%s:%s] know the validation detail. \n",
              execname, validator_symbols[validator] );
    }
  }


  /* 
   * OpenType related funtions
   */
  static int
  run_ot_validator( FT_Face      face,
                    const char*  tables,
                    int          validation_level )
  {
    FT_UInt       validation_flags;
    FT_Error      error;
    FT_Bytes      data[N_OT_TABLE_SPEC];
    unsigned int  i;
    FT_Memory     memory = FT_FACE_MEMORY( face );
    

    validation_flags  = validation_level;
    validation_flags |= make_table_specs( face, tables, ot_table_spec,
                                          N_OT_TABLE_SPEC );

    for ( i = 0; i < N_OT_TABLE_SPEC; i++ )
      data[i] = NULL;

    report_header( validation_flags, ot_table_spec, N_OT_TABLE_SPEC );

    error = FT_OpenType_Validate(
              face, 
              validation_flags, 
              &data[0], &data[1], &data[2], &data[3], &data[4] );
      
    report_result( data, validation_flags, ot_table_spec, N_OT_TABLE_SPEC );

    for ( i = 0; i < N_OT_TABLE_SPEC; i++ )
      FT_FREE( data[i] );

    return (int)error;
  }


  static int
  list_ot_tables( FT_Face  face )
  {
    FT_UInt  validation_flags;


    validation_flags = list_face_tables( face, ot_table_spec,
                                         N_OT_TABLE_SPEC );
    return print_tables( stdout, validation_flags, ot_table_spec,
                         N_OT_TABLE_SPEC );
  }


  /*
   * Main driver
   */

  int
  main( int     argc, 
        char**  argv )
  {
    char*  fontfile;
    int    option;
    int    status;

    char*  tables;
    int    dump_table_list;

    FT_ValidationLevel  validation_level;
#if 0
    int  trace_level;
#endif  /* 0 */
    
    execname = ft_basename( argv[0] );

    /*
     * Parsing options
     */
    validator        = OT_VALIDATE;
    tables           = NULL;
    dump_table_list  = 0;
    validation_level = FT_VALIDATE_DEFAULT;
#if 0
    trace_level      = 0;
#endif  /* 0 */

    while ( 1 )
    {
      option = getopt( argc, argv, "t:T:Lv:l:" );

      if ( option == -1 )
        break;
    
      switch ( option )
      {
      case 't':
        if ( strcmp( optarg, OT_VALIDATOR_SYMBOL ) == 0 )
          validator = OT_VALIDATE;
        else
        {
          fprintf( stderr, "*** Unknown validator name: %s\n", optarg );
          print_usage();
        }
        break;

      case 'T':
        tables = optarg;
        break;

      case 'L':
        dump_table_list = 1;
        break;

      case 'v':
        validation_level = (FT_ValidationLevel)atoi( optarg );
        if ( validation_level > FT_VALIDATE_PARANOID )
        {
          fprintf( stderr, "*** Validation level is out of range: %d\n",
                           validation_level );
          print_usage();
        }
        break;

      default:
        print_usage();
        break;
      }
    }

    argc -= optind;
    argv += optind;

    if ( argc == 0 )
    {
      fprintf(stderr, "*** Font file is not specified.\n");
      print_usage();
    }
    else if ( argc > 1 )
    {
      fprintf(stderr, "*** Too many font files.\n");
      print_usage();
    }

    fontfile = argv[0];

#if 0
    printf( "fontfile: %s\n",
            fontfile );
    printf( "validator type: %s\n",
            ( validator == OT_VALIDATE ) ? OT_VALIDATOR_SYMBOL : "unknown" );
    printf( "tables: %s\n",
            ( tables != NULL ) ? tables : "unspecified" );
    printf( "action: %s\n",
            ( dump_table_list == 1 ) ? "list" : "validate" );
    printf( "validation level: %d\n",
            validation_level );
#if 0
    printf( "trace level: %d\n", trace_level );
#endif /* 0 */
#endif /* 0 */


    /*
     * Run a validator
     */
    {
      FT_Library  library;
      FT_Face     face;
      FT_Error    error;


      status = 0;

      error = FT_Init_FreeType( &library );
      if ( error )
        panic ( error, "Could not initialize FreeType library" );

      /* TODO: Multiple faces in a font file? */
      error = FT_New_Face( library, fontfile, 0, &face );
      if ( error )
        panic( error, "Could not open face." );
      
      if ( validator == OT_VALIDATE )
      {
        if ( dump_table_list == 0 )
          status = run_ot_validator( face, tables, validation_level );
        else
          status = list_ot_tables  ( face );
      }
      /* ...More validator here */
      
      FT_Done_FreeType( library );
    }

    return status;
  }


/* End */

⌨️ 快捷键说明

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