📄 ftvalid.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 + -