📄 ftvalid.c
字号:
/****************************************************************************/
/* */
/* The FreeType project -- a free and portable quality font engine */
/* */
/* Copyright 2005, 2006 by */
/* D. Turner, R.Wilhelm, and W. Lemberg */
/* */
/* ftvalid: Validates layout related tables of OpenType and */
/* TrueTypeGX/AAT. This program calls `FT_OpenType_Validate', */
/* `FT_TrueTypeGX_Validate' or `FT_ClassicKern_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 FT_GX_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,
#define GX_VALIDATOR_SYMBOL "gx"
GX_VALIDATE,
#define CKERN_VALIDATOR_SYMBOL "ckern"
CKERN_VALIDATE,
} ValidatorType;
static const char* validator_symbols[] = { OT_VALIDATOR_SYMBOL,
GX_VALIDATOR_SYMBOL,
CKERN_VALIDATOR_SYMBOL,
NULL };
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 const TableSpecRec gx_table_spec[] =
{
MAKE_TABLE_SPEC( feat ),
MAKE_TABLE_SPEC( mort ),
MAKE_TABLE_SPEC( morx ),
MAKE_TABLE_SPEC( bsln ),
MAKE_TABLE_SPEC( just ),
MAKE_TABLE_SPEC( kern ),
MAKE_TABLE_SPEC( opbd ),
MAKE_TABLE_SPEC( trak ),
MAKE_TABLE_SPEC( prop ),
MAKE_TABLE_SPEC( lcar ),
};
#define N_GX_TABLE_SPEC ( sizeof ( gx_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 \"ot\", \"gx\" and \"ckern\" are available.\n" );
fprintf( stderr, "\n" );
fprintf( stderr, " -T \"sfnt:tabl:enam:es \" [ot or gx] select snft table names to be \n" );
fprintf( stderr, " validated. `:' is for separating table names.\n" );
fprintf( stderr, "\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, " Supported tables in gx validator are:\n" );
fprintf( stderr, " " );
for ( i = 0; i < N_GX_TABLE_SPEC; i++ )
{
print_tag( stderr, gx_table_spec[i].tag );
fprintf( stderr, " " );
}
fprintf( stderr, "\n" );
fprintf( stderr, "\n" );
fprintf( stderr, " -T \"ms:apple\" [ckern] select (a) classic kern dialect(s) for \n" );
fprintf( stderr, " validation. `:' is for separating dialect names.\n" );
fprintf( stderr, " If more than one dialects is specified, all\n" );
fprintf( stderr, " dialects are accepted when validating. \n" );
fprintf( stderr, "\n" );
fprintf( stderr, " Supported dialects in ckern validator are:\n" );
fprintf( stderr, " ms apple" );
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, " ckern is applicable to kern table. -L lists\n");
fprintf( stderr, " dialects supported in ckern validator only if \n" );
fprintf( stderr, " kern table is available in the font file.\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, " Available components for gx validator:\n" );
fprintf( stderr, " gxvmodule gxvcommon gxvfeat gxvmort gxvmorx gxvbsln gxvjust\n");
fprintf( stderr, " gxvkern gxvobpd gxvtrak gxvprop gxvlcar\n");
fprintf( stderr, "\n" );
fprintf( stderr, " Only gxvkern is available for ckern validator.\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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -