Add gxvalid module to validate TrueType GX/AAT tables.
Modifications on existing files: * Jamfile: Register gxvalid module. * src/base/Jamfile: Register ftgxval.c. * src/base/rule.mk: Register ftgxval.c. * docs/INSTALL.ANY: Register gxvalid/gxvalid.c. * include/freetype/config/ftheader.h: Add macro to include gxvalid header file, FT_GX_VALIDATE_H. * include/freetype/config/ftmodule.h: Register gxv_module_class. * include/freetype/ftchapters.h: Add comment about gx_validation. * include/freetype/ftotval.h: Change keyword FT_VALIDATE_XXX to FT_VALIDATE_OTXXX to co-exist gxvalid. * include/freetype/tttags.h: Add tag for TrueType GX/AAT tables. * include/freetype/internal/ftserv.h: Add macro to use gxvalid service, FT_SERVICE_GX_VALIDATE_H * include/freetype/internal/fttrace.h: Add trace facilities for gxvalid. New files on existing directories: * include/freetype/internal/services/svgxval.h: Registration of validation service for TrueType GX/AAT and classic kern table. * include/freetype/ftgxval.h: Public API definition to use gxvalid. * src/base/ftgxval.c: Public API of gxvalid. New files under src/gxvalid/: * src/gxvalid/Jamfile src/gxvalid/README src/gxvalid/module.mk src/gxvalid/rules.mk src/gxvalid/gxvalid.c src/gxvalid/gxvalid.h src/gxvalid/gxvbsln.c src/gxvalid/gxvcommn.c src/gxvalid/gxvcommn.h src/gxvalid/gxverror.h src/gxvalid/gxvfeat.c src/gxvalid/gxvfgen.c src/gxvalid/gxvjust.c src/gxvalid/gxvkern.c src/gxvalid/gxvlcar.c src/gxvalid/gxvmod.c src/gxvalid/gxvmod.h src/gxvalid/gxvmort.c src/gxvalid/gxvmort.h src/gxvalid/gxvmort0.c src/gxvalid/gxvmort1.c src/gxvalid/gxvmort2.c src/gxvalid/gxvmort4.c src/gxvalid/gxvmort5.c src/gxvalid/gxvmorx.c src/gxvalid/gxvmorx.h src/gxvalid/gxvmorx0.c src/gxvalid/gxvmorx1.c src/gxvalid/gxvmorx2.c src/gxvalid/gxvmorx4.c src/gxvalid/gxvmorx5.c src/gxvalid/gxvopbd.c src/gxvalid/gxvprop.c src/gxvalid/gxvtrak.c: New files, gxvalid body.
This commit is contained in:
parent
2752bd1a46
commit
a438621451
47
ChangeLog
47
ChangeLog
@ -1,3 +1,50 @@
|
||||
2005-08-23 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
|
||||
|
||||
Add gxvalid module to validate TrueType GX/AAT tables.
|
||||
|
||||
Modifications on existing files:
|
||||
|
||||
* Jamfile: Register gxvalid module.
|
||||
* src/base/Jamfile: Register ftgxval.c.
|
||||
* src/base/rule.mk: Register ftgxval.c.
|
||||
* docs/INSTALL.ANY: Register gxvalid/gxvalid.c.
|
||||
|
||||
* include/freetype/config/ftheader.h: Add macro to include gxvalid
|
||||
header file, FT_GX_VALIDATE_H.
|
||||
* include/freetype/config/ftmodule.h: Register gxv_module_class.
|
||||
|
||||
* include/freetype/ftchapters.h: Add comment about gx_validation.
|
||||
* include/freetype/ftotval.h: Change keyword FT_VALIDATE_XXX
|
||||
to FT_VALIDATE_OTXXX to co-exist gxvalid.
|
||||
* include/freetype/tttags.h: Add tag for TrueType GX/AAT tables.
|
||||
|
||||
* include/freetype/internal/ftserv.h: Add macro to use gxvalid
|
||||
service, FT_SERVICE_GX_VALIDATE_H
|
||||
* include/freetype/internal/fttrace.h: Add trace facilities
|
||||
for gxvalid.
|
||||
|
||||
New files on existing directories:
|
||||
|
||||
* include/freetype/internal/services/svgxval.h: Registration of
|
||||
validation service for TrueType GX/AAT and classic kern table.
|
||||
* include/freetype/ftgxval.h: Public API definition to use gxvalid.
|
||||
* src/base/ftgxval.c: Public API of gxvalid.
|
||||
|
||||
New files under src/gxvalid/:
|
||||
|
||||
* src/gxvalid/Jamfile src/gxvalid/README src/gxvalid/module.mk
|
||||
src/gxvalid/rules.mk src/gxvalid/gxvalid.c src/gxvalid/gxvalid.h
|
||||
src/gxvalid/gxvbsln.c src/gxvalid/gxvcommn.c src/gxvalid/gxvcommn.h
|
||||
src/gxvalid/gxverror.h src/gxvalid/gxvfeat.c src/gxvalid/gxvfgen.c
|
||||
src/gxvalid/gxvjust.c src/gxvalid/gxvkern.c src/gxvalid/gxvlcar.c
|
||||
src/gxvalid/gxvmod.c src/gxvalid/gxvmod.h src/gxvalid/gxvmort.c
|
||||
src/gxvalid/gxvmort.h src/gxvalid/gxvmort0.c src/gxvalid/gxvmort1.c
|
||||
src/gxvalid/gxvmort2.c src/gxvalid/gxvmort4.c src/gxvalid/gxvmort5.c
|
||||
src/gxvalid/gxvmorx.c src/gxvalid/gxvmorx.h src/gxvalid/gxvmorx0.c
|
||||
src/gxvalid/gxvmorx1.c src/gxvalid/gxvmorx2.c src/gxvalid/gxvmorx4.c
|
||||
src/gxvalid/gxvmorx5.c src/gxvalid/gxvopbd.c src/gxvalid/gxvprop.c
|
||||
src/gxvalid/gxvtrak.c: New files, gxvalid body.
|
||||
|
||||
2005-08-21 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/truetype/ttgload.c (TT_Load_Glyph): Only translate outline
|
||||
|
1
Jamfile
1
Jamfile
@ -76,6 +76,7 @@ FT2_COMPONENTS ?= autofit # auto-fitter
|
||||
cache # cache sub-system
|
||||
cff # CFF/CEF font driver
|
||||
cid # PostScript CID-keyed font driver
|
||||
gxvalid # validation of TrueTypeGX/AAT tables
|
||||
gzip # support for gzip-compressed files
|
||||
lzw # support for LZW-compressed files
|
||||
otvalid # validation of OpenType tables
|
||||
|
@ -69,6 +69,7 @@ I. Standard procedure
|
||||
src/cache/ftcache.c -- cache sub-system (in beta)
|
||||
src/gzip/ftgzip.c -- support for compressed fonts (.gz)
|
||||
src/lzw/ftlzw.c -- support for compressed fonts (.Z)
|
||||
src/gxvalid/gxvalid.c -- TrueTypeGX/AAT table validation
|
||||
src/otvalid/otvalid.c -- OpenType table validation
|
||||
src/psaux/psaux.c -- PostScript Type 1 parsing
|
||||
src/pshinter/pshinter.c -- PS hinting module
|
||||
|
@ -557,6 +557,18 @@
|
||||
/* */
|
||||
#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* @macro: */
|
||||
/* FT_GX_VALIDATE_H */
|
||||
/* */
|
||||
/* @description: */
|
||||
/* A macro used in #include statements to name the file containing */
|
||||
/* the optional FreeType 2 API used to validate TrueTypeGX/AAT tables */
|
||||
/* (feat, mort, morx, bsln, just, kern, opbd, trak, prop). */
|
||||
/* */
|
||||
#define FT_GX_VALIDATE_H <freetype/ftgxval.h>
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
|
@ -17,3 +17,4 @@ FT_USE_MODULE(ft_smooth_lcd_renderer_class)
|
||||
FT_USE_MODULE(ft_smooth_lcdv_renderer_class)
|
||||
FT_USE_MODULE(otv_module_class)
|
||||
FT_USE_MODULE(bdf_driver_class)
|
||||
FT_USE_MODULE(gxv_module_class)
|
||||
|
@ -41,6 +41,7 @@
|
||||
/* pfr_fonts */
|
||||
/* winfnt_fonts */
|
||||
/* ot_validation */
|
||||
/* gx_validation */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
|
302
include/freetype/ftgxval.h
Normal file
302
include/freetype/ftgxval.h
Normal file
@ -0,0 +1,302 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftgxval.h */
|
||||
/* */
|
||||
/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
|
||||
/* */
|
||||
/* Copyright 2004 by */
|
||||
/* Masatake YAMATO, Redhat K.K, */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout is support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __FTGXVAL_H__
|
||||
#define __FTGXVAL_H__
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#ifdef FREETYPE_H
|
||||
#error "freetype.h of FreeType 1 has been loaded!"
|
||||
#error "Please fix the directory search order for header files"
|
||||
#error "so that freetype.h of FreeType 2 is found first."
|
||||
#endif
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Section> */
|
||||
/* gx_validation */
|
||||
/* */
|
||||
/* <Title> */
|
||||
/* TrueTypeGX/AAT Validation */
|
||||
/* */
|
||||
/* <Abstract> */
|
||||
/* An API to validate TrueTypeGX/AAT tables. */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* This section contains the declaration of functions to validate */
|
||||
/* some TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, */
|
||||
/* trak, prop, lcar). */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* */
|
||||
/* Warnings: Use FT_VALIDATE_XXX to validate a table. */
|
||||
/* Following definitions are for gxvalid developers. */
|
||||
/* */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
#define FT_VALIDATE_feat_INDEX 0
|
||||
#define FT_VALIDATE_mort_INDEX 1
|
||||
#define FT_VALIDATE_morx_INDEX 2
|
||||
#define FT_VALIDATE_bsln_INDEX 3
|
||||
#define FT_VALIDATE_just_INDEX 4
|
||||
#define FT_VALIDATE_kern_INDEX 5
|
||||
#define FT_VALIDATE_opbd_INDEX 6
|
||||
#define FT_VALIDATE_trak_INDEX 7
|
||||
#define FT_VALIDATE_prop_INDEX 8
|
||||
#define FT_VALIDATE_lcar_INDEX 9
|
||||
#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX
|
||||
#define FT_VALIDATE_GX_LENGTH (FT_VALIDATE_GX_LAST_INDEX + 1)
|
||||
|
||||
/* Up to 0x1000 is used by otvalid.
|
||||
Ox2000 is reserved for feature ot extension. */
|
||||
#define FT_VALIDATE_GX_START 0x4000
|
||||
#define FT_VALIDATE_GX_BITFIELD(tag) \
|
||||
(FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX)
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* @enum:
|
||||
* FT_VALIDATE_GXXXX
|
||||
*
|
||||
* @description:
|
||||
* A list of bit-field constants used with @FT_TrueTypeGX_Validate to
|
||||
* indicate which TrueTypeGX/AAT Type tables should be validated.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_feat ::
|
||||
* Validate feat table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_mort ::
|
||||
* Validate mort table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_morx ::
|
||||
* Validate morx table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_bsln ::
|
||||
* Validate bsln table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_just ::
|
||||
* Validate just table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_kern ::
|
||||
* Validate kern table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_opbd ::
|
||||
* Validate opbd table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_trak ::
|
||||
* Validate trak table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_prop ::
|
||||
* Validate prop table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_lcar ::
|
||||
* Validate lcar table.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_GX ::
|
||||
* Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern,
|
||||
* opbd, trak, prop and lcar).
|
||||
*
|
||||
*/
|
||||
|
||||
#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD(feat)
|
||||
#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD(mort)
|
||||
#define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD(morx)
|
||||
#define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD(bsln)
|
||||
#define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD(just)
|
||||
#define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD(kern)
|
||||
#define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD(opbd)
|
||||
#define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD(trak)
|
||||
#define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD(prop)
|
||||
#define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD(lcar)
|
||||
|
||||
#define FT_VALIDATE_GX ( FT_VALIDATE_feat | \
|
||||
FT_VALIDATE_mort | \
|
||||
FT_VALIDATE_morx | \
|
||||
FT_VALIDATE_bsln | \
|
||||
FT_VALIDATE_just | \
|
||||
FT_VALIDATE_kern | \
|
||||
FT_VALIDATE_opbd | \
|
||||
FT_VALIDATE_trak | \
|
||||
FT_VALIDATE_prop | \
|
||||
FT_VALIDATE_lcar )
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_TrueTypeGX_Validate
|
||||
*
|
||||
* @description:
|
||||
* Validate various TrueTypeGX tables to assure that all offsets and
|
||||
* indices are valid. The idea is that a higher-level library which
|
||||
* actually does the text layout can access those tables without
|
||||
* error checking (which can be quite time consuming).
|
||||
*
|
||||
* @input:
|
||||
* face ::
|
||||
* A handle to the input face.
|
||||
*
|
||||
* validation_flags ::
|
||||
* A bit field which specifies the tables to be validated. See
|
||||
* @FT_VALIDATE_GXXXX for possible values.
|
||||
*
|
||||
* table_length ::
|
||||
* The length of tables. Generally FT_VALIDATE_GX_LENGTH should
|
||||
* be passed.
|
||||
*
|
||||
* @output
|
||||
* tables ::
|
||||
* The array where each validated sfnt tables are stored to.
|
||||
* The array itself must be allocated by a client.
|
||||
*
|
||||
* @return:
|
||||
* FreeType error code. 0 means success.
|
||||
*
|
||||
* @note:
|
||||
* This function only works with TrueTypeGX fonts, returning an error
|
||||
* otherwise.
|
||||
*
|
||||
* After use, the application should deallocate the buffers pointed by each
|
||||
* tables' element. A NULL value indicates that the table either
|
||||
* doesn't exist in the font, the application hasn't asked for validation, or
|
||||
* the validator doesn't have ability to validate the sfnt table.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_TrueTypeGX_Validate( FT_Face face,
|
||||
FT_UInt validation_flags,
|
||||
FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
|
||||
FT_UInt table_length );
|
||||
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* @enum:
|
||||
* FT_VALIDATE_CKERNXXX
|
||||
*
|
||||
* @description:
|
||||
* A list of bit-field constants used with @FT_ClassicKern_Validate
|
||||
* to indicate (a) classic kern dialect(s).
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_MS ::
|
||||
* Validate the kern table as it has classic Microsoft kern dialect.
|
||||
* If @FT_ClassicKern_Validate detects the table has the other
|
||||
* dialect, it regards the table invalid.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_APPLE ::
|
||||
* Validate the kern table as it has classic Apple kern dialect.
|
||||
* If @FT_ClassicKern_Validate detects the table has the other
|
||||
* dialect, it regards the table invalid.
|
||||
*
|
||||
* @values:
|
||||
* FT_VALIDATE_CKERN ::
|
||||
* Validate the kern table as it has classic Apple kern dialect or
|
||||
* Microsoft kern dialect.
|
||||
*/
|
||||
#define FT_VALIDATE_MS (FT_VALIDATE_GX_START << 0)
|
||||
#define FT_VALIDATE_APPLE (FT_VALIDATE_GX_START << 1)
|
||||
|
||||
#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_ClassicKern_Validate
|
||||
*
|
||||
* @description:
|
||||
* Validate classic(16bit format) kern table to assure that the offsets
|
||||
* and indices are valid. The idea is that a higher-level library
|
||||
* which actually does the text layout can access those tables without
|
||||
* error checking (which can be quite time consuming).
|
||||
*
|
||||
* Kern table validator in @FT_TrueTypeGX_Validate deals both
|
||||
* new 32 bit format and classic 16 bit format. In other hand
|
||||
* this function supports only the classic 16 bit format.
|
||||
*
|
||||
* @input:
|
||||
* face ::
|
||||
* A handle to the input face.
|
||||
*
|
||||
* validation_flags ::
|
||||
* A bit field which specifies the dialect to be validated. See
|
||||
* @FT_VALIDATE_CKERNXXX for possible values.
|
||||
*
|
||||
* @output
|
||||
* ckern_table ::
|
||||
* A pointer to the kern table.
|
||||
*
|
||||
* @return:
|
||||
* FreeType error code. 0 means success.
|
||||
*
|
||||
* @note:
|
||||
* After use, the application should deallocate the buffers pointed by
|
||||
* ckern_table. A NULL value indicates that the table either
|
||||
* doesn't exist in the font.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_ClassicKern_Validate( FT_Face face,
|
||||
FT_UInt validation_flags,
|
||||
FT_Bytes *ckern_table );
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* __FTGXVAL_H__ */
|
||||
|
||||
|
||||
/* END */
|
@ -64,7 +64,7 @@ FT_BEGIN_HEADER
|
||||
/**********************************************************************
|
||||
*
|
||||
* @enum:
|
||||
* FT_VALIDATE_XXX
|
||||
* FT_VALIDATE_OTXXX
|
||||
*
|
||||
* @description:
|
||||
* A list of bit-field constants used with @FT_OpenType_Validate to
|
||||
@ -121,7 +121,7 @@ FT_BEGIN_HEADER
|
||||
*
|
||||
* validation_flags ::
|
||||
* A bit field which specifies the tables to be validated. See
|
||||
* @FT_VALIDATE_XXX for possible values.
|
||||
* @FT_VALIDATE_OTXXX for possible values.
|
||||
*
|
||||
* @output:
|
||||
* BASE_table ::
|
||||
|
@ -309,6 +309,7 @@ FT_BEGIN_HEADER
|
||||
#define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h>
|
||||
#define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h>
|
||||
#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h>
|
||||
#define FT_SERVICE_GX_VALIDATE_H <freetype/internal/services/svgxval.h>
|
||||
#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h>
|
||||
#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h>
|
||||
#define FT_SERVICE_XFREE86_NAME_H <freetype/internal/services/svxf86nm.h>
|
||||
|
@ -114,5 +114,19 @@ FT_TRACE_DEF( otvgpos )
|
||||
FT_TRACE_DEF( otvgsub )
|
||||
FT_TRACE_DEF( otvjstf )
|
||||
|
||||
/* TrueTypeGX/AAT validation components */
|
||||
FT_TRACE_DEF( gxvmodule )
|
||||
FT_TRACE_DEF( gxvcommon )
|
||||
FT_TRACE_DEF( gxvfeat )
|
||||
FT_TRACE_DEF( gxvmort )
|
||||
FT_TRACE_DEF( gxvmorx )
|
||||
FT_TRACE_DEF( gxvbsln )
|
||||
FT_TRACE_DEF( gxvjust )
|
||||
FT_TRACE_DEF( gxvkern )
|
||||
FT_TRACE_DEF( gxvopbd )
|
||||
FT_TRACE_DEF( gxvtrak )
|
||||
FT_TRACE_DEF( gxvprop )
|
||||
FT_TRACE_DEF( gxvlcar )
|
||||
|
||||
|
||||
/* END */
|
||||
|
69
include/freetype/internal/services/svgxval.h
Normal file
69
include/freetype/internal/services/svgxval.h
Normal file
@ -0,0 +1,69 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* svgxval.h */
|
||||
/* */
|
||||
/* FreeType API for validating TrueTypeGX/AAT tables (specification). */
|
||||
/* */
|
||||
/* Copyright 2004 by */
|
||||
/* Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#ifndef __SVGXVAL_H__
|
||||
#define __SVGXVAL_H__
|
||||
|
||||
#include FT_GX_VALIDATE_H
|
||||
#include FT_INTERNAL_VALIDATE_H
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
#define FT_SERVICE_ID_GX_VALIDATE "truetypegx-validate"
|
||||
#define FT_SERVICE_ID_CLASSICKERN_VALIDATE "classickern-validate"
|
||||
|
||||
typedef FT_Error
|
||||
(*gxv_validate_func)( FT_Face face,
|
||||
FT_UInt gx_flags,
|
||||
FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
|
||||
FT_UInt table_length );
|
||||
|
||||
|
||||
typedef FT_Error
|
||||
(*ckern_validate_func) ( FT_Face face,
|
||||
FT_UInt ckern_flags,
|
||||
FT_Bytes *ckern_table );
|
||||
|
||||
|
||||
FT_DEFINE_SERVICE( GXvalidate )
|
||||
{
|
||||
gxv_validate_func validate;
|
||||
};
|
||||
|
||||
FT_DEFINE_SERVICE( CKERNvalidate )
|
||||
{
|
||||
ckern_validate_func validate;
|
||||
};
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __SVGXVAL_H__ */
|
||||
|
||||
|
||||
/* END */
|
@ -38,6 +38,7 @@ FT_BEGIN_HEADER
|
||||
#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' )
|
||||
#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
|
||||
#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
|
||||
#define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' )
|
||||
#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
|
||||
#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
|
||||
#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' )
|
||||
@ -46,6 +47,7 @@ FT_BEGIN_HEADER
|
||||
#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' )
|
||||
#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' )
|
||||
#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' )
|
||||
#define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' )
|
||||
#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' )
|
||||
#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' )
|
||||
#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' )
|
||||
@ -59,19 +61,26 @@ FT_BEGIN_HEADER
|
||||
#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
|
||||
#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' )
|
||||
#define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' )
|
||||
#define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' )
|
||||
#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' )
|
||||
#define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' )
|
||||
#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
|
||||
#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
|
||||
#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
|
||||
#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
|
||||
#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
|
||||
#define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' )
|
||||
#define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' )
|
||||
#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
|
||||
#define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' )
|
||||
#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' )
|
||||
#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' )
|
||||
#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' )
|
||||
#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )
|
||||
#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
|
||||
#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' )
|
||||
#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' )
|
||||
#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )
|
||||
#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' )
|
||||
#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' )
|
||||
#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
|
||||
|
@ -32,7 +32,7 @@ SubDir FT2_TOP $(FT2_SRC_DIR) base ;
|
||||
#
|
||||
Library $(FT2_LIB) : ftsystem.c ftinit.c ftglyph.c ftmm.c ftbdf.c
|
||||
ftbbox.c ftdebug.c ftxf86.c fttype1.c ftpfr.c
|
||||
ftstroke.c ftwinfnt.c ftotval.c ftbitmap.c ;
|
||||
ftstroke.c ftwinfnt.c ftotval.c ftgxval.c ftbitmap.c ;
|
||||
|
||||
# Add Macintosh-specific file to the library when necessary.
|
||||
#
|
||||
|
103
src/base/ftgxval.c
Normal file
103
src/base/ftgxval.c
Normal file
@ -0,0 +1,103 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* ftgxval.c */
|
||||
/* */
|
||||
/* FreeType API for validating TrueTyepGX/AAT tables (body). */
|
||||
/* */
|
||||
/* Copyright 2004 by */
|
||||
/* Masatake YAMATO, Redhat K.K, */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_SERVICE_GX_VALIDATE_H
|
||||
|
||||
/* documentation is in ftgxval.h */
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_TrueTypeGX_Validate( FT_Face face,
|
||||
FT_UInt validation_flags,
|
||||
FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
|
||||
FT_UInt table_length )
|
||||
{
|
||||
FT_Service_GXvalidate service;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
if ( !face )
|
||||
{
|
||||
error = FT_Err_Invalid_Face_Handle;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( tables == NULL )
|
||||
{
|
||||
error = FT_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
FT_FACE_FIND_GLOBAL_SERVICE( face, service, GX_VALIDATE );
|
||||
|
||||
if ( service )
|
||||
error = service->validate( face,
|
||||
validation_flags,
|
||||
tables,
|
||||
table_length );
|
||||
else
|
||||
error = FT_Err_Invalid_Argument;
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_ClassicKern_Validate( FT_Face face,
|
||||
FT_UInt validation_flags,
|
||||
FT_Bytes *ckern_table )
|
||||
{
|
||||
FT_Service_CKERNvalidate service;
|
||||
FT_Error error;
|
||||
|
||||
|
||||
if ( !face )
|
||||
{
|
||||
error = FT_Err_Invalid_Face_Handle;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( ckern_table == NULL )
|
||||
{
|
||||
error = FT_Err_Invalid_Argument;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
FT_FACE_FIND_GLOBAL_SERVICE( face, service, CLASSICKERN_VALIDATE );
|
||||
|
||||
if ( service )
|
||||
error = service->validate( face,
|
||||
validation_flags,
|
||||
ckern_table );
|
||||
else
|
||||
error = FT_Err_Invalid_Argument;
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
@ -54,6 +54,7 @@ BASE_EXT_SRC := $(BASE_DIR)/ftbitmap.c \
|
||||
$(BASE_DIR)/ftbbox.c \
|
||||
$(BASE_DIR)/ftbdf.c \
|
||||
$(BASE_DIR)/ftglyph.c \
|
||||
$(BASE_DIR)/ftgxval.c \
|
||||
$(BASE_DIR)/ftmm.c \
|
||||
$(BASE_DIR)/ftotval.c \
|
||||
$(BASE_DIR)/ftpfr.c \
|
||||
|
21
src/gxvalid/Jamfile
Normal file
21
src/gxvalid/Jamfile
Normal file
@ -0,0 +1,21 @@
|
||||
# FreeType 2 src/gxvalid Jamfile (c) 2005 suzuki toshiya, Masatake YAMATO and Red Hat K.K.
|
||||
#
|
||||
|
||||
SubDir FT2_TOP $(FT2_SRC_DIR) gxvalid ;
|
||||
|
||||
{
|
||||
local _sources ;
|
||||
|
||||
if $(FT2_MULTI)
|
||||
{
|
||||
_sources = gxvcommn gxvfeat gxvbsln gxvtrak gxvopbd gxvprop gxvjust gxvmort gxvmort0 gxvmort1 gxvmort2 gxvmort4 gxvmort5 gxvmorx gxvmorx0 gxvmorx1 gxvmorx2 gxvmorx4 gxvmorx5 gxvlcar gxvkern gxvmod ;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sources = gxvalid ;
|
||||
}
|
||||
|
||||
Library $(FT2_LIB) : $(_sources).c ;
|
||||
}
|
||||
|
||||
# end of src/gxvalid Jamfile
|
447
src/gxvalid/README
Normal file
447
src/gxvalid/README
Normal file
@ -0,0 +1,447 @@
|
||||
gxvalid: TrueType GX validator
|
||||
==============================
|
||||
|
||||
1. What is this
|
||||
---------------
|
||||
"gxvalid" is a module to validate TrueType GX tables: a collection of
|
||||
additional tables in TrueType font which is used by "QuickDraw GX
|
||||
Text", Apple Advanced Typography (AAT). In addition, gxvalid can
|
||||
validates "kern" table which had been extended for AAT. Like otvalid,
|
||||
gxvalid uses Freetype2's validator framework(ftvalid).
|
||||
|
||||
You can link gxvalid with your program; before running your own layout
|
||||
engine, gxvalid validates a font file. As the result, you can reduce
|
||||
error-checking code from the layout engine. You can use gxvalid as a
|
||||
stand-alone font validator; ftvalid command included in ft2demo calls
|
||||
gxvalid internally. Stand-alone font validator may be useful for font
|
||||
developers.
|
||||
|
||||
This documents contains following informations:
|
||||
- supported TrueType GX tables
|
||||
- validation limitation in principle
|
||||
- permissive error handling of broken GX tables
|
||||
- "kern" table issue.
|
||||
|
||||
|
||||
2. Supported tables
|
||||
-------------------
|
||||
Following GX tables are currently supported.
|
||||
bsln feat just kern(*) lcar mort morx opbd prop trak
|
||||
|
||||
Following GX tables are currently unsupported.
|
||||
cvar fdsc fmtx fvar gvar Zapf
|
||||
|
||||
Following GX tables won't be supported.
|
||||
acnt(**) hsty(***)
|
||||
|
||||
Undocumented tables in TrueType fonts designed for Apple platform.
|
||||
CVTM TPNM addg umif
|
||||
|
||||
*) "kern" validator includes both of classic kern (format supported
|
||||
by both of Microsoft and Apple platforms) and new kern (a format
|
||||
supported by Apple platform only).
|
||||
|
||||
**) "acnt" tables is not supported by currently available Apple font
|
||||
tools.
|
||||
|
||||
***) There is one more Apple extension "hsty" but it is for Newton-OS,
|
||||
not GX (Newton-OS is a platform by Apple, but it can use sfnt-
|
||||
housed bitmap fonts only. Therefore, it should be excluded from
|
||||
"Apple platform" in the context of TrueType. gxvalid ignores it
|
||||
as Apple font tools do so.
|
||||
|
||||
We have checked 183 fonts bundled to MacOS 9.1, MacOS 9.2, MacOS 10.0,
|
||||
MacOS X 10.1, MSIE for MacOS and AppleWorks 6.0. In addition, we have
|
||||
checked 67 Dynalab fonts (designed for MacOS) and 189 Ricoh fonts
|
||||
(designed for Windows and MacOS dual platforms). The number of fonts
|
||||
including TrueType GX tables are listed in following:
|
||||
bsln: 76
|
||||
feat: 191
|
||||
just: 84
|
||||
kern: 59
|
||||
lcar: 4
|
||||
mort: 326
|
||||
morx: 19
|
||||
opbd: 4
|
||||
prop: 114
|
||||
trak: 16
|
||||
Dynalab and Ricoh fonts didn't have GX tables except of feat and mort.
|
||||
|
||||
3. Validation limitations in principle
|
||||
--------------------------------------
|
||||
TrueType GX provides layout information to font-rasterize/text-layout
|
||||
libraries. gxvalid can check whether layout information is stored as
|
||||
TrueType GX format specified by Apple. But gxvalid cannot check how
|
||||
QuickDraw GX/AAT renderer uses the stored information.
|
||||
|
||||
3-1. Validation of State Machine activity
|
||||
-----------------------------------------
|
||||
QuickDraw GX/AAT has "State Machine" to provide "stateful" layout
|
||||
features, and TrueType GX stores the state transition diagram of
|
||||
"State Machine" in "StateTable" data structure. While State Machine
|
||||
receives a series of glyph ID, State Machine starts from "start of
|
||||
text" state, walks around various states and generates various
|
||||
layout informations to renderer, and finally reaches to "end of
|
||||
text".
|
||||
|
||||
gxvalid can check essential errors like:
|
||||
- possibility of state transition to undefined states
|
||||
- existence of glyph ID that State Machine doesn't know how to
|
||||
handle it
|
||||
- State Machine cannot compute the layout information from given
|
||||
diagram
|
||||
these errors can be checked within finite steps, and without State
|
||||
Machine itself, because these are errors of "expression" of state
|
||||
transition diagram.
|
||||
|
||||
There's no limitation about how long State Machine walks around, so
|
||||
validation of the algorithm in the state transition diagram requires
|
||||
infinite steps, even if we have State Machine in gxvalid. Therefore,
|
||||
following "errors" cannot be checked.
|
||||
- existence of states which State Machine never transits to.
|
||||
- possibility that State Machine never reaches to "end of text".
|
||||
- possibility of stack underflow/overflow in State Machine
|
||||
(in ligature and contextual glyph substitution, State Machine
|
||||
can store 16 glyphs onto its stack)
|
||||
|
||||
In addition, gxvalid doesn't check "temporal glyph ID" used in the
|
||||
chained State Machines (in "mort" and "morx" tables). When a layout
|
||||
feature is implemented by single State Machine, glyph ID converted
|
||||
by State Machine is passed to the glyph renderer, thus it should not
|
||||
point to undefined glyph ID. But if a layout feature is implemented
|
||||
by chained State Machines, the component State Machine (if it is not
|
||||
final one) is permitted to generate undefined glyph ID for temporal
|
||||
use, because it is handled by next component State Machine, instead
|
||||
of the glyph renderer. To validate such temporal glyph ID, gxvalid
|
||||
must stack all undefined glyph IDs which is possible in the output
|
||||
of previous State Machine and search them in "ClassTable" of current
|
||||
State Machine. It is too complexed work to list all possible glyph
|
||||
IDs from StateTable, especially from ligature substitution table.
|
||||
|
||||
3-2. Validation of relationship among multiple layout features
|
||||
--------------------------------------------------------------
|
||||
gxvalid does not validate the relationship among multiple layout
|
||||
features at all.
|
||||
|
||||
If multiple layout features are defined in TrueType GX tables, the
|
||||
interactivity, overriding, and conflict among layout features are
|
||||
defined in the font too. For example, there are several predefined
|
||||
spacing control features:
|
||||
- Text Spacing (Proportional/Monospace/Half-width/Normal)
|
||||
- Number Spacing (Monospaced-numbers/Proportional-numbers)
|
||||
- Kana Spacing (Full-width/Proportional)
|
||||
- Ideographic Spacing (Full-width/Proportional)
|
||||
- CJK Roman Spacing (Half-width/Proportional/Default-roman
|
||||
/Full-width-roman/Proportional)
|
||||
If all layout features are independently managed, we can set an
|
||||
inconsistent typographic rule, as like "Text Spacing=Monospace" and
|
||||
"Ideographic Spacing=Proportional", at the same time.
|
||||
|
||||
The combination of each layout feature is managed by 32bit integer
|
||||
(1 bit for 1 selector setting), so we can define relationship among
|
||||
features up to 32 settings, theoretically. But if setting of
|
||||
a feature affects setting of another features, typographic priority
|
||||
of each layout feature is required to validate the relationship.
|
||||
TrueType GX format specification does not give such information even
|
||||
for predefined features.
|
||||
|
||||
4. Permissive error handling of broken GX tables
|
||||
------------------------------------------------
|
||||
When Apple's font rendering system finds an inconsistency, violation
|
||||
of specification or unspecified value in TrueType GX tables, they do
|
||||
not always return error. In most case, they silently ignore such wrong
|
||||
values or whole of table. In fact, MacOS is shipped with fonts
|
||||
including broken GX/AAT tables, but no harmful effects due to
|
||||
officially broken fonts are observed by end-users.
|
||||
|
||||
gxvalid is designed to continue its validation as long as possible.
|
||||
When gxvalid find wrong value, gxvalid warns it at least, and take a
|
||||
fallback procedure if possible. The fallback procedure depends on the
|
||||
debug level.
|
||||
|
||||
We used following 3 tools to refer Apple's error handling.
|
||||
- FontValidator (for MacOS 8.5 - 9.2) resource fork font
|
||||
- ftxvalidator (for MacOS X 10.1 -) dfont or naked-sfnt
|
||||
- ftxdumperfuser (for MacOS X 10.1 -) dfont or naked-sfnt
|
||||
However, all tests are on PowerPC based Macintosh, we have not tested
|
||||
on m68k-based Macintosh at all, at present.
|
||||
|
||||
We checked 183 fonts bundled to MacOS 9.1, MacOS 9.2, MacOS 10.0,
|
||||
MacOS X 10.1, MSIE for MacOS and AppleWorks 6.0. These fonts are
|
||||
distributed officially, but many broken GX/AAT tables are found by
|
||||
Apple's font tools. In following, we list typical violation against GX
|
||||
specification, in Apple official fonts. At least, gxvalid warns them,
|
||||
and fallback method to continue
|
||||
|
||||
4-1. broken BinSrchHeader ( 19/183)
|
||||
-----------------------------------
|
||||
BinSrchHeader is a header of data array, for m68k platform to access
|
||||
memory effectively. Although independent parameters for real use are
|
||||
only 2 (unitSize and nUnits), BinSrchHeader has 3 additional
|
||||
parameters which can be calculated from unitSize and nUnits, for
|
||||
fast setup. Apple font tools ignore them silently, so gxvalid warns
|
||||
inconsistency and always continues validation. The additional
|
||||
parameters are ignored regardless of the consistency.
|
||||
|
||||
19 fonts include inconsistent with calculated values
|
||||
all breaks are in BinSrchHeader of "kern" table.
|
||||
|
||||
4-2. too-short LookupTable ( 5/183)
|
||||
-----------------------------------
|
||||
LookupTable format 0 is simple array to get a value from given GID,
|
||||
the index of array is GID. Therefore, the length of array is
|
||||
expected to be same with max GID defined in "maxp" table, but there
|
||||
is some fonts whose LookupTable format 0 is too short to cover all
|
||||
GID. FontValidator ignores this error silently, ftxvalidator and
|
||||
ftxdumperfuser warns and continues. Similar shortage is found in
|
||||
format 3 subtable of "kern".
|
||||
gxvalid warns always and abort at FT_VALIDATE_PARANOID.
|
||||
|
||||
5 fonts include too-short kern format 0 subtables.
|
||||
1 font includes too-short kern format 3 subtable.
|
||||
|
||||
|
||||
4-3. broken LookupTable format 2 ( 1/183)
|
||||
-----------------------------------------
|
||||
LookupTable format 2, 4 covers GID space by collection of segments
|
||||
which specified by firstGlyph and lastGlyph. Some fonts stores
|
||||
firstGlyph and lastGlyph in reverse order, so segment specification
|
||||
is broken. Apple font tools ignores this error silently, broken
|
||||
segment is ignored as if it did not exist. gxvalid warns and
|
||||
normalize the segment at FT_VALIDATE_DEFAULT, or ignore the segment
|
||||
at FT_VALIDATE_TIGHT, or abort at FT_VALIDATE_PARANOID.
|
||||
|
||||
1 font includes broken LookupTable format 2, in "just" table.
|
||||
|
||||
*) It seems that all fonts manufactured by ITC for AppleWorks have
|
||||
this error.
|
||||
|
||||
|
||||
4-4. bad bracketing in glyph property ( 14/183)
|
||||
-----------------------------------------------
|
||||
GX/AAT defines bracketing property of the glyphs by "prop" table, to
|
||||
control layout functionalities for string closed in brackets and out
|
||||
of brackets. Some fonts give inappropriate bracket properties to
|
||||
glyphs. Apple font tools warn this error. gxvalid warns always and
|
||||
abort at FT_VALIDATE_PARANOID.
|
||||
|
||||
14 fonts include wrong bracket properties.
|
||||
|
||||
|
||||
4-5. invalid feature number (117/183)
|
||||
-------------------------------------
|
||||
GX/AAT extension can include 255 different features for layout, but
|
||||
popular layout features are predefined
|
||||
(see http://developer.apple.com/fonts/Registry/index.html).
|
||||
Some fonts include feature number which is incompatible with
|
||||
predefined feature registry.
|
||||
|
||||
In our survey, there are 140 fonts including "feat" table.
|
||||
a) 67 fonts uses feature number which should not be used.
|
||||
b) 117 fonts set wrong feature range (nSetting).
|
||||
this infraction is found in mort/morx.
|
||||
|
||||
Apple font tools gives no warning, although they cannot recognize
|
||||
what the feature is. At FT_VALIDATE_DEFAULT, gxvalid warns but
|
||||
continues in both cases (a, b). At FT_VALIDATE_TIGHT, gxvalid warns
|
||||
and aborts for (a), but continues for (b). At FT_VALIDATE_PARANOID,
|
||||
gxvalid warns and aborts in both cases (a, b).
|
||||
|
||||
4-6. invalid prop version ( 10/183)
|
||||
-----------------------------------
|
||||
As most TrueType GX tables, prop table must start with 32bit
|
||||
version: 0x00010000, 0x00020000 or 0x00030000. But some fonts store
|
||||
nonsense binary data in it. When Apple font tools find them, they
|
||||
abort the processing at once, and following data are unhandled.
|
||||
gxvalid does same always.
|
||||
|
||||
10 fonts include broken prop version.
|
||||
|
||||
All of these fonts are classic TrueType for Japanese script,
|
||||
manufactured by Apple.
|
||||
|
||||
4-7. unknown resource name ( 2/183)
|
||||
------------------------------------
|
||||
NOTE: THIS IS NOT TRUETYPE GX ERROR
|
||||
When TrueType font is stored in resource fork or dfont format,
|
||||
the data must be tagged as "sfnt" in resource fork index, to invoke
|
||||
TrueType font handler for the data. But the TrueType font data in
|
||||
"Keyboard.dfont" is tagged as "kbd", and that in "LastResort.dfont"
|
||||
is tagged as "lst". Apple font tools can detect the data is of
|
||||
TrueType and successfully validate them. Possibly this because they
|
||||
are known to be dfont. Current implementation of resource fork
|
||||
driver of FreeType cannot do that, thus gxvalid cannot validate them.
|
||||
|
||||
2 fonts use unknown tag for TrueType font resource.
|
||||
|
||||
5. "kern" table issue
|
||||
---------------------
|
||||
In common terminology of TrueType, "kern" is classified to basic and
|
||||
platform-independent table. But there are Apple extensions of kern,
|
||||
and there is an extension which requires GX state machine for
|
||||
contextual kerning. Therefore, gxvalid includes validator for kern.
|
||||
Unfortunately, there is no exact algorithm to check Apple's extension,
|
||||
so gxvalid includes pragmatic detector of data format and validator
|
||||
for all possible data formats, including data format for Microsoft.
|
||||
By calling classic_kern_validate() instead of gxv_validate(), you can
|
||||
specify available "kern" format explicitly. However, current FreeType2
|
||||
uses Microsoft "kern" format only, others are ignored.
|
||||
|
||||
5-1. History
|
||||
------------
|
||||
Original 16bit version of "kern" had been designed by Apple in pre-
|
||||
GX era, and it was also approved by Microsoft. Afterwards, Apple has
|
||||
designed new 32bit version "kern". Apple has noted as the difference
|
||||
between 16bit and 32bit version is only the size of variables in
|
||||
"kern" header. In following, we call the original 16bit version as
|
||||
"classic", and 32bit version as "new".
|
||||
|
||||
5-2. Versions and dialects which should be discriminated
|
||||
--------------------------------------------------------
|
||||
The "kern" table consists of the table header and several subtables.
|
||||
The version "classic" or "new" is explicitly written in the table
|
||||
header, but there are undocumented difference of font parser between
|
||||
Microsoft and Apple. It is called as "dialect" in following.
|
||||
There are 3 cases which should be discriminated: new Apple-dialect,
|
||||
classic Apple-dialect, and classic Microsoft-dialect. Analysis and
|
||||
auto detection algorithm of gxvalid is described in following.
|
||||
|
||||
5-2-1. Version detection: classic and new kern
|
||||
----------------------------------------------
|
||||
According to Apple TrueType specification, the clarified
|
||||
difference between classic and new version are only 2:
|
||||
- "kern" table header starts with the version number.
|
||||
The classic version starts with 0x0000 (16bit),
|
||||
the new version starts with 0x00010000 (32bit).
|
||||
- In the "kern" table header, the number of subtables follows to
|
||||
the version number.
|
||||
In the classic version, it is stored in 16bit variable.
|
||||
In the new version, it is stored in 32bit variable.
|
||||
|
||||
From Apple font tool's output (DumpKERN is also tested in addition
|
||||
to 3 Apple font tools in above), there is another undocumented
|
||||
difference. In new version, the subtable header includes a 16bit
|
||||
variable named "tupleIndex" which does not exist in the classic
|
||||
version.
|
||||
|
||||
New version can store all subtable formats (0, 1, 2 and 3), but
|
||||
Apple TrueType specification does not mention about subtable
|
||||
formats available in classic version.
|
||||
|
||||
|
||||
5-2-2. Avaibale subtable format in classic version
|
||||
--------------------------------------------------
|
||||
Although Apple TrueType specification recommends to use classic
|
||||
version in the case if the font is designed for both of Apple and
|
||||
Microsoft platforms, it does not note about the available subtable
|
||||
formats in classic version.
|
||||
|
||||
According to Microsoft TrueType specification, the subtable format
|
||||
assured for Windows & OS/2 support is only subtable format 0. Also
|
||||
Microsoft TrueType specification describes the subtable format 2,
|
||||
but does not mention about which platforms support it. About
|
||||
subtable format 1, 3 and later are noted as reserved for future
|
||||
use. Therefore, the classic version can store subtable formats 0
|
||||
and 2, at least. ttfdump.exe, a font tool provided by Microsoft
|
||||
ignores the subtable format written in the subtable header, and
|
||||
parse as if all subtables are in format 0.
|
||||
|
||||
kern subtable format 1 uses StateTable, so it cannot be utilized
|
||||
without GX State Machine. Therefore, it is reasonable to assume
|
||||
format 1 (and 3) is introduced after Apple have introduced GX and
|
||||
moved to new 32bit version.
|
||||
|
||||
5-2-3. Apple and Microsoft dialects
|
||||
-----------------------------------
|
||||
The kern subtable has 16bit "coverage" to describe kerning
|
||||
attributions, but bit-interpretations by Apple and Microsoft are
|
||||
reverse ordered:
|
||||
e.g. Apple-dialect writes subtable format from 0x000F bit range,
|
||||
Microsoft-dialect writes subtable format from 0x0F00 bit range).
|
||||
|
||||
In addition, from the outputs of DumpKERN and FontValidator,
|
||||
Apple's bit-interpretations of coverage in classic and new version
|
||||
are incompatible. In summary, there are 3 dialects: classic Apple-
|
||||
dialect, classic Microsoft-dialect, and new Apple-dialect.
|
||||
The classic Microsoft-dialect and new Apple-dialect are documented
|
||||
by each vendors' TrueType font specification, but the document for
|
||||
classic Apple-dialect had been lost.
|
||||
|
||||
For example, in new Apple-dialect, the bit 0x8000 is documented as
|
||||
"set to 1 when the kerning is vertical". On the other hand, in
|
||||
classic Microsoft-dialect, the bit 0x0001 is documented as "set to
|
||||
1 when the kerning is horizontal". From the outputs of DumpKERN
|
||||
and FontValidator, classic Apple-dialect recognizes the bit 0x8000
|
||||
as "set to 1 when the kerning is horizontal". From the results of
|
||||
similar experiments, classic Apple-dialect is ein ndian-reverse of
|
||||
classic Microsoft-dialect.
|
||||
|
||||
It must be noted: no font tool can sense classic Apple-dialect or
|
||||
classic-Microsoft dialect automatically.
|
||||
|
||||
5-2-4. gxvalid auto dialect detection algorithm
|
||||
-----------------------------------------------
|
||||
The first 16bit of kern table is enough to sense the version:
|
||||
- if first 16bit is 0x0000,
|
||||
kern table is in classic Apple-dialect
|
||||
or classic Microsoft-dialect,
|
||||
- if first 16bit is 0x0001, and next 16bit is 0x0000,
|
||||
kern table is in new Apple-dialect.
|
||||
If kern table is classic version, 16bit coverage is checked for in
|
||||
next. For first, the coverage is decoded by classic Apple-dialect
|
||||
as following (it is based on DumpKERN output):
|
||||
0x8000: 1=horizontal, 0=vertical
|
||||
0x4000: not used
|
||||
0x2000: 1=cross-stream, 0=normal
|
||||
0x1FF0: reserved
|
||||
0x000F: subtable format
|
||||
If any of reserved bits are set or subtable format is
|
||||
interpreted as 1 or 3, we take it as "impossible in classic
|
||||
Apple-dialect", and retry by classic Microsoft-dialect.
|
||||
The most popular coverage in new Apple-dialect: 0x8000,
|
||||
The most popular coverage in classic Apple-dialect: 0x0000,
|
||||
The most popular coverage in classic Microsoft dialect: 0x0001.
|
||||
|
||||
5-3. Tested fonts
|
||||
-----------------
|
||||
We checked 59 fonts bundled to MacOS which includes kern, and
|
||||
38 fonts bundled to Windows which includes kern.
|
||||
- fonts bundled to MacOS
|
||||
* new Apple-dialect
|
||||
format 0: 18
|
||||
format 2: 1
|
||||
format 3: 1
|
||||
* classic Apple-dialect
|
||||
format 0: 14
|
||||
* classic Microsoft-dialect
|
||||
format 0: 15
|
||||
- fonts bundled to Windows
|
||||
* classic Microsoft-dialect
|
||||
format 0: 38
|
||||
It looks strange that classic Microsoft-dialect fonts are bundled to
|
||||
MacOS: they come from MSIE for MacOS, except of MarkerFelt.dfont.
|
||||
|
||||
|
||||
ACKNOWLEDGEMENT
|
||||
---------------
|
||||
Some part of gxvalid is derived from both gxlayout module and otvalid
|
||||
module. Development of gxlayout was support of Information-technology
|
||||
Promotion Agency(IPA), Japan.
|
||||
|
||||
The detailed analysis of undefined glyph ID utilization in mort, morx
|
||||
is provided by George Williams.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Copyright 2004, 2005 by
|
||||
suzuki toshiya, Masatake YAMATO, Red hat K.K.,
|
||||
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.
|
||||
|
||||
|
||||
--- end of README ---
|
46
src/gxvalid/gxvalid.c
Normal file
46
src/gxvalid/gxvalid.c
Normal file
@ -0,0 +1,46 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvalid.c */
|
||||
/* */
|
||||
/* FreeType validator for TrueTypeGX/AAT tables (body only). */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
#define FT_MAKE_OPTION_SINGLE_OBJECT
|
||||
|
||||
#include <ft2build.h>
|
||||
|
||||
#include "gxvfeat.c"
|
||||
#include "gxvcommn.c"
|
||||
#include "gxvbsln.c"
|
||||
#include "gxvtrak.c"
|
||||
#include "gxvjust.c"
|
||||
#include "gxvmort.c"
|
||||
#include "gxvmort0.c"
|
||||
#include "gxvmort1.c"
|
||||
#include "gxvmort2.c"
|
||||
#include "gxvmort4.c"
|
||||
#include "gxvmort5.c"
|
||||
#include "gxvmorx.c"
|
||||
#include "gxvmorx0.c"
|
||||
#include "gxvmorx1.c"
|
||||
#include "gxvmorx2.c"
|
||||
#include "gxvmorx4.c"
|
||||
#include "gxvmorx5.c"
|
||||
#include "gxvkern.c"
|
||||
#include "gxvopbd.c"
|
||||
#include "gxvprop.c"
|
||||
#include "gxvlcar.c"
|
||||
#include "gxvmod.c"
|
||||
|
||||
|
||||
/* END */
|
106
src/gxvalid/gxvalid.h
Normal file
106
src/gxvalid/gxvalid.h
Normal file
@ -0,0 +1,106 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvalid.h */
|
||||
/* */
|
||||
/* TrueTyeeGX/AAT table validation (specification only). */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __GXVALID_H__
|
||||
#define __GXVALID_H__
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "gxverror.h" /* must come before FT_INTERNAL_VALIDATE_H */
|
||||
|
||||
#include FT_INTERNAL_VALIDATE_H
|
||||
#include FT_INTERNAL_STREAM_H
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_feat_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_bsln_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_trak_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_just_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_morx_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_kern_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_kern_validate_classic
|
||||
( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Int dialect_flags,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_opbd_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_prop_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_lcar_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator valid );
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
|
||||
#endif /* __GXVALID_H__ */
|
||||
|
||||
|
||||
/* END */
|
326
src/gxvalid/gxvbsln.c
Normal file
326
src/gxvalid/gxvbsln.c
Normal file
@ -0,0 +1,326 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvbsln.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT bsln table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvbsln
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define GXV_BSLN_VALUE_COUNT 32
|
||||
#define GXV_BSLN_VALUE_EMPTY 0xFFFF
|
||||
|
||||
typedef struct GXV_bsln_DataRec_
|
||||
{
|
||||
FT_Bytes ctlPoints_p;
|
||||
FT_UShort defaultBaseline;
|
||||
|
||||
} GXV_bsln_DataRec, *GXV_bsln_Data;
|
||||
#define GXV_BSLN_DATA(field) GXV_TABLE_DATA( bsln, field )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_bsln_LookupValue_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort v = value.u;
|
||||
FT_UShort* ctlPoints;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( " lookup value" );
|
||||
|
||||
if ( v >= GXV_BSLN_VALUE_COUNT )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
|
||||
ctlPoints = (FT_UShort*)GXV_BSLN_DATA( ctlPoints_p );
|
||||
if ( ctlPoints && ctlPoints[v] == GXV_BSLN_VALUE_EMPTY )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
+===============+ --------+
|
||||
| lookup header | |
|
||||
+===============+ |
|
||||
| BinSrchHeader | |
|
||||
+===============+ |
|
||||
| lastGlyph[0] | |
|
||||
+---------------+ |
|
||||
| firstGlyph[0] | | head of lookup table
|
||||
+---------------+ | +
|
||||
| offset[0] | -> | offset [byte]
|
||||
+===============+ | +
|
||||
| lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
|
||||
+---------------+ |
|
||||
| firstGlyph[1] | |
|
||||
+---------------+ |
|
||||
| offset[1] | |
|
||||
+===============+ |
|
||||
|
|
||||
... |
|
||||
|
|
||||
16bit value array |
|
||||
+===============+ |
|
||||
| value | <-------+
|
||||
...
|
||||
*/
|
||||
|
||||
static GXV_LookupValueDesc
|
||||
gxv_bsln_LookupFmt4_transit( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p;
|
||||
FT_Bytes limit;
|
||||
FT_UShort offset;
|
||||
GXV_LookupValueDesc value;
|
||||
|
||||
offset = base_value.u + ( relative_gindex * sizeof ( FT_UShort ) );
|
||||
|
||||
p = valid->lookuptbl_head + offset;
|
||||
limit = lookuptbl_limit;
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
|
||||
value.u = FT_NEXT_USHORT( p );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_bsln_parts_fmt0_validate( FT_Bytes tables,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = tables;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "parts format 0" );
|
||||
|
||||
/* deltas */
|
||||
GXV_LIMIT_CHECK( 2 * GXV_BSLN_VALUE_COUNT );
|
||||
|
||||
valid->table_data = NULL; /* No ctlPoints here. */
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_bsln_parts_fmt1_validate( FT_Bytes tables,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = tables;
|
||||
|
||||
GXV_NAME_ENTER( " parts format 1" );
|
||||
|
||||
/* deltas */
|
||||
gxv_bsln_parts_fmt0_validate( p, limit, valid );
|
||||
|
||||
/* mappingData */
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_bsln_LookupValue_validate;
|
||||
valid->lookupfmt4_trans = gxv_bsln_LookupFmt4_transit;
|
||||
gxv_LookupTable_validate( p + 2 * GXV_BSLN_VALUE_COUNT,
|
||||
limit,
|
||||
valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_bsln_parts_fmt2_validate( FT_Bytes tables,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = tables;
|
||||
|
||||
FT_UShort stdGlyph;
|
||||
FT_UShort ctlPoint;
|
||||
FT_Int i;
|
||||
|
||||
FT_UShort defaultBaseline = GXV_BSLN_DATA( defaultBaseline );
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "parts format 2" );
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + ( 2 * GXV_BSLN_VALUE_COUNT ) );
|
||||
|
||||
/* stdGlyph */
|
||||
stdGlyph = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( " (stdGlyph = %u)\n", stdGlyph ));
|
||||
|
||||
gxv_glyphid_validate( stdGlyph, valid );
|
||||
|
||||
/* Record the position of ctlPoints */
|
||||
GXV_BSLN_DATA( ctlPoints_p) = p;
|
||||
|
||||
/* ctlPoints */
|
||||
for ( i = 0; i < GXV_BSLN_VALUE_COUNT; i++ )
|
||||
{
|
||||
ctlPoint = FT_NEXT_USHORT( p );
|
||||
if ( ctlPoint == GXV_BSLN_VALUE_EMPTY )
|
||||
{
|
||||
if ( i == defaultBaseline )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
gxv_ctlPoint_validate( stdGlyph, (FT_Short)ctlPoint, valid );
|
||||
}
|
||||
}
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_bsln_parts_fmt3_validate( FT_Bytes tables,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid)
|
||||
{
|
||||
FT_Bytes p = tables;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "parts format 3" );
|
||||
|
||||
/* stdGlyph + ctlPoints */
|
||||
gxv_bsln_parts_fmt2_validate( p, limit, valid );
|
||||
|
||||
/* mappingData */
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_bsln_LookupValue_validate;
|
||||
valid->lookupfmt4_trans = gxv_bsln_LookupFmt4_transit;
|
||||
gxv_LookupTable_validate( p + ( 2 + 2 * GXV_BSLN_VALUE_COUNT ),
|
||||
limit,
|
||||
valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** bsln TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_bsln_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
|
||||
GXV_bsln_DataRec bslnrec;
|
||||
GXV_bsln_Data bsln = &bslnrec;
|
||||
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
|
||||
FT_ULong version;
|
||||
FT_UShort format;
|
||||
FT_UShort defaultBaseline;
|
||||
|
||||
GXV_Validate_Func fmt_funcs_table [] =
|
||||
{
|
||||
gxv_bsln_parts_fmt0_validate,
|
||||
gxv_bsln_parts_fmt1_validate,
|
||||
gxv_bsln_parts_fmt2_validate,
|
||||
gxv_bsln_parts_fmt3_validate,
|
||||
};
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = bsln;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation bsln table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
format = FT_NEXT_USHORT( p );
|
||||
defaultBaseline = FT_NEXT_USHORT( p );
|
||||
|
||||
/* version 1.0 is only defined (1996) */
|
||||
if ( version != 0x00010000UL )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
/* format 1, 2, 3 are only defined (1996) */
|
||||
GXV_TRACE(( " (format = %d)\n", format ));
|
||||
if ( format > 3 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
if ( defaultBaseline > 31 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
|
||||
bsln->defaultBaseline = defaultBaseline;
|
||||
|
||||
fmt_funcs_table[format]( p, limit, valid );
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
/* arch-tag: ebe81143-fdaa-4c68-a4d1-b57227daa3bc
|
||||
(do not change this comment) */
|
||||
|
||||
|
||||
/* END */
|
1735
src/gxvalid/gxvcommn.c
Normal file
1735
src/gxvalid/gxvcommn.c
Normal file
File diff suppressed because it is too large
Load Diff
452
src/gxvalid/gxvcommn.h
Normal file
452
src/gxvalid/gxvcommn.h
Normal file
@ -0,0 +1,452 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvcommn.h */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT common tables validation (specification). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
/*
|
||||
* keywords in variable naming
|
||||
* ---------------------------
|
||||
* table: FT_Bytes typed, pointing the start of this table/subtable.
|
||||
* limit: FT_Bytes typed, pointing the end of this table/subtable
|
||||
* including padding for alignment.
|
||||
* offset: FT_UInt typed, the number of octets from the start to target.
|
||||
* length: FT_UInt typed, the number of octets from the start to the end.
|
||||
* in this table/subtable, including padding for alignment.
|
||||
*
|
||||
* _MIN, _MAX: should be added to the tail of macros, as INT_MIN etc.
|
||||
*/
|
||||
|
||||
#ifndef __GXVCOMMN_H__
|
||||
#define __GXVCOMMN_H__
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include "gxvalid.h"
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
#include FT_SFNT_NAMES_H
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** VALIDATION *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct GXV_ValidatorRec_* GXV_Validator;
|
||||
|
||||
#define DUMMY_LIMIT 0
|
||||
typedef void (*GXV_Validate_Func)( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
/* ====================== LookupTable Validator ======================== */
|
||||
|
||||
typedef union GXV_LookupValueDesc_
|
||||
{
|
||||
FT_UShort u;
|
||||
FT_Short s;
|
||||
|
||||
} GXV_LookupValueDesc;
|
||||
|
||||
typedef enum GXV_LookupValue_SignSpec_
|
||||
{
|
||||
GXV_LOOKUPVALUE_UNSIGNED = 0,
|
||||
GXV_LOOKUPVALUE_SIGNED
|
||||
|
||||
} GXV_LookupValue_SignSpec;
|
||||
|
||||
typedef void (*GXV_Lookup_Value_Validate_Func)( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid );
|
||||
|
||||
typedef GXV_LookupValueDesc (*GXV_Lookup_Fmt4_Transit_Func)
|
||||
( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
/* ====================== StateTable Validator ========================= */
|
||||
|
||||
typedef enum GXV_GlyphOffset_Format_
|
||||
{
|
||||
GXV_GLYPHOFFSET_NONE = -1,
|
||||
GXV_GLYPHOFFSET_UCHAR = 2,
|
||||
GXV_GLYPHOFFSET_CHAR,
|
||||
GXV_GLYPHOFFSET_USHORT = 4,
|
||||
GXV_GLYPHOFFSET_SHORT,
|
||||
GXV_GLYPHOFFSET_ULONG = 8,
|
||||
GXV_GLYPHOFFSET_LONG
|
||||
|
||||
} GXV_GlyphOffset_Format;
|
||||
|
||||
|
||||
#define GXV_GLYPHOFFSET_FMT( table ) \
|
||||
( valid-> table . entry_glyphoffset_fmt )
|
||||
|
||||
#define GXV_GLYPHOFFSET_SIZE( table ) \
|
||||
( ( valid-> table . entry_glyphoffset_fmt ) / 2 )
|
||||
|
||||
/* ----------------------- 16bit StateTable ---------------------------- */
|
||||
|
||||
typedef union GXV_StateTable_GlyphOffsetDesc_
|
||||
{
|
||||
FT_Byte uc;
|
||||
FT_UShort u; /* same with GXV_LookupValueDesc */
|
||||
FT_ULong ul;
|
||||
FT_Char c;
|
||||
FT_Short s; /* same with GXV_LookupValueDesc */
|
||||
FT_Long l;
|
||||
|
||||
} GXV_StateTable_GlyphOffsetDesc;
|
||||
|
||||
typedef void (*GXV_StateTable_Subtable_Setup_Func)( FT_UShort table_size,
|
||||
FT_UShort classTable,
|
||||
FT_UShort stateArray,
|
||||
FT_UShort entryTable,
|
||||
FT_UShort* classTable_length_p,
|
||||
FT_UShort* stateArray_length_p,
|
||||
FT_UShort* entryTable_length_p,
|
||||
GXV_Validator valid );
|
||||
|
||||
typedef void (*GXV_StateTable_Entry_Validate_Func)( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes statetable_table,
|
||||
FT_Bytes statetable_limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
typedef void (*GXV_StateTable_OptData_Load_Func)( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
typedef struct GXV_StateTable_ValidatorRec_
|
||||
{
|
||||
GXV_GlyphOffset_Format entry_glyphoffset_fmt;
|
||||
void* optdata;
|
||||
GXV_StateTable_Subtable_Setup_Func
|
||||
subtable_setup_func;
|
||||
GXV_StateTable_Entry_Validate_Func
|
||||
entry_validate_func;
|
||||
GXV_StateTable_OptData_Load_Func
|
||||
optdata_load_func;
|
||||
|
||||
} GXV_StateTable_ValidatorRec, *GXV_StateTable_ValidatorRecData;
|
||||
|
||||
|
||||
/* ---------------------- 32bit XStateTable ---------------------------- */
|
||||
|
||||
typedef GXV_StateTable_GlyphOffsetDesc GXV_XStateTable_GlyphOffsetDesc;
|
||||
|
||||
typedef void (*GXV_XStateTable_Subtable_Setup_Func)( FT_ULong table_size,
|
||||
FT_ULong classTable,
|
||||
FT_ULong stateArray,
|
||||
FT_ULong entryTable,
|
||||
FT_ULong* classTable_length_p,
|
||||
FT_ULong* stateArray_length_p,
|
||||
FT_ULong* entryTable_length_p,
|
||||
GXV_Validator valid );
|
||||
|
||||
typedef void (*GXV_XStateTable_Entry_Validate_Func)( FT_UShort state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc
|
||||
glyphOffset,
|
||||
FT_Bytes xstatetable_table,
|
||||
FT_Bytes xstatetable_limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
typedef GXV_StateTable_OptData_Load_Func GXV_XStateTable_OptData_Load_Func;
|
||||
|
||||
typedef struct GXV_XStateTable_ValidatorRec_
|
||||
{
|
||||
int entry_glyphoffset_fmt;
|
||||
void* optdata;
|
||||
GXV_XStateTable_Subtable_Setup_Func
|
||||
subtable_setup_func;
|
||||
GXV_XStateTable_Entry_Validate_Func
|
||||
entry_validate_func;
|
||||
GXV_XStateTable_OptData_Load_Func
|
||||
optdata_load_func;
|
||||
FT_ULong nClasses;
|
||||
FT_UShort maxClassID;
|
||||
|
||||
} GXV_XStateTable_ValidatorRec, *GXV_XStateTable_ValidatorRecData;
|
||||
|
||||
/* ===================================================================== */
|
||||
|
||||
typedef struct GXV_ValidatorRec_
|
||||
{
|
||||
FT_Validator root;
|
||||
|
||||
FT_Face face;
|
||||
void* table_data;
|
||||
|
||||
FT_ULong subtable_length;
|
||||
|
||||
GXV_LookupValue_SignSpec lookupval_sign;
|
||||
GXV_Lookup_Value_Validate_Func lookupval_func;
|
||||
GXV_Lookup_Fmt4_Transit_Func lookupfmt4_trans;
|
||||
FT_Bytes lookuptbl_head;
|
||||
|
||||
GXV_StateTable_ValidatorRec statetable;
|
||||
GXV_XStateTable_ValidatorRec xstatetable;
|
||||
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
FT_UInt debug_indent;
|
||||
const FT_String* debug_function_name[3];
|
||||
#endif
|
||||
|
||||
} GXV_ValidatorRec;
|
||||
|
||||
#define GXV_TABLE_DATA( tag, field ) \
|
||||
( ( (GXV_ ## tag ## _Data)valid->table_data )->field )
|
||||
|
||||
#undef FT_INVALID_
|
||||
#define FT_INVALID_( _prefix, _error ) \
|
||||
ft_validator_error( valid->root, _prefix ## _error )
|
||||
|
||||
#define GXV_LIMIT_CHECK( _count ) \
|
||||
FT_BEGIN_STMNT \
|
||||
if ( p + _count > ( limit? limit : valid->root->limit ) ) \
|
||||
FT_INVALID_TOO_SHORT; \
|
||||
FT_END_STMNT
|
||||
|
||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||
#define GXV_INIT valid->debug_indent = 0
|
||||
|
||||
#define GXV_NAME_ENTER( name ) \
|
||||
FT_BEGIN_STMNT \
|
||||
valid->debug_indent += 2; \
|
||||
FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
|
||||
FT_TRACE4(( "%s table\n", name )); \
|
||||
FT_END_STMNT
|
||||
|
||||
#define GXV_EXIT valid->debug_indent -= 2
|
||||
|
||||
#define GXV_TRACE( s ) \
|
||||
FT_BEGIN_STMNT \
|
||||
FT_TRACE4(( "%*.s", valid->debug_indent, 0 )); \
|
||||
FT_TRACE4( s ); \
|
||||
FT_END_STMNT
|
||||
|
||||
#else /* !FT_DEBUG_LEVEL_TRACE */
|
||||
#define GXV_INIT do ; while ( 0 )
|
||||
#define GXV_NAME_ENTER( name ) do ; while ( 0 )
|
||||
#define GXV_EXIT do ; while ( 0 )
|
||||
|
||||
#define GXV_TRACE( s ) do ; while ( 0 )
|
||||
|
||||
#endif /* !FT_DEBUG_LEVEL_TRACE */
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** 32bit alignment checking *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define GXV_32BIT_ALIGNMENT_VALIDATE( a ) \
|
||||
FT_BEGIN_STMNT \
|
||||
{ \
|
||||
if ( 0 != ( (a) % 4 ) ) FT_INVALID_OFFSET ; \
|
||||
} \
|
||||
FT_END_STMNT
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Dumping Binary Data *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define GXV_TRACE_HEXDUMP( p, len ) \
|
||||
FT_BEGIN_STMNT \
|
||||
{ \
|
||||
FT_Bytes b; \
|
||||
for (b = p; b < (FT_Bytes)p + len; b++) \
|
||||
FT_TRACE1(("\\x%02x", *b)) ; \
|
||||
} \
|
||||
FT_END_STMNT
|
||||
|
||||
#define GXV_TRACE_HEXDUMP_C( p, len ) \
|
||||
FT_BEGIN_STMNT \
|
||||
{ \
|
||||
FT_Bytes b; \
|
||||
for (b = p; b < (FT_Bytes)p + len; b++) \
|
||||
if (0x40 < *b && *b < 0x7e) \
|
||||
FT_TRACE1(("%c", *b)) ; \
|
||||
else \
|
||||
FT_TRACE1(("\\x%02x", *b)) ; \
|
||||
} \
|
||||
FT_END_STMNT
|
||||
|
||||
#define GXV_TRACE_HEXDUMP_SFNTNAME( n ) GXV_TRACE_HEXDUMP( n.string, n.string_len )
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** LOOKUP TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_BinSrchHeader_validate( FT_Bytes p,
|
||||
FT_Bytes limit,
|
||||
FT_UShort* unitSize_p,
|
||||
FT_UShort* nUnits_p,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_LookupTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Glyph ID *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL( FT_Int )
|
||||
gxv_glyphid_validate( FT_UShort gid,
|
||||
GXV_Validator valid );
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** CONTROL POINT *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_ctlPoint_validate( FT_UShort gid,
|
||||
FT_Short ctl_point,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** SFNT NAME *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_sfntName_validate( FT_UShort name_index,
|
||||
FT_UShort min_index,
|
||||
FT_UShort max_index,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** STATE TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_StateTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY MACRO *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define GXV_SUBTABLE_OFFSET_CHECK( _offset ) \
|
||||
FT_BEGIN_STMNT \
|
||||
if ( (_offset) > valid->subtable_length ) \
|
||||
FT_INVALID_OFFSET; \
|
||||
FT_END_STMNT
|
||||
|
||||
#define GXV_SUBTABLE_LIMIT_CHECK( _count ) \
|
||||
FT_BEGIN_STMNT \
|
||||
if ( ( p + (_count) - valid->subtable_start ) > valid->subtable_length ) \
|
||||
FT_INVALID_TOO_SHORT; \
|
||||
FT_END_STMNT
|
||||
|
||||
#define GXV_USHORT_TO_SHORT( _us ) \
|
||||
( ( 0x8000 < ( _us ) ) ? ( ( _us ) - 0x8000 ) : ( _us ) )
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Table overlapping *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct GXV_odtect_DataRec_
|
||||
{
|
||||
FT_Bytes start;
|
||||
FT_ULong length;
|
||||
FT_String* name;
|
||||
|
||||
} GXV_odtect_DataRec, *GXV_odtect_Data;
|
||||
|
||||
typedef struct GXV_odtect_RangeRec_
|
||||
{
|
||||
FT_UInt nRanges;
|
||||
GXV_odtect_Data range;
|
||||
|
||||
} GXV_odtect_RangeRec, *GXV_odtect_Range;
|
||||
|
||||
#define GXV_ODTECT( n, odtect ) \
|
||||
GXV_odtect_DataRec odtect ## _range[ n ]; \
|
||||
GXV_odtect_RangeRec odtect ## _rec = { 0, NULL }; \
|
||||
GXV_odtect_Range odtect = NULL
|
||||
|
||||
#define GXV_ODTECT_INIT( odtect ) \
|
||||
FT_BEGIN_STMNT \
|
||||
odtect ## _rec.nRanges = 0; \
|
||||
odtect ## _rec.range = odtect ## _range; \
|
||||
odtect = & odtect ## _rec; \
|
||||
FT_END_STMNT
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* Not def: __GXVCOMMN_H__ */
|
||||
|
||||
|
||||
/* END */
|
48
src/gxvalid/gxverror.h
Normal file
48
src/gxvalid/gxverror.h
Normal file
@ -0,0 +1,48 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxverror.h */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT validation module error codes (specification only). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* This file is used to define the OpenType validation module error */
|
||||
/* enumeration constants. */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef __GXVERROR_H__
|
||||
#define __GXVERROR_H__
|
||||
|
||||
#include FT_MODULE_ERRORS_H
|
||||
|
||||
#undef __FTERRORS_H__
|
||||
|
||||
#define FT_ERR_PREFIX GXV_Err_
|
||||
#define FT_ERR_BASE FT_Mod_Err_GXV
|
||||
|
||||
#define FT_KEEP_ERR_PREFIX
|
||||
|
||||
#include FT_ERRORS_H
|
||||
|
||||
#endif /* __GXVERROR_H__ */
|
||||
|
||||
|
||||
/* END */
|
464
src/gxvalid/gxvfeat.c
Normal file
464
src/gxvalid/gxvfeat.c
Normal file
@ -0,0 +1,464 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvfeat.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT feat table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvfeat
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Registry predefined by Apple *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/* TODO: More compact format */
|
||||
typedef struct GXV_Feature_RegistryRec_
|
||||
{
|
||||
FT_Bool existence;
|
||||
FT_Bool apple_reserved;
|
||||
FT_Bool exclusive;
|
||||
FT_Byte nSettings;
|
||||
|
||||
} GX_Feature_RegistryRec;
|
||||
#define gxv_feat_registry_length ( sizeof ( gxv_feat_registry ) / sizeof ( GX_Feature_RegistryRec ) )
|
||||
|
||||
static GX_Feature_RegistryRec gxv_feat_registry [] =
|
||||
{
|
||||
/* Generated from gxvfgen.c */
|
||||
{1, 0, 0, 1}, /* All Typographic Features */
|
||||
{1, 0, 0, 8}, /* Ligatures */
|
||||
{1, 0, 1, 3}, /* Cursive Connection */
|
||||
{1, 0, 1, 6}, /* Letter Case */
|
||||
{1, 0, 0, 1}, /* Vertical Substitution */
|
||||
{1, 0, 0, 1}, /* Linguistic Rearrangement */
|
||||
{1, 0, 1, 2}, /* Number Spacing */
|
||||
{1, 1, 0, 0}, /* Apple Reserved 1 */
|
||||
{1, 0, 0, 5}, /* Smart Swashes */
|
||||
{1, 0, 1, 3}, /* Diacritics */
|
||||
{1, 0, 1, 4}, /* Vertical Position */
|
||||
{1, 0, 1, 3}, /* Fractions */
|
||||
{1, 1, 0, 0}, /* Apple Reserved 2 */
|
||||
{1, 0, 0, 1}, /* Overlapping Characters */
|
||||
{1, 0, 0, 6}, /* Typographic Extras */
|
||||
{1, 0, 0, 5}, /* Mathematical Extras */
|
||||
{1, 0, 1, 7}, /* Ornament Sets */
|
||||
{1, 0, 1, 1}, /* Character Alternatives */
|
||||
{1, 0, 1, 5}, /* Design Complexity */
|
||||
{1, 0, 1, 6}, /* Style Options */
|
||||
{1, 0, 1, 11}, /* Character Shape */
|
||||
{1, 0, 1, 2}, /* Number Case */
|
||||
{1, 0, 1, 4}, /* Text Spacing */
|
||||
{1, 0, 1, 10}, /* Transliteration */
|
||||
{1, 0, 1, 9}, /* Annotation */
|
||||
{1, 0, 1, 2}, /* Kana Spacing */
|
||||
{1, 0, 1, 2}, /* Ideographic Spacing */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{0, 0, 0, 0}, /* __EMPTY__ */
|
||||
{1, 0, 1, 4}, /* Text Spacing */
|
||||
{1, 0, 1, 2}, /* Kana Spacing */
|
||||
{1, 0, 1, 2}, /* Ideographic Spacing */
|
||||
{1, 0, 1, 4}, /* CJK Roman Spacing */
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
typedef struct GXV_feat_DataRec_
|
||||
{
|
||||
FT_UInt reserved_size;
|
||||
FT_UShort feature;
|
||||
FT_UShort setting;
|
||||
|
||||
} GXV_feat_DataRec, *GXV_feat_Data;
|
||||
#define GXV_FEAT_DATA(field) GXV_TABLE_DATA( feat, field )
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GXV_FEAT_MASK_EXCLUSIVE_SETTINGS = 0x8000,
|
||||
GXV_FEAT_MASK_DYNAMIC_DEFAULT = 0x4000,
|
||||
GXV_FEAT_MASK_UNUSED = 0x3F00,
|
||||
GXV_FEAT_MASK_DEFAULT_SETTING = 0x00FF
|
||||
|
||||
} GXV_FeatureFlagsMask ;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_feat_registry_validate( FT_UShort feature,
|
||||
FT_UShort nSettings,
|
||||
FT_Bool exclusive,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_NAME_ENTER( "feature in registry" );
|
||||
|
||||
GXV_TRACE(( " (feature = %u)\n", feature ));
|
||||
|
||||
if ( feature >= gxv_feat_registry_length )
|
||||
{
|
||||
GXV_TRACE(( "feature number %d is out of range %d\n",
|
||||
feature, gxv_feat_registry_length ));
|
||||
if ( valid->root->level == FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( gxv_feat_registry[feature].existence == 0 )
|
||||
{
|
||||
GXV_TRACE(( "feature number %d is in define range but inexistent\n",
|
||||
feature ));
|
||||
if ( valid->root->level == FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( gxv_feat_registry[feature].apple_reserved )
|
||||
{
|
||||
/* Don't use here. Apple is reserved. */
|
||||
GXV_TRACE(( "feature number %d is reserved by Apple\n",
|
||||
feature ));
|
||||
if ( valid->root->level >= FT_VALIDATE_TIGHT )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
if ( nSettings != gxv_feat_registry[feature].nSettings )
|
||||
{
|
||||
GXV_TRACE(( "feature %d: nSettings %d != defined nSettings %d\n",
|
||||
feature, nSettings, gxv_feat_registry[feature].nSettings ));
|
||||
if ( valid->root->level >= FT_VALIDATE_TIGHT )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
if ( exclusive != gxv_feat_registry[feature].exclusive )
|
||||
{
|
||||
GXV_TRACE(( "exclusive flag %d differs from predefined value\n",
|
||||
exclusive ));
|
||||
if ( valid->root->level >= FT_VALIDATE_TIGHT )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
Exit:
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_feat_name_index_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
FT_Short nameIndex;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "nameIndex" );
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
nameIndex = FT_NEXT_SHORT ( p );
|
||||
GXV_TRACE(( " (nameIndex = %d)\n", nameIndex ));
|
||||
|
||||
gxv_sfntName_validate( (FT_UShort)nameIndex,
|
||||
255,
|
||||
32768,
|
||||
valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_feat_setting_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
FT_Bool exclusive,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort setting;
|
||||
|
||||
GXV_NAME_ENTER( "setting" );
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
|
||||
setting = FT_NEXT_USHORT( p );
|
||||
|
||||
/* If exclusive setting, setting should be odd. */
|
||||
if ( exclusive && ( ( setting % 2 ) == 0 ) )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
gxv_feat_name_index_validate( p, limit, valid );
|
||||
|
||||
GXV_FEAT_DATA( setting ) = setting;
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_feat_name_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UInt reserved_size = GXV_FEAT_DATA( reserved_size );
|
||||
|
||||
FT_UShort feature;
|
||||
FT_UShort nSettings;
|
||||
FT_UInt settingTable;
|
||||
FT_UShort featureFlags;
|
||||
|
||||
FT_Bool exclusive;
|
||||
FT_Int last_setting;
|
||||
FT_Int i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "name" );
|
||||
|
||||
/* feature + nSettings + settingTable + featureFlags */
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 );
|
||||
|
||||
feature = FT_NEXT_USHORT( p );
|
||||
GXV_FEAT_DATA( feature ) = feature;
|
||||
|
||||
nSettings = FT_NEXT_USHORT( p );
|
||||
settingTable = FT_NEXT_ULONG ( p );
|
||||
featureFlags = FT_NEXT_USHORT( p );
|
||||
|
||||
if ( settingTable < reserved_size )
|
||||
FT_INVALID_OFFSET;
|
||||
|
||||
if ( valid->root->level == FT_VALIDATE_PARANOID &&
|
||||
(featureFlags & GXV_FEAT_MASK_UNUSED) == 0 )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
exclusive = featureFlags & GXV_FEAT_MASK_EXCLUSIVE_SETTINGS;
|
||||
if ( exclusive )
|
||||
{
|
||||
FT_Byte dynamic_default;
|
||||
|
||||
|
||||
if (featureFlags & GXV_FEAT_MASK_DYNAMIC_DEFAULT)
|
||||
dynamic_default = featureFlags & GXV_FEAT_MASK_DEFAULT_SETTING;
|
||||
else
|
||||
dynamic_default = 0;
|
||||
|
||||
/* If exclusive, check whether default setting is in the range. */
|
||||
if ( !( dynamic_default < nSettings ) )
|
||||
FT_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
gxv_feat_registry_validate( feature, nSettings, exclusive, valid );
|
||||
|
||||
gxv_feat_name_index_validate( p, limit, valid );
|
||||
|
||||
p = valid->root->base + settingTable;
|
||||
for ( last_setting = -1, i = 0; i < nSettings; i++ )
|
||||
{
|
||||
gxv_feat_setting_validate( p, limit, exclusive, valid );
|
||||
|
||||
if ( valid->root->level == FT_VALIDATE_PARANOID &&
|
||||
(FT_Int)GXV_FEAT_DATA( setting ) <= last_setting )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
last_setting = (FT_Int)GXV_FEAT_DATA( setting );
|
||||
/* setting + nameIndex */
|
||||
p += ( 2 + 2 );
|
||||
}
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** feat TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_feat_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
|
||||
GXV_feat_DataRec featrec;
|
||||
GXV_feat_Data feat = &featrec;
|
||||
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
|
||||
FT_UInt featureNameCount;
|
||||
|
||||
FT_Int i;
|
||||
FT_Int last_feature;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = feat;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation feat table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
feat->reserved_size = 0;
|
||||
|
||||
/* version + featureNameCount + none_0 + none_1 */
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 );
|
||||
feat->reserved_size += 4 + 2 + 2 + 4;
|
||||
|
||||
if ( FT_NEXT_ULONG( p ) != 0x00010000UL ) /* Version */
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
featureNameCount = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount ));
|
||||
|
||||
if ( valid->root->level != FT_VALIDATE_PARANOID )
|
||||
p += 6; /* skip (none) and (none) */
|
||||
else
|
||||
{
|
||||
if ( FT_NEXT_USHORT( p ) != 0 )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
if ( FT_NEXT_ULONG( p ) != 0 )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
feat->reserved_size += ( featureNameCount * ( 2 + 2 + 4 + 2 + 2 ) );
|
||||
for( last_feature = -1, i = 0; i < featureNameCount; i++ )
|
||||
{
|
||||
gxv_feat_name_validate( p, limit, valid );
|
||||
|
||||
if ( valid->root->level == FT_VALIDATE_PARANOID &&
|
||||
(FT_Int)GXV_FEAT_DATA( feature ) <= last_feature )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
last_feature = GXV_FEAT_DATA( feature );
|
||||
p += ( 2 + 2 + 4 + 2 + 2 );
|
||||
}
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
471
src/gxvalid/gxvfgen.c
Normal file
471
src/gxvalid/gxvfgen.c
Normal file
@ -0,0 +1,471 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxfgen.c */
|
||||
/* */
|
||||
/* Generate feature registry infomations for gxv feat validator. */
|
||||
/* This program is derived from gxfeatreg.c in gxlayout. */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by Masatake YAMATO and Redhat K.K. */
|
||||
/* */
|
||||
/* This file 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxfeatreg.c */
|
||||
/* */
|
||||
/* Database of font features pre-defined by Apple Computer, Inc. */
|
||||
/* http://developer.apple.com/fonts/Registry/ */
|
||||
/* (body). */
|
||||
/* */
|
||||
/* Copyright 2003 by */
|
||||
/* Masatake YAMATO and Redhat K.K. */
|
||||
/* */
|
||||
/* This file 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* Development of gxfeatreg.c is support of */
|
||||
/* Information-technology Promotion Agency, Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* This file is compiled to a standalone executable. */
|
||||
/* This file is never compiled into `libfreetype2'. */
|
||||
/* The output of this file is used in `gxvfeat.c'. */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* Compile: gcc `pkg-config --cflags freetype2` gxvfgen.c -o gxvfgen */
|
||||
/* Run: ./gxvfgen > tmp.c */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
|
||||
/***************************************************************************/
|
||||
/*
|
||||
* If you add a new setting to a feature, check the number of setting
|
||||
* in the feature. If the number is greater than value defined as
|
||||
* FEATREG_MAX_SETTING, update the value.
|
||||
*/
|
||||
#define FEATREG_MAX_SETTING 12
|
||||
/***************************************************************************/
|
||||
/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
|
||||
/***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
#define APPLE_RESERVED "Apple Reserved"
|
||||
#define APPLE_RESERVED_LENGTH 14
|
||||
|
||||
typedef struct GX_Feature_RegistryRec_
|
||||
{
|
||||
const char* feat_name;
|
||||
char exclusive;
|
||||
char* setting_name [FEATREG_MAX_SETTING];
|
||||
|
||||
} GX_Feature_RegistryRec;
|
||||
|
||||
#define EMPTYFEAT {0, 0, {NULL}}
|
||||
static GX_Feature_RegistryRec featreg_table [] = {
|
||||
{ /* 0 */
|
||||
"All Typographic Features",
|
||||
0,
|
||||
{
|
||||
"All Type Features",
|
||||
NULL
|
||||
}
|
||||
}, { /* 1 */
|
||||
"Ligatures",
|
||||
0,
|
||||
{
|
||||
"Required Ligatures",
|
||||
"Common Ligatures",
|
||||
"Rare Ligatures",
|
||||
"Logos",
|
||||
"Rebus Pictures",
|
||||
"Diphthong Ligatures",
|
||||
"Squared Ligatures",
|
||||
"Squared Ligatures, Abbreviated",
|
||||
NULL
|
||||
}
|
||||
}, { /* 2 */
|
||||
"Cursive Connection",
|
||||
1,
|
||||
{
|
||||
"Unconnected",
|
||||
"Partially Connected",
|
||||
"Cursive",
|
||||
NULL
|
||||
}
|
||||
}, { /* 3 */
|
||||
"Letter Case",
|
||||
1,
|
||||
{
|
||||
"Upper & Lower Case",
|
||||
"All Caps",
|
||||
"All Lower Case",
|
||||
"Small Caps",
|
||||
"Initial Caps",
|
||||
"Initial Caps & Small Caps",
|
||||
NULL
|
||||
}
|
||||
}, { /* 4 */
|
||||
"Vertical Substitution",
|
||||
0,
|
||||
{
|
||||
/* "Substitute Vertical Forms", */
|
||||
"Turns on the feature",
|
||||
NULL
|
||||
}
|
||||
}, { /* 5 */
|
||||
"Linguistic Rearrangement",
|
||||
0,
|
||||
{
|
||||
/* "Linguistic Rearrangement", */
|
||||
"Turns on the feature",
|
||||
NULL
|
||||
}
|
||||
}, { /* 6 */
|
||||
"Number Spacing",
|
||||
1,
|
||||
{
|
||||
"Monospaced Numbers",
|
||||
"Proportional Numbers",
|
||||
NULL
|
||||
}
|
||||
}, { /* 7 */
|
||||
APPLE_RESERVED " 1",
|
||||
0,
|
||||
{NULL}
|
||||
}, { /* 8 */
|
||||
"Smart Swashes",
|
||||
0,
|
||||
{
|
||||
"Word Initial Swashes",
|
||||
"Word Final Swashes",
|
||||
"Line Initial Swashes",
|
||||
"Line Final Swashes",
|
||||
"Non-Final Swashes",
|
||||
NULL
|
||||
}
|
||||
}, { /* 9 */
|
||||
"Diacritics",
|
||||
1,
|
||||
{
|
||||
"Show Diacritics",
|
||||
"Hide Diacritics",
|
||||
"Decompose Diacritics",
|
||||
NULL
|
||||
}
|
||||
}, { /* 10 */
|
||||
"Vertical Position",
|
||||
1,
|
||||
{
|
||||
/* "Normal Position", */
|
||||
"No Vertical Position",
|
||||
"Superiors",
|
||||
"Inferiors",
|
||||
"Ordinals",
|
||||
NULL
|
||||
}
|
||||
}, { /* 11 */
|
||||
"Fractions",
|
||||
1,
|
||||
{
|
||||
"No Fractions",
|
||||
"Vertical Fractions",
|
||||
"Diagonal Fractions",
|
||||
NULL
|
||||
}
|
||||
}, { /* 12 */
|
||||
APPLE_RESERVED " 2",
|
||||
0,
|
||||
{NULL}
|
||||
}, { /* 13 */
|
||||
"Overlapping Characters",
|
||||
0,
|
||||
{
|
||||
/* "Prevent Overlap", */
|
||||
"Turns on the feature",
|
||||
NULL
|
||||
}
|
||||
}, { /* 14 */
|
||||
"Typographic Extras",
|
||||
0,
|
||||
{
|
||||
"Hyphens to Em Dash",
|
||||
"Hyphens to En Dash",
|
||||
"Unslashed Zero",
|
||||
"Form Interrobang",
|
||||
"Smart Quotes",
|
||||
"Periods to Ellipsis",
|
||||
NULL
|
||||
}
|
||||
}, { /* 15 */
|
||||
"Mathematical Extras",
|
||||
0,
|
||||
{
|
||||
"Hyphens to Minus",
|
||||
"Asterisk to Multiply",
|
||||
"Slash to Divide",
|
||||
"Inequality Ligatures",
|
||||
"Exponents",
|
||||
NULL
|
||||
}
|
||||
}, { /* 16 */
|
||||
"Ornament Sets",
|
||||
1,
|
||||
{
|
||||
"No Ornaments",
|
||||
"Dingbats",
|
||||
"Pi Characters",
|
||||
"Fleurons",
|
||||
"Decorative Borders",
|
||||
"International Symbols",
|
||||
"Math Symbols",
|
||||
NULL
|
||||
}
|
||||
}, { /* 17 */
|
||||
"Character Alternatives",
|
||||
1,
|
||||
{
|
||||
"No Alternates",
|
||||
/* TODO */
|
||||
NULL
|
||||
}
|
||||
}, { /* 18 */
|
||||
"Design Complexity",
|
||||
1,
|
||||
{
|
||||
"Design Level 1",
|
||||
"Design Level 2",
|
||||
"Design Level 3",
|
||||
"Design Level 4",
|
||||
"Design Level 5",
|
||||
/* TODO */
|
||||
NULL
|
||||
}
|
||||
}, { /* 19 */
|
||||
"Style Options",
|
||||
1,
|
||||
{
|
||||
"No Style Options",
|
||||
"Display Text",
|
||||
"Engraved Text",
|
||||
"Illuminated Caps",
|
||||
"Tilling Caps",
|
||||
"Tall Caps",
|
||||
NULL
|
||||
}
|
||||
}, { /* 20 */
|
||||
"Character Shape",
|
||||
1,
|
||||
{
|
||||
"Traditional Characters",
|
||||
"Simplified Characters",
|
||||
"JIS 1978 Characters",
|
||||
"JIS 1983 Characters",
|
||||
"JIS 1990 Characters",
|
||||
"Traditional Characters, Alternative Set 1",
|
||||
"Traditional Characters, Alternative Set 2",
|
||||
"Traditional Characters, Alternative Set 3",
|
||||
"Traditional Characters, Alternative Set 4",
|
||||
"Traditional Characters, Alternative Set 5",
|
||||
"Expert Characters",
|
||||
NULL /* count=>12 */
|
||||
}
|
||||
}, { /* 21 */
|
||||
"Number Case",
|
||||
1,
|
||||
{
|
||||
"Lower Case Numbers",
|
||||
"Upper Case Numbers",
|
||||
NULL
|
||||
}
|
||||
}, { /* 22 */
|
||||
"Text Spacing",
|
||||
1,
|
||||
{
|
||||
"Proportional",
|
||||
"Monospaced",
|
||||
"Half-width",
|
||||
"Normal",
|
||||
NULL
|
||||
}
|
||||
}, /* Here after Newer */ { /* 23 */
|
||||
"Transliteration",
|
||||
1,
|
||||
{
|
||||
"No Transliteration",
|
||||
"Hanja To Hangul",
|
||||
"Hiragana to Katakana",
|
||||
"Katakana to Hiragana",
|
||||
"Kana to Romanization",
|
||||
"Romanization to Hiragana",
|
||||
"Romanization to Katakana",
|
||||
"Hanja to Hangul, Alternative Set 1",
|
||||
"Hanja to Hangul, Alternative Set 2",
|
||||
"Hanja to Hangul, Alternative Set 3",
|
||||
NULL
|
||||
}
|
||||
}, { /* 24 */
|
||||
"Annotation",
|
||||
1,
|
||||
{
|
||||
"No Annotation",
|
||||
"Box Annotation",
|
||||
"Rounded Box Annotation",
|
||||
"Circle Annotation",
|
||||
"Inverted Circle Annotation",
|
||||
"Parenthesis Annotation",
|
||||
"Period Annotation",
|
||||
"Roman Numeral Annotation",
|
||||
"Diamond Annotation",
|
||||
NULL
|
||||
}
|
||||
}, { /* 25 */
|
||||
"Kana Spacing",
|
||||
1,
|
||||
{
|
||||
"Full Width",
|
||||
"Proportional",
|
||||
NULL
|
||||
}
|
||||
}, { /* 26 */
|
||||
"Ideographic Spacing",
|
||||
1,
|
||||
{
|
||||
"Full Width",
|
||||
"Proportional",
|
||||
NULL
|
||||
}
|
||||
}, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 27-30 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 31-35 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 36-40 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 40-45 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 46-50 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 51-55 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 56-60 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 61-65 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 66-70 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 71-75 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 76-80 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 81-85 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 86-90 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 91-95 */
|
||||
EMPTYFEAT, EMPTYFEAT, EMPTYFEAT, /* 96-98 */
|
||||
EMPTYFEAT, /* 99 */ { /* 100 => 22*/
|
||||
"Text Spacing",
|
||||
1,
|
||||
{
|
||||
"Proportional",
|
||||
"Monospaced",
|
||||
"Half-width",
|
||||
"Normal",
|
||||
NULL
|
||||
}
|
||||
}, { /* 101 => 25 */
|
||||
"Kana Spacing",
|
||||
1,
|
||||
{
|
||||
"Full Width",
|
||||
"Proportional",
|
||||
NULL
|
||||
}
|
||||
}, { /* 102 => 26 */
|
||||
"Ideographic Spacing",
|
||||
1,
|
||||
{
|
||||
"Full Width",
|
||||
"Proportional",
|
||||
NULL
|
||||
}
|
||||
}, { /* 103 */
|
||||
"CJK Roman Spacing",
|
||||
1,
|
||||
{
|
||||
"Half-width",
|
||||
"Proportional",
|
||||
"Default Roman",
|
||||
"Full-width Roman",
|
||||
NULL
|
||||
}
|
||||
}, { /* 104 => 1 */
|
||||
"All Typographic Features",
|
||||
0,
|
||||
{
|
||||
"All Type Features",
|
||||
NULL
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Generator *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
int
|
||||
main( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
printf( " {\n" );
|
||||
printf( " /* Generated from %s */\n", __FILE__ );
|
||||
|
||||
for ( i = 0;
|
||||
i < sizeof ( featreg_table ) / sizeof ( GX_Feature_RegistryRec );
|
||||
i++ )
|
||||
{
|
||||
const char* feat_name;
|
||||
int nSettings;
|
||||
|
||||
feat_name = featreg_table[i].feat_name;
|
||||
for ( nSettings = 0;
|
||||
featreg_table[i].setting_name[nSettings];
|
||||
nSettings++)
|
||||
0; /* Do nothing */
|
||||
|
||||
printf( " {%1d, %1d, %1d, %2d}, /* %s */\n",
|
||||
feat_name ? 1 : 0,
|
||||
( feat_name &&
|
||||
( strncmp( feat_name, APPLE_RESERVED, APPLE_RESERVED_LENGTH ) == 0 )
|
||||
) ? 1 : 0,
|
||||
featreg_table[i].exclusive ? 1 : 0,
|
||||
nSettings,
|
||||
feat_name ? feat_name : "__EMPTY__" );
|
||||
}
|
||||
|
||||
printf( " };\n" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* END */
|
588
src/gxvalid/gxvjust.c
Normal file
588
src/gxvalid/gxvjust.c
Normal file
@ -0,0 +1,588 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvjust.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT just table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
#include FT_SFNT_NAMES_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvjust
|
||||
|
||||
/*
|
||||
* refered just table format specification:
|
||||
* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6just.html
|
||||
* last update is 2000.
|
||||
* ----------------------------------------------
|
||||
* [JUST HEADER]: GXV_JUST_HEADER_SIZE
|
||||
* version (fixed: 32bit) = 0x00010000
|
||||
* format (uint16: 16bit) = 0 is only defined (2000)
|
||||
* horizOffset (uint16: 16bit)
|
||||
* vertOffset (uint16: 16bit)
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
typedef struct GXV_just_DataRec_
|
||||
{
|
||||
FT_UShort wdc_offset_max;
|
||||
FT_UShort wdc_offset_min;
|
||||
FT_UShort pc_offset_max;
|
||||
FT_UShort pc_offset_min;
|
||||
|
||||
} GXV_just_DataRec, *GXV_just_Data;
|
||||
|
||||
#define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
|
||||
|
||||
static void
|
||||
gxv_just_wdp_entry_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_ULong justClass;
|
||||
FT_Fixed beforeGrowLimit;
|
||||
FT_Fixed beforeShrinkGrowLimit;
|
||||
FT_Fixed afterGrowLimit;
|
||||
FT_Fixed afterShrinkGrowLimit;
|
||||
FT_UShort growFlags;
|
||||
FT_UShort shrinkFlags;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
|
||||
justClass = FT_NEXT_ULONG( p );
|
||||
beforeGrowLimit = FT_NEXT_ULONG( p );
|
||||
beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
|
||||
afterGrowLimit = FT_NEXT_ULONG( p );
|
||||
afterShrinkGrowLimit = FT_NEXT_ULONG( p );
|
||||
growFlags = FT_NEXT_USHORT( p );
|
||||
shrinkFlags = FT_NEXT_USHORT( p );
|
||||
|
||||
/* TODO: decode flags for human readabilty */
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_wdc_entry_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_ULong count, i;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 );
|
||||
count = FT_NEXT_ULONG( p );
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
GXV_TRACE(( "validate wdc pair %d/%d\n", i + 1, count ));
|
||||
gxv_just_wdp_entry_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_just_widthDeltaClusters_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table ;
|
||||
FT_Bytes wdc_end = table + GXV_JUST_DATA( wdc_offset_max );
|
||||
FT_UInt i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "just justDeltaClusters" );
|
||||
|
||||
if ( limit <= wdc_end )
|
||||
FT_INVALID_OFFSET;
|
||||
for ( i = 0; p <= wdc_end; i++ )
|
||||
{
|
||||
gxv_just_wdc_entry_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_actSubrecord_type0_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_Fixed lowerLimit;
|
||||
FT_Fixed upperLimit;
|
||||
FT_UShort order;
|
||||
FT_UShort decomposedCount;
|
||||
FT_UInt i;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
|
||||
lowerLimit = FT_NEXT_ULONG( p );
|
||||
upperLimit = FT_NEXT_ULONG( p );
|
||||
order = FT_NEXT_USHORT( p );
|
||||
decomposedCount = FT_NEXT_USHORT( p );
|
||||
|
||||
for ( i = 0; i < decomposedCount; i++ )
|
||||
{
|
||||
FT_UShort glyphs;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
glyphs = FT_NEXT_USHORT( p );
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_actSubrecord_type1_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort addGlyph;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
addGlyph = FT_NEXT_USHORT( p );
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_actSubrecord_type2_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
|
||||
FT_UShort addGlyph;
|
||||
FT_UShort substGlyph;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 );
|
||||
substThreshhold = FT_NEXT_ULONG( p );
|
||||
addGlyph = FT_NEXT_USHORT( p );
|
||||
substGlyph = FT_NEXT_USHORT( p );
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_just_actSubrecord_type4_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_ULong variantsAxis;
|
||||
FT_Fixed minimumLimit;
|
||||
FT_Fixed noStretchValue;
|
||||
FT_Fixed maximumLimit;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
|
||||
variantsAxis = FT_NEXT_ULONG( p );
|
||||
minimumLimit = FT_NEXT_ULONG( p );
|
||||
noStretchValue = FT_NEXT_ULONG( p );
|
||||
maximumLimit = FT_NEXT_ULONG( p );
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_just_actSubrecord_type5_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort flags;
|
||||
FT_UShort glyph;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 );
|
||||
flags = FT_NEXT_USHORT( p );
|
||||
glyph = FT_NEXT_USHORT( p );
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
}
|
||||
|
||||
|
||||
/* parse single actSubrecord */
|
||||
static void
|
||||
gxv_just_actSubrecord_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort actionClass;
|
||||
FT_UShort actionType;
|
||||
FT_ULong actionLength;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "just actSubrecord" );
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 4 );
|
||||
actionClass = FT_NEXT_USHORT( p );
|
||||
actionType = FT_NEXT_USHORT( p );
|
||||
actionLength = FT_NEXT_ULONG( p );
|
||||
|
||||
if ( actionType == 0 )
|
||||
gxv_just_actSubrecord_type0_validate( p, limit, valid );
|
||||
else if ( actionType == 1 )
|
||||
gxv_just_actSubrecord_type1_validate( p, limit, valid );
|
||||
else if ( actionType == 2 )
|
||||
gxv_just_actSubrecord_type2_validate( p, limit, valid );
|
||||
else if ( actionType == 3 )
|
||||
; /* Stretch glyph action: no actionData */
|
||||
else if ( actionType == 4 )
|
||||
gxv_just_actSubrecord_type4_validate( p, limit, valid );
|
||||
else if ( actionType == 5 )
|
||||
gxv_just_actSubrecord_type5_validate( p, limit, valid );
|
||||
else
|
||||
FT_INVALID_DATA;
|
||||
|
||||
valid->subtable_length = actionLength;
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_pcActionRecord_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_ULong actionCount;
|
||||
FT_ULong i;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 );
|
||||
actionCount = FT_NEXT_ULONG( p );
|
||||
GXV_TRACE(( "actionCount = %d\n", actionCount ));
|
||||
|
||||
for ( i = 0; i < actionCount; i++ )
|
||||
{
|
||||
gxv_just_actSubrecord_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_pcTable_LookupValue_entry_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
if ( value.u > GXV_JUST_DATA( pc_offset_max ) )
|
||||
GXV_JUST_DATA( pc_offset_max ) = value.u;
|
||||
if ( value.u < GXV_JUST_DATA( pc_offset_max ) )
|
||||
GXV_JUST_DATA( pc_offset_min ) = value.u;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_pcLookupTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
GXV_NAME_ENTER( "just pcLookupTable" );
|
||||
GXV_JUST_DATA( pc_offset_max ) = 0x0000;
|
||||
GXV_JUST_DATA( pc_offset_min ) = 0xFFFF;
|
||||
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_just_pcTable_LookupValue_entry_validate;
|
||||
gxv_LookupTable_validate( p, limit, valid );
|
||||
/* subtable_length is set by gxv_LookupTable_validate() */
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_postcompTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "just postcompTable" );
|
||||
|
||||
gxv_just_pcLookupTable_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
gxv_just_pcActionRecord_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_classTable_entry_validate( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort setMark;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort markClass;
|
||||
FT_UShort currentClass;
|
||||
|
||||
|
||||
setMark = ( 0x8000 & flags ) / 0x8000;
|
||||
dontAdvance = ( 0x4000 & flags ) / 0x4000;
|
||||
markClass = ( 0x3F80 & flags ) / 0x0080;
|
||||
currentClass = 0x007F & flags ;
|
||||
/* TODO: validate markClass & currentClass */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_justClassTable_validate ( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort length;
|
||||
FT_UShort coverage;
|
||||
FT_ULong subFeatureFlags;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "just justClassTable" );
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 4 );
|
||||
length = FT_NEXT_USHORT( p );
|
||||
coverage = FT_NEXT_USHORT( p );
|
||||
subFeatureFlags = FT_NEXT_ULONG( p );
|
||||
|
||||
GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)", coverage,
|
||||
(0x4000 & coverage) == 0 ? "ascending" : "descending"
|
||||
));
|
||||
|
||||
valid->statetable.optdata = NULL;
|
||||
valid->statetable.optdata_load_func = NULL;
|
||||
valid->statetable.subtable_setup_func = NULL;
|
||||
valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
|
||||
valid->statetable.entry_validate_func = gxv_just_classTable_entry_validate;
|
||||
gxv_StateTable_validate( p, table + length, valid );
|
||||
/* subtable_length is set by gxv_LookupTable_validate() */
|
||||
GXV_EXIT;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_wdcTable_LookupValue_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
if ( value.u > GXV_JUST_DATA( wdc_offset_max ) )
|
||||
GXV_JUST_DATA( wdc_offset_max ) = value.u;
|
||||
if ( value.u < GXV_JUST_DATA( wdc_offset_min ) )
|
||||
GXV_JUST_DATA( wdc_offset_min ) = value.u;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_just_justData_lookuptable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
|
||||
GXV_JUST_DATA( wdc_offset_max ) = 0x0000;
|
||||
GXV_JUST_DATA( wdc_offset_min ) = 0xFFFF;
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_just_wdcTable_LookupValue_validate;
|
||||
gxv_LookupTable_validate( p, limit, valid );
|
||||
/* subtable_length is set by gxv_LookupTable_validate() */
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gxv_just_justData_validate() parses and validates horizData, vertData.
|
||||
*/
|
||||
static void
|
||||
gxv_just_justData_validate ( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* following 3 offsets are measured from the start of just
|
||||
* which table points to), not justData
|
||||
*/
|
||||
FT_UShort justClassTableOffset;
|
||||
FT_UShort wdcTableOffset;
|
||||
FT_UShort pcTableOffset;
|
||||
FT_Bytes p = table;
|
||||
GXV_ODTECT( 4, odtect );
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "just justData" );
|
||||
|
||||
GXV_ODTECT_INIT( odtect );
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 2 );
|
||||
justClassTableOffset = FT_NEXT_USHORT( p );
|
||||
wdcTableOffset = FT_NEXT_USHORT( p );
|
||||
pcTableOffset = FT_NEXT_USHORT( p );
|
||||
|
||||
GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset ));
|
||||
GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset ));
|
||||
GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset ));
|
||||
|
||||
|
||||
gxv_just_justData_lookuptable_validate( p, limit, valid );
|
||||
gxv_odtect_add_range( p, valid->subtable_length, "just_LookupTable", odtect );
|
||||
|
||||
if ( wdcTableOffset )
|
||||
{
|
||||
gxv_just_widthDeltaClusters_validate( valid->root->base + wdcTableOffset,
|
||||
limit, valid );
|
||||
gxv_odtect_add_range( valid->root->base + wdcTableOffset,
|
||||
valid->subtable_length, "just_wdcTable", odtect );
|
||||
}
|
||||
|
||||
if ( pcTableOffset )
|
||||
{
|
||||
gxv_just_postcompTable_validate( valid->root->base + pcTableOffset,
|
||||
limit, valid );
|
||||
gxv_odtect_add_range( valid->root->base + pcTableOffset,
|
||||
valid->subtable_length, "just_pcTable", odtect );
|
||||
}
|
||||
|
||||
if ( justClassTableOffset )
|
||||
{
|
||||
gxv_just_justClassTable_validate( valid->root->base + justClassTableOffset,
|
||||
limit, valid );
|
||||
gxv_odtect_add_range( valid->root->base + justClassTableOffset,
|
||||
valid->subtable_length, "just_justClassTable", odtect );
|
||||
}
|
||||
|
||||
gxv_odtect_validate( odtect, valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_just_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
FT_UInt table_size;
|
||||
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
GXV_just_DataRec justrec;
|
||||
GXV_just_Data just = &justrec;
|
||||
|
||||
FT_ULong version;
|
||||
FT_UShort format;
|
||||
FT_UShort horizOffset;
|
||||
FT_UShort vertOffset;
|
||||
|
||||
GXV_ODTECT( 3, odtect );
|
||||
|
||||
|
||||
GXV_ODTECT_INIT( odtect );
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = just;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation just table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
limit = valid->root->limit;
|
||||
table_size = limit - table;
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
format = FT_NEXT_USHORT( p );
|
||||
horizOffset = FT_NEXT_USHORT( p );
|
||||
vertOffset = FT_NEXT_USHORT( p );
|
||||
gxv_odtect_add_range( table, p - table, "just header", odtect );
|
||||
|
||||
|
||||
/* Version 1.0 (always:2000) */
|
||||
GXV_TRACE(( " (version = 0x%08x)\n", version ));
|
||||
if ( version != 0x00010000UL )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
/* format 0 (always:2000) */
|
||||
GXV_TRACE(( " (format = 0x%04x)\n", format ));
|
||||
if ( format != 0x0000 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
GXV_TRACE(( " (horizOffset = %d)\n", horizOffset ));
|
||||
GXV_TRACE(( " (vertOffset = %d)\n", vertOffset ));
|
||||
|
||||
|
||||
/* validate justData */
|
||||
if ( 0 < horizOffset )
|
||||
{
|
||||
gxv_just_justData_validate( table + horizOffset, limit, valid );
|
||||
gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
|
||||
"horizJustData", odtect );
|
||||
}
|
||||
|
||||
if ( 0 < vertOffset )
|
||||
{
|
||||
gxv_just_justData_validate( table + vertOffset, limit, valid );
|
||||
gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
|
||||
"vertJustData", odtect );
|
||||
}
|
||||
|
||||
gxv_odtect_validate( odtect, valid );
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
801
src/gxvalid/gxvkern.c
Normal file
801
src/gxvalid/gxvkern.c
Normal file
@ -0,0 +1,801 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvkern.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT kern table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
#include FT_SFNT_NAMES_H
|
||||
#include FT_SERVICE_GX_VALIDATE_H
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvkern
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef enum GXV_kern_Version_
|
||||
{
|
||||
KERN_VERSION_CLASSIC = 0x0000,
|
||||
KERN_VERSION_NEW = 0x0001
|
||||
|
||||
} GXV_kern_Version;
|
||||
|
||||
typedef enum GXV_kern_Dialect_
|
||||
{
|
||||
KERN_DIALECT_MS = FT_VALIDATE_MS,
|
||||
KERN_DIALECT_APPLE = FT_VALIDATE_APPLE,
|
||||
KERN_DIALECT_ANY = FT_VALIDATE_CKERN
|
||||
|
||||
} GXV_kern_Dialect;
|
||||
|
||||
typedef struct GXV_kern_DataRec_
|
||||
{
|
||||
GXV_kern_Version version;
|
||||
void *subtable_data;
|
||||
GXV_kern_Dialect dialect_request;
|
||||
|
||||
} GXV_kern_DataRec, *GXV_kern_Data;
|
||||
|
||||
#define GXV_KERN_DATA( field ) GXV_TABLE_DATA( kern, field )
|
||||
|
||||
#define KERN_IS_CLASSIC( valid ) ( KERN_VERSION_CLASSIC == GXV_KERN_DATA( version ) )
|
||||
#define KERN_IS_NEW( valid ) ( KERN_VERSION_NEW == GXV_KERN_DATA( version ) )
|
||||
|
||||
#define KERN_DIALECT( valid ) GXV_KERN_DATA( dialect_request )
|
||||
#define KERN_ALLOWS_MS( valid ) ( KERN_DIALECT( valid ) & KERN_DIALECT_MS )
|
||||
#define KERN_ALLOWS_APPLE( valid ) ( KERN_DIALECT( valid ) & KERN_DIALECT_APPLE )
|
||||
|
||||
#define GXV_KERN_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 4 )
|
||||
#define GXV_KERN_SUBTABLE_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 6 )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** SUBTABLE VALIDATORS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
/* ============================= format 0 ============================== */
|
||||
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_fmt0_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
|
||||
|
||||
FT_UShort nPairs;
|
||||
FT_UShort unitSize;
|
||||
FT_UShort i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER("kern subtable format0");
|
||||
|
||||
unitSize = ( 2 + 2 + 2 );
|
||||
nPairs = 0;
|
||||
|
||||
/* nPairs, searchRange, entrySelector, rangeShift */
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
|
||||
gxv_BinSrchHeader_validate( p, limit, &unitSize, &nPairs, valid );
|
||||
p += 2 + 2 + 2 + 2;
|
||||
|
||||
for ( i = 0; i < nPairs; i++ )
|
||||
{
|
||||
FT_UShort gid_left;
|
||||
FT_UShort gid_right;
|
||||
FT_Short kernValue;
|
||||
/* TODO: should be checked pairs are unique. */
|
||||
|
||||
/* left */
|
||||
gid_left = FT_NEXT_USHORT( p );
|
||||
gxv_glyphid_validate( gid_left, valid );
|
||||
|
||||
/* right */
|
||||
gid_right = FT_NEXT_USHORT( p );
|
||||
gxv_glyphid_validate( gid_right, valid );
|
||||
|
||||
/* skip the kern value */
|
||||
kernValue = FT_NEXT_SHORT( p );
|
||||
}
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* ============================= format 1 ============================== */
|
||||
|
||||
|
||||
typedef struct GXV_kern_fmt1_StateOptRec_
|
||||
{
|
||||
FT_UShort valueTable;
|
||||
FT_UShort valueTable_length;
|
||||
|
||||
} GXV_kern_fmt1_StateOptRec, *GXV_kern_fmt1_StateOptRecData;
|
||||
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_fmt1_valueTable_load( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_kern_fmt1_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
optdata->valueTable = FT_NEXT_USHORT( p );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* passed tables_size covers whole StateTable, including kern fmt1 header
|
||||
*/
|
||||
static void
|
||||
gxv_kern_subtable_fmt1_subtable_setup( FT_UShort table_size,
|
||||
FT_UShort classTable,
|
||||
FT_UShort stateArray,
|
||||
FT_UShort entryTable,
|
||||
FT_UShort* classTable_length_p,
|
||||
FT_UShort* stateArray_length_p,
|
||||
FT_UShort* entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort o[4];
|
||||
FT_UShort *l[4];
|
||||
FT_UShort buff[5];
|
||||
GXV_kern_fmt1_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
|
||||
o[0] = classTable;
|
||||
o[1] = stateArray;
|
||||
o[2] = entryTable;
|
||||
o[3] = optdata->valueTable;
|
||||
l[0] = classTable_length_p;
|
||||
l[1] = stateArray_length_p;
|
||||
l[2] = entryTable_length_p;
|
||||
l[3] = &(optdata->valueTable_length);
|
||||
|
||||
gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* passed table & limit are of whole of StateTable, not included subtables.
|
||||
*/
|
||||
static void
|
||||
gxv_kern_subtable_fmt1_entry_validate( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort push;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort valueOffset;
|
||||
FT_UShort kernAction;
|
||||
FT_UShort kernValue;
|
||||
|
||||
push = flags / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
valueOffset = flags & 0x3FFF;
|
||||
|
||||
{
|
||||
GXV_kern_fmt1_StateOptRecData vt_rec = valid->statetable.optdata;
|
||||
FT_Bytes p;
|
||||
|
||||
if ( valueOffset < vt_rec->valueTable )
|
||||
FT_INVALID_OFFSET;
|
||||
|
||||
p = table + valueOffset;
|
||||
limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 );
|
||||
kernAction = FT_NEXT_USHORT( p );
|
||||
kernValue = FT_NEXT_USHORT( p );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_fmt1_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_kern_fmt1_StateOptRec vt_rec;
|
||||
|
||||
GXV_NAME_ENTER("kern subtable format1");
|
||||
|
||||
valid->statetable.optdata = &vt_rec;
|
||||
valid->statetable.optdata_load_func = gxv_kern_subtable_fmt1_valueTable_load;
|
||||
valid->statetable.subtable_setup_func = gxv_kern_subtable_fmt1_subtable_setup;
|
||||
valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
|
||||
valid->statetable.entry_validate_func = gxv_kern_subtable_fmt1_entry_validate;
|
||||
gxv_StateTable_validate( p, limit, valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
/* ================ Data for Class-Based Subtables 2, 3 ================ */
|
||||
|
||||
|
||||
typedef enum GXV_kern_ClassSpec_
|
||||
{
|
||||
GXV_KERN_CLS_L = 0,
|
||||
GXV_KERN_CLS_R
|
||||
} GXV_kern_ClassSpec;
|
||||
|
||||
|
||||
/* ============================= format 2 ============================== */
|
||||
|
||||
/* ---------------------- format 2 specific data ----------------------- */
|
||||
|
||||
typedef struct GXV_kern_subtable_fmt2_DataRec_
|
||||
{
|
||||
FT_UShort rowWidth;
|
||||
FT_UShort array;
|
||||
FT_UShort offset_min[2];
|
||||
FT_UShort offset_max[2];
|
||||
FT_String* class_tag[2];
|
||||
GXV_odtect_Range odtect;
|
||||
|
||||
} GXV_kern_subtable_fmt2_DataRec, *GXV_kern_subtable_fmt2_Data;
|
||||
|
||||
#define GXV_KERN_FMT2_DATA( field ) \
|
||||
(((GXV_kern_subtable_fmt2_DataRec *)(GXV_KERN_DATA( subtable_data )))-> field )
|
||||
|
||||
/* -------------------------- utility functions ----------------------- */
|
||||
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_fmt2_clstbl_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_kern_ClassSpec spec,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_String* tag = GXV_KERN_FMT2_DATA( class_tag[spec] );
|
||||
GXV_odtect_Range odtect = GXV_KERN_FMT2_DATA( odtect );
|
||||
|
||||
FT_Bytes p = table;
|
||||
FT_UShort firstGlyph;
|
||||
FT_UShort nGlyphs;
|
||||
|
||||
|
||||
GXV_NAME_ENTER(( "kern format 2 classTable" ));
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 );
|
||||
firstGlyph = FT_NEXT_USHORT( p );
|
||||
nGlyphs = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( " %s firstGlyph=%d, nGlyphs=%d\n", tag, firstGlyph, nGlyphs ));
|
||||
|
||||
|
||||
gxv_glyphid_validate( firstGlyph, valid );
|
||||
gxv_glyphid_validate( firstGlyph + nGlyphs - 1, valid );
|
||||
|
||||
|
||||
gxv_array_getlimits_ushort( p, p + ( 2 * nGlyphs ),
|
||||
&( GXV_KERN_FMT2_DATA( offset_min[spec] ) ),
|
||||
&( GXV_KERN_FMT2_DATA( offset_max[spec] ) ),
|
||||
valid );
|
||||
|
||||
|
||||
gxv_odtect_add_range( table, ( 2 * nGlyphs ), tag, odtect );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_fmt2_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_ODTECT( 3, odtect );
|
||||
GXV_kern_subtable_fmt2_DataRec fmt2_rec =
|
||||
{ 0, 0, { 0, 0 }, { 0, 0 }, { "leftClass", "rightClass" }, NULL };
|
||||
|
||||
FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
|
||||
FT_UShort leftOffsetTable;
|
||||
FT_UShort rightOffsetTable;
|
||||
|
||||
|
||||
GXV_NAME_ENTER("kern subtable format2");
|
||||
|
||||
GXV_ODTECT_INIT( odtect );
|
||||
fmt2_rec.odtect = odtect;
|
||||
GXV_KERN_DATA( subtable_data ) = &fmt2_rec;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
|
||||
GXV_KERN_FMT2_DATA( rowWidth ) = FT_NEXT_USHORT( p );
|
||||
leftOffsetTable = FT_NEXT_USHORT( p );
|
||||
rightOffsetTable = FT_NEXT_USHORT( p );
|
||||
GXV_KERN_FMT2_DATA( array ) = FT_NEXT_USHORT( p );
|
||||
|
||||
GXV_TRACE(( "rowWidth = %d\n", GXV_KERN_FMT2_DATA( rowWidth ) ));
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( leftOffsetTable );
|
||||
GXV_LIMIT_CHECK( rightOffsetTable );
|
||||
GXV_LIMIT_CHECK( GXV_KERN_FMT2_DATA( array ) );
|
||||
|
||||
|
||||
gxv_kern_subtable_fmt2_clstbl_validate( table + leftOffsetTable, limit,
|
||||
GXV_KERN_CLS_L, valid );
|
||||
|
||||
|
||||
gxv_kern_subtable_fmt2_clstbl_validate( table + rightOffsetTable, limit,
|
||||
GXV_KERN_CLS_R, valid );
|
||||
|
||||
if ( GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_L] )
|
||||
+ GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_R] )
|
||||
< GXV_KERN_FMT2_DATA( array ) )
|
||||
FT_INVALID_OFFSET;
|
||||
|
||||
|
||||
gxv_odtect_add_range( table + GXV_KERN_FMT2_DATA( array ),
|
||||
GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_L] )
|
||||
+ GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_R] )
|
||||
- GXV_KERN_FMT2_DATA( array ),
|
||||
"array", odtect );
|
||||
|
||||
gxv_odtect_validate( odtect, valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* ============================= format 3 ============================== */
|
||||
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_fmt3_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
|
||||
FT_UShort glyphCount;
|
||||
FT_Byte kernValueCount;
|
||||
FT_Byte leftClassCount;
|
||||
FT_Byte rightClassCount;
|
||||
FT_Byte flags;
|
||||
|
||||
|
||||
GXV_NAME_ENTER("kern subtable format3");
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 );
|
||||
glyphCount = FT_NEXT_USHORT( p );
|
||||
kernValueCount = FT_NEXT_BYTE( p );
|
||||
leftClassCount = FT_NEXT_BYTE( p );
|
||||
rightClassCount = FT_NEXT_BYTE( p );
|
||||
flags = FT_NEXT_BYTE( p );
|
||||
|
||||
|
||||
if ( valid->face->num_glyphs != glyphCount )
|
||||
{
|
||||
GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n", valid->face->num_glyphs, glyphCount ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_GLYPH_ID;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Just skip kernValue[kernValueCount]
|
||||
*/
|
||||
GXV_LIMIT_CHECK( 2 * kernValueCount );
|
||||
p += ( 2 * kernValueCount );
|
||||
|
||||
|
||||
/*
|
||||
* check leftClass[gid] < leftClassCount
|
||||
*/
|
||||
{
|
||||
FT_Byte min, max;
|
||||
|
||||
GXV_LIMIT_CHECK( glyphCount );
|
||||
gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
|
||||
p += valid->subtable_length;
|
||||
|
||||
if ( leftClassCount < max )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check rightClass[gid] < rightClassCount
|
||||
*/
|
||||
{
|
||||
FT_Byte min, max;
|
||||
|
||||
GXV_LIMIT_CHECK( glyphCount );
|
||||
gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
|
||||
p += valid->subtable_length;
|
||||
|
||||
if ( rightClassCount < max )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check kernIndex[i, j] < kernValueCount
|
||||
*/
|
||||
{
|
||||
FT_UShort i, j;
|
||||
for ( i = 0; i < leftClassCount; i ++ )
|
||||
{
|
||||
for ( j = 0; j < rightClassCount; j ++ )
|
||||
{
|
||||
GXV_LIMIT_CHECK( 1 );
|
||||
if ( kernValueCount < FT_NEXT_BYTE( p ) )
|
||||
FT_INVALID_OFFSET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static FT_Bool
|
||||
gxv_kern_coverage_new_apple_validate( FT_UShort coverage,
|
||||
FT_UShort* format,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* new Apple-dialect */
|
||||
FT_Bool kernVertical;
|
||||
FT_Bool kernCrossStream;
|
||||
FT_Bool kernVariation;
|
||||
|
||||
|
||||
/* reserved bits = 0 */
|
||||
if ( coverage & 0x1FFC )
|
||||
return FALSE;
|
||||
|
||||
|
||||
kernVertical = ( coverage >> 15 ) & 1;
|
||||
kernCrossStream = ( coverage >> 14 ) & 1;
|
||||
kernVariation = ( coverage >> 13 ) & 1;
|
||||
*format = coverage & 0x0003;
|
||||
|
||||
GXV_TRACE(( "new Apple-dialect: "
|
||||
"horizontal=%d, cross-stream=%d, variation=%d, format=%d\n",
|
||||
!kernVertical, kernCrossStream, kernVariation, *format ));
|
||||
|
||||
GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static FT_Bool
|
||||
gxv_kern_coverage_classic_apple_validate( FT_UShort coverage,
|
||||
FT_UShort* format,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* classic Apple-dialect */
|
||||
FT_Bool horizontal;
|
||||
FT_Bool cross_stream;
|
||||
|
||||
|
||||
/* expected flags but don't check if MS-dialect is impossible */
|
||||
if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
|
||||
return FALSE;
|
||||
|
||||
/* reserved bits = 0 */
|
||||
if ( coverage & 0x02FC )
|
||||
return FALSE;
|
||||
|
||||
|
||||
horizontal = ( coverage >> 15 ) & 1;
|
||||
cross_stream = ( coverage >> 13 ) & 1;
|
||||
*format = coverage & 0x0003;
|
||||
|
||||
GXV_TRACE(( "classic Apple-dialect: "
|
||||
"horizontal=%d, cross-stream=%d, format=%d\n",
|
||||
horizontal, cross_stream, *format ));
|
||||
|
||||
/* format1 requires GX State Machine, too new for classic */
|
||||
if ( *format == 1 )
|
||||
return FALSE;
|
||||
|
||||
GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static FT_Bool
|
||||
gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage,
|
||||
FT_UShort* format,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* classic Microsoft-dialect */
|
||||
FT_Bool horizontal;
|
||||
FT_Bool minimum;
|
||||
FT_Bool cross_stream;
|
||||
FT_Bool override;
|
||||
|
||||
/* reserved bits = 0 */
|
||||
if ( coverage & 0xFDF0 )
|
||||
return FALSE;
|
||||
|
||||
horizontal = coverage & 1;
|
||||
minimum = ( coverage >> 1 ) & 1;
|
||||
cross_stream = ( coverage >> 2 ) & 1;
|
||||
override = ( coverage >> 3 ) & 1;
|
||||
*format = ( coverage >> 8 ) & 0x0003;
|
||||
|
||||
GXV_TRACE(( "classic Microsoft-dialect: "
|
||||
"horizontal=%d, minimum=%d, cross-stream=%d, override=%d, format=%d\n",
|
||||
horizontal, minimum, cross_stream, override, *format ));
|
||||
|
||||
if ( *format == 2 )
|
||||
GXV_TRACE(( "kerning values in Microsoft format 2 subtable are ignored\n" ));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** MAIN *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
|
||||
static GXV_kern_Dialect
|
||||
gxv_kern_coverage_validate ( FT_UShort coverage,
|
||||
FT_UShort* format,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Int result = 0;
|
||||
|
||||
|
||||
GXV_NAME_ENTER(( "validate coverage" ));
|
||||
|
||||
GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage ));
|
||||
|
||||
if ( KERN_IS_NEW( valid ) )
|
||||
{
|
||||
if ( gxv_kern_coverage_new_apple_validate( coverage,
|
||||
format,
|
||||
valid ) )
|
||||
{
|
||||
result = KERN_DIALECT_APPLE;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_APPLE( valid ) )
|
||||
{
|
||||
if ( gxv_kern_coverage_classic_apple_validate( coverage,
|
||||
format,
|
||||
valid ) )
|
||||
{
|
||||
result = KERN_DIALECT_APPLE;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_MS( valid ) )
|
||||
{
|
||||
if ( gxv_kern_coverage_classic_microsoft_validate( coverage,
|
||||
format,
|
||||
valid ) )
|
||||
{
|
||||
result = KERN_DIALECT_MS;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" ));
|
||||
|
||||
Exit:
|
||||
GXV_EXIT;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_kern_subtable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort version = 0; /* MS only: subtable version, unused */
|
||||
FT_ULong length; /* MS: 16bit, Apple: 32bit*/
|
||||
FT_UShort coverage;
|
||||
FT_UShort tupleIndex = 0; /* Apple only */
|
||||
FT_UShort u16[2];
|
||||
FT_UShort format = 255; /* subtable format */
|
||||
|
||||
|
||||
GXV_NAME_ENTER("kern subtable");
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 2 );
|
||||
u16[0] = FT_NEXT_USHORT( p ); /* Apple: length_hi MS: version */
|
||||
u16[1] = FT_NEXT_USHORT( p ); /* Apple: length_lo MS: length */
|
||||
coverage = FT_NEXT_USHORT( p );
|
||||
|
||||
switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
|
||||
{
|
||||
case KERN_DIALECT_MS:
|
||||
version = u16[0];
|
||||
length = u16[1];
|
||||
tupleIndex = 0;
|
||||
GXV_TRACE(( "Subtable version = %d\n", version ));
|
||||
GXV_TRACE(( "Subtable length = %d\n", length ));
|
||||
break;
|
||||
case KERN_DIALECT_APPLE:
|
||||
version = 0;
|
||||
length = ( u16[0] << 16 ) + u16[1];
|
||||
tupleIndex = 0;
|
||||
GXV_TRACE(( "Subtable length = %d\n", length ));
|
||||
|
||||
if ( KERN_IS_NEW( valid ))
|
||||
{
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
tupleIndex = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
length = u16[1];
|
||||
GXV_TRACE(( "cannot detect subtable dialect, "
|
||||
"just skip %d byte\n", length ));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* fmt1, 2, 3 requires the position of the start of this subtable */
|
||||
if ( format == 0 )
|
||||
gxv_kern_subtable_fmt0_validate( table, table + length, valid );
|
||||
else if ( format == 1 )
|
||||
gxv_kern_subtable_fmt1_validate( table, table + length, valid );
|
||||
else if ( format == 2 )
|
||||
gxv_kern_subtable_fmt2_validate( table, table + length, valid );
|
||||
else if ( format == 3 )
|
||||
gxv_kern_subtable_fmt3_validate( table, table + length, valid );
|
||||
else
|
||||
FT_INVALID_DATA;
|
||||
|
||||
Exit:
|
||||
valid->subtable_length = length;
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** kern TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_kern_validate_generic( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Bool classic_only,
|
||||
GXV_kern_Dialect dialect_request,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
|
||||
GXV_kern_DataRec kernrec;
|
||||
GXV_kern_Data kern = &kernrec;
|
||||
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
|
||||
FT_ULong nTables = 0;
|
||||
FT_UInt i;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = kern;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation kern table\n" ));
|
||||
GXV_INIT;
|
||||
KERN_DIALECT( valid ) = dialect_request;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
GXV_KERN_DATA( version ) = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( "version 0x%04x (higher 16bit)\n", GXV_KERN_DATA( version ) ));
|
||||
|
||||
if ( 0x0001 < GXV_KERN_DATA( version ) )
|
||||
FT_INVALID_FORMAT;
|
||||
else if ( KERN_IS_CLASSIC( valid ) )
|
||||
{
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
nTables = FT_NEXT_USHORT( p );
|
||||
}
|
||||
else if ( KERN_IS_NEW( valid ) )
|
||||
{
|
||||
if ( classic_only )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
if ( 0x0000 != FT_NEXT_USHORT( p ) )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 );
|
||||
nTables = FT_NEXT_ULONG( p );
|
||||
}
|
||||
|
||||
|
||||
for ( i = 0; i < nTables; i++ )
|
||||
{
|
||||
GXV_TRACE(( "validate subtable %d/%d\n", i, nTables ));
|
||||
/* p should be 32bit-aligned? */
|
||||
gxv_kern_subtable_validate( p, 0, valid );
|
||||
p += valid->subtable_length;
|
||||
}
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_kern_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
gxv_kern_validate_generic( table, face, 0, KERN_DIALECT_ANY, ftvalid );
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_kern_validate_classic( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Int dialect_flags,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_kern_Dialect dialect_request;
|
||||
|
||||
|
||||
dialect_request = dialect_flags;
|
||||
gxv_kern_validate_generic( table, face, 1, dialect_request, ftvalid );
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
217
src/gxvalid/gxvlcar.c
Normal file
217
src/gxvalid/gxvlcar.c
Normal file
@ -0,0 +1,217 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvlcar.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT lcar table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvlcar
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct GXV_lcar_DataRec_
|
||||
{
|
||||
FT_UShort format;
|
||||
|
||||
} GXV_lcar_DataRec, *GXV_lcar_Data;
|
||||
|
||||
#define GXV_LCAR_DATA(FIELD) GXV_TABLE_DATA( lcar, FIELD )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_lcar_partial_validate( FT_UShort partial,
|
||||
FT_UShort glyph,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_NAME_ENTER( "partial" );
|
||||
|
||||
if ( GXV_LCAR_DATA( format ) != 1 )
|
||||
goto Exit;
|
||||
|
||||
gxv_ctlPoint_validate( glyph, partial, valid );
|
||||
|
||||
Exit:
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_lcar_LookupValue_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = valid->root->base + value.u;
|
||||
FT_Bytes limit = valid->root->limit;
|
||||
FT_UShort count;
|
||||
FT_Short partial;
|
||||
unsigned int i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "element in lookupTable" );
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
count = FT_NEXT_USHORT( p );
|
||||
|
||||
GXV_LIMIT_CHECK( 2 * count );
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
partial = FT_NEXT_SHORT( p );
|
||||
gxv_lcar_partial_validate( partial, glyph, valid );
|
||||
}
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
/*
|
||||
+------ lcar --------------------+
|
||||
| |
|
||||
| +===============+ |
|
||||
| | looup header | |
|
||||
| +===============+ |
|
||||
| | BinSrchHeader | |
|
||||
| +===============+ |
|
||||
| | lastGlyph[0] | |
|
||||
| +---------------+ |
|
||||
| | firstGlyph[0] | | head of lcar sfnt table
|
||||
| +---------------+ | +
|
||||
| | offset[0] | -> | offset [byte]
|
||||
| +===============+ | +
|
||||
| | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
|
||||
| +---------------+ |
|
||||
| | firstGlyph[1] | |
|
||||
| +---------------+ |
|
||||
| | offset[1] | |
|
||||
| +===============+ |
|
||||
| |
|
||||
| .... |
|
||||
| |
|
||||
| 16bit value array |
|
||||
| +===============+ |
|
||||
+------| value | <-------+
|
||||
| ....
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
+----> lcar values...handled by lcar callback function */
|
||||
|
||||
static GXV_LookupValueDesc
|
||||
gxv_lcar_LookupFmt4_transit( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p;
|
||||
FT_Bytes limit;
|
||||
FT_UShort offset;
|
||||
GXV_LookupValueDesc value;
|
||||
|
||||
|
||||
offset = base_value.u + ( relative_gindex * sizeof ( FT_UShort ) );
|
||||
p = valid->root->base + offset;
|
||||
limit = valid->root->limit;
|
||||
|
||||
GXV_LIMIT_CHECK ( 2 );
|
||||
value.u = FT_NEXT_USHORT( p );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** lcar TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_lcar_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
|
||||
GXV_lcar_DataRec lcarrec;
|
||||
GXV_lcar_Data lcar = &lcarrec;
|
||||
|
||||
FT_Fixed version;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = lcar;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation lcar table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 2 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
GXV_LCAR_DATA( format ) = FT_NEXT_USHORT( p );
|
||||
|
||||
if ( version != 0x00010000)
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
if ( GXV_LCAR_DATA( format ) > 1 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_lcar_LookupValue_validate;
|
||||
valid->lookupfmt4_trans = gxv_lcar_LookupFmt4_transit;
|
||||
gxv_LookupTable_validate( p, limit, valid );
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
274
src/gxvalid/gxvmod.c
Normal file
274
src/gxvalid/gxvmod.c
Normal file
@ -0,0 +1,274 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmod.c */
|
||||
/* */
|
||||
/* FreeType's TrueTypeGX/AAT validation module implementation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
#include FT_TRUETYPE_TAGS_H
|
||||
#include FT_GX_VALIDATE_H
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
#include FT_SERVICE_GX_VALIDATE_H
|
||||
|
||||
#include "gxvmod.h"
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmodule
|
||||
|
||||
|
||||
static FT_Error
|
||||
gxv_load_table( FT_Face face,
|
||||
FT_Tag tag,
|
||||
FT_Byte** table,
|
||||
FT_ULong* table_len )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Memory memory = FT_FACE_MEMORY( face );
|
||||
|
||||
|
||||
error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len );
|
||||
if ( error == GXV_Err_Table_Missing )
|
||||
return GXV_Err_Ok;
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
if ( FT_ALLOC( *table, *table_len ) )
|
||||
goto Exit;
|
||||
|
||||
error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#define GXV_TABLE_DECL( _sfnt ) \
|
||||
FT_Byte * _sfnt = NULL; \
|
||||
FT_ULong len_##_sfnt = 0
|
||||
|
||||
#define GXV_TABLE_LOAD( _sfnt ) \
|
||||
if ( ( FT_VALIDATE_##_sfnt##_INDEX < table_count ) && \
|
||||
( gx_flags & FT_VALIDATE_##_sfnt ) ) \
|
||||
{ \
|
||||
error = gxv_load_table( face, TTAG_##_sfnt, &_sfnt, &len_##_sfnt ); \
|
||||
if ( error ) \
|
||||
goto Exit; \
|
||||
}
|
||||
|
||||
#define GXV_TABLE_VALIDATE( _sfnt ) \
|
||||
if ( _sfnt ) \
|
||||
{ \
|
||||
ft_validator_init( &valid, _sfnt, _sfnt + len_##_sfnt, FT_VALIDATE_DEFAULT ); \
|
||||
if ( ft_validator_run( &valid ) == 0 ) \
|
||||
gxv_##_sfnt##_validate( _sfnt, face, &valid ); \
|
||||
error = valid.error; \
|
||||
if ( error ) \
|
||||
goto Exit; \
|
||||
}
|
||||
|
||||
#define GXV_TABLE_SET( _sfnt ) \
|
||||
if ( FT_VALIDATE_##_sfnt##_INDEX < table_count ) \
|
||||
tables[FT_VALIDATE_##_sfnt##_INDEX] = (FT_Bytes)_sfnt
|
||||
|
||||
static FT_Error
|
||||
gxv_validate( FT_Face face,
|
||||
FT_UInt gx_flags,
|
||||
FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
|
||||
FT_UInt table_count )
|
||||
{
|
||||
FT_Memory memory = FT_FACE_MEMORY( face );
|
||||
|
||||
FT_Error error = GXV_Err_Ok;
|
||||
FT_ValidatorRec valid;
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
GXV_TABLE_DECL( feat );
|
||||
GXV_TABLE_DECL( bsln );
|
||||
GXV_TABLE_DECL( trak );
|
||||
GXV_TABLE_DECL( just );
|
||||
GXV_TABLE_DECL( mort );
|
||||
GXV_TABLE_DECL( morx );
|
||||
GXV_TABLE_DECL( kern );
|
||||
GXV_TABLE_DECL( opbd );
|
||||
GXV_TABLE_DECL( prop );
|
||||
GXV_TABLE_DECL( lcar );
|
||||
|
||||
|
||||
for ( i = 0; i < table_count; i++ )
|
||||
tables[i] = 0;
|
||||
|
||||
/* load tables */
|
||||
GXV_TABLE_LOAD( feat );
|
||||
GXV_TABLE_LOAD( bsln );
|
||||
GXV_TABLE_LOAD( trak );
|
||||
GXV_TABLE_LOAD( just );
|
||||
GXV_TABLE_LOAD( mort );
|
||||
GXV_TABLE_LOAD( morx );
|
||||
GXV_TABLE_LOAD( kern );
|
||||
GXV_TABLE_LOAD( opbd );
|
||||
GXV_TABLE_LOAD( prop );
|
||||
GXV_TABLE_LOAD( lcar );
|
||||
|
||||
|
||||
/* validate tables */
|
||||
GXV_TABLE_VALIDATE( feat );
|
||||
GXV_TABLE_VALIDATE( bsln );
|
||||
GXV_TABLE_VALIDATE( trak );
|
||||
GXV_TABLE_VALIDATE( just );
|
||||
GXV_TABLE_VALIDATE( mort );
|
||||
GXV_TABLE_VALIDATE( morx );
|
||||
GXV_TABLE_VALIDATE( kern );
|
||||
GXV_TABLE_VALIDATE( opbd );
|
||||
GXV_TABLE_VALIDATE( prop );
|
||||
GXV_TABLE_VALIDATE( lcar );
|
||||
|
||||
/* Set results */
|
||||
GXV_TABLE_SET( feat );
|
||||
GXV_TABLE_SET( mort );
|
||||
GXV_TABLE_SET( morx );
|
||||
GXV_TABLE_SET( bsln );
|
||||
GXV_TABLE_SET( just );
|
||||
GXV_TABLE_SET( kern );
|
||||
GXV_TABLE_SET( opbd );
|
||||
GXV_TABLE_SET( trak );
|
||||
GXV_TABLE_SET( prop );
|
||||
GXV_TABLE_SET( lcar );
|
||||
|
||||
Exit:
|
||||
if ( error )
|
||||
{
|
||||
FT_FREE( feat );
|
||||
FT_FREE( bsln );
|
||||
FT_FREE( trak );
|
||||
FT_FREE( just );
|
||||
FT_FREE( mort );
|
||||
FT_FREE( morx );
|
||||
FT_FREE( kern );
|
||||
FT_FREE( opbd );
|
||||
FT_FREE( prop );
|
||||
FT_FREE( lcar );
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
classic_kern_validate( FT_Face face,
|
||||
FT_UInt ckern_flags,
|
||||
FT_Bytes* ckern_table )
|
||||
{
|
||||
FT_Memory memory = FT_FACE_MEMORY( face );
|
||||
|
||||
FT_Byte* ckern = NULL;
|
||||
FT_ULong len_ckern = 0;
|
||||
|
||||
FT_Error error = GXV_Err_Ok;
|
||||
FT_ValidatorRec valid;
|
||||
|
||||
|
||||
*ckern_table = NULL;
|
||||
|
||||
error = gxv_load_table( face, TTAG_kern, &ckern, &len_ckern );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
if ( ckern )
|
||||
{
|
||||
ft_validator_init( &valid, ckern, ckern + len_ckern, FT_VALIDATE_DEFAULT );
|
||||
if ( ft_validator_run( &valid ) == 0 )
|
||||
gxv_kern_validate_classic( ckern, face,
|
||||
ckern_flags & FT_VALIDATE_CKERN, &valid );
|
||||
error = valid.error;
|
||||
if ( error )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
*ckern_table = ckern;
|
||||
|
||||
Exit:
|
||||
if ( error )
|
||||
FT_FREE( ckern );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static
|
||||
const FT_Service_GXvalidateRec gxvalid_interface =
|
||||
{
|
||||
gxv_validate
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
const FT_Service_CKERNvalidateRec ckernvalid_interface =
|
||||
{
|
||||
classic_kern_validate
|
||||
};
|
||||
|
||||
|
||||
static
|
||||
const FT_ServiceDescRec gxvalid_services[] =
|
||||
{
|
||||
{ FT_SERVICE_ID_GX_VALIDATE, &gxvalid_interface },
|
||||
{ FT_SERVICE_ID_CLASSICKERN_VALIDATE, &ckernvalid_interface },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
static FT_Pointer
|
||||
gxvalid_get_service( FT_Module module,
|
||||
const char* service_id )
|
||||
{
|
||||
FT_UNUSED( module );
|
||||
|
||||
return ft_service_list_lookup( gxvalid_services, service_id );
|
||||
}
|
||||
|
||||
|
||||
FT_CALLBACK_TABLE_DEF
|
||||
const FT_Module_Class gxv_module_class =
|
||||
{
|
||||
0,
|
||||
sizeof( FT_ModuleRec ),
|
||||
"gxvalid",
|
||||
0x10000L,
|
||||
0x20000L,
|
||||
|
||||
0, /* module-specific interface */
|
||||
|
||||
(FT_Module_Constructor)0,
|
||||
(FT_Module_Destructor) 0,
|
||||
(FT_Module_Requester) gxvalid_get_service
|
||||
};
|
||||
|
||||
|
||||
/* END */
|
45
src/gxvalid/gxvmod.h
Normal file
45
src/gxvalid/gxvmod.h
Normal file
@ -0,0 +1,45 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmod.h */
|
||||
/* */
|
||||
/* FreeType's TrueTypeGX/AAT validation module implementation */
|
||||
/* (specification). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __GXVMOD_H__
|
||||
#define __GXVMOD_H__
|
||||
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_MODULE_H
|
||||
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
|
||||
FT_EXPORT_VAR( const FT_Module_Class ) gxv_module_class;
|
||||
|
||||
|
||||
FT_END_HEADER
|
||||
|
||||
#endif /* Not def: __GXVMOD_H__ */
|
||||
|
||||
|
||||
/* END */
|
267
src/gxvalid/gxvmort.c
Normal file
267
src/gxvalid/gxvmort.c
Normal file
@ -0,0 +1,267 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT mort table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvmort.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmort
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_feature_validate( GXV_mort_feature f,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
if ( f->featureType > gxv_feat_registry_length )
|
||||
{
|
||||
GXV_TRACE(( "featureType %d is out of registered range, "
|
||||
"setting %d is unchecked\n",
|
||||
f->featureType, f->featureSetting ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
else if ( !gxv_feat_registry[f->featureType].existence )
|
||||
{
|
||||
GXV_TRACE(( "featureType %d is within registered area "
|
||||
"but undefined, setting %d is unchecked\n",
|
||||
f->featureType, f->featureSetting ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Byte nSettings_max;
|
||||
|
||||
/* nSettings in gxvfeat.c is halved for exclusive on/off settings */
|
||||
if ( gxv_feat_registry[f->featureType].exclusive )
|
||||
nSettings_max = 2 * gxv_feat_registry[f->featureType].nSettings;
|
||||
else
|
||||
nSettings_max = gxv_feat_registry[f->featureType].nSettings;
|
||||
|
||||
GXV_TRACE(( "featureType %d is registered", f->featureType ));
|
||||
GXV_TRACE(( "setting %d", f->featureSetting ));
|
||||
if ( f->featureSetting > nSettings_max )
|
||||
{
|
||||
GXV_TRACE(( "out of defined range %d", nSettings_max ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
GXV_TRACE(( "\n" ));
|
||||
}
|
||||
|
||||
/* TODO: enableFlags must be unique value in specified chain? */
|
||||
}
|
||||
|
||||
/*
|
||||
* nFeatureFlags is typed to FT_UInt to accept that in
|
||||
* mort (typed FT_UShort) and morx (typed FT_ULong).
|
||||
*/
|
||||
static void
|
||||
gxv_mort_featurearray_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
FT_UInt nFeatureFlags,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UInt i;
|
||||
GXV_mort_featureRec f = GXV_MORT_FEATURE_OFF;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort feature list" );
|
||||
for ( i = 0; i < nFeatureFlags; i++ )
|
||||
{
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 4 + 4 );
|
||||
f.featureType = FT_NEXT_USHORT( p );
|
||||
f.featureSetting = FT_NEXT_USHORT( p );
|
||||
f.enableFlags = FT_NEXT_ULONG( p );
|
||||
f.disableFlags = FT_NEXT_ULONG( p );
|
||||
|
||||
gxv_mort_feature_validate( &f, valid );
|
||||
}
|
||||
|
||||
if ( !IS_GXV_MORT_FEATURE_OFF(f) )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_coverage_validate( FT_UShort coverage,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
if ( coverage & 0x8000 )
|
||||
GXV_TRACE(( " this subtable is for vertical text only\n" ));
|
||||
else
|
||||
GXV_TRACE(( " this subtable is for horizontal text only\n" ));
|
||||
|
||||
if ( coverage & 0x4000 )
|
||||
GXV_TRACE(( " this subtable is applied to glyph array in descending order\n" ));
|
||||
else
|
||||
GXV_TRACE(( " this subtable is applied to glyph array in ascending order\n" ));
|
||||
|
||||
if ( coverage & 0x2000 )
|
||||
GXV_TRACE(( " this subtable is forcibly applied to vertical/horizontal text\n" ));
|
||||
|
||||
if ( coverage & 0x1FF8 )
|
||||
GXV_TRACE(( " coverage has non-zero bits in reserved area\n" ));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtables_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
FT_UShort nSubtables,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_Validate_Func fmt_funcs_table [] =
|
||||
{
|
||||
gxv_mort_subtable_type0_validate, /* 0 */
|
||||
gxv_mort_subtable_type1_validate, /* 1 */
|
||||
gxv_mort_subtable_type2_validate, /* 2 */
|
||||
NULL, /* 3 */
|
||||
gxv_mort_subtable_type4_validate, /* 4 */
|
||||
gxv_mort_subtable_type5_validate, /* 5 */
|
||||
|
||||
};
|
||||
GXV_Validate_Func func;
|
||||
FT_UShort i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER(( "subtables in a chain" ));
|
||||
|
||||
for ( i = 0; i < nSubtables; i++ )
|
||||
{
|
||||
FT_UShort length;
|
||||
FT_UShort coverage;
|
||||
FT_ULong subFeatureFlags;
|
||||
FT_UInt type;
|
||||
FT_UInt rest;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 4 );
|
||||
length = FT_NEXT_USHORT( p );
|
||||
coverage = FT_NEXT_USHORT( p );
|
||||
subFeatureFlags = FT_NEXT_ULONG( p );
|
||||
|
||||
GXV_TRACE(( "validate chain subtable %d/%d (%d bytes)\n",
|
||||
i + 1, nSubtables, length ));
|
||||
type = coverage & 0x0007;
|
||||
rest = length - ( 2 + 2 + 4 );
|
||||
|
||||
GXV_LIMIT_CHECK( rest );
|
||||
gxv_mort_coverage_validate( coverage, valid );
|
||||
|
||||
if ( type > 5 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
func = fmt_funcs_table[type];
|
||||
if ( func == NULL )
|
||||
GXV_TRACE(( "morx type %d is reserved\n", type ));
|
||||
|
||||
func( p, p + rest, valid );
|
||||
|
||||
p += rest;
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_chain_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_ULong defaultFlags;
|
||||
FT_ULong chainLength;
|
||||
FT_UShort nFeatureFlags;
|
||||
FT_UShort nSubtables;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort chain header" );
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
|
||||
defaultFlags = FT_NEXT_ULONG( p );
|
||||
chainLength = FT_NEXT_ULONG( p );
|
||||
nFeatureFlags = FT_NEXT_USHORT( p );
|
||||
nSubtables = FT_NEXT_USHORT( p );
|
||||
|
||||
gxv_mort_featurearray_validate( p, table + chainLength, nFeatureFlags, valid );
|
||||
p += valid->subtable_length;
|
||||
gxv_mort_subtables_validate( p, table + chainLength, nSubtables, valid );
|
||||
valid->subtable_length = chainLength;
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_mort_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
FT_ULong version;
|
||||
FT_ULong nChains;
|
||||
FT_ULong i;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->face = face;
|
||||
limit = valid->root->limit;
|
||||
|
||||
FT_TRACE3(( "validation mort table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
nChains = FT_NEXT_ULONG( p );
|
||||
|
||||
if (version != 0x00010000)
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
for ( i = 0; i < nChains; i++ )
|
||||
{
|
||||
GXV_TRACE(( "validate chain %d/%d\n", i + 1, nChains ));
|
||||
GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
|
||||
gxv_mort_chain_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
}
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
96
src/gxvalid/gxvmort.h
Normal file
96
src/gxvalid/gxvmort.h
Normal file
@ -0,0 +1,96 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort.h */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT common definition for mort table (specification). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#ifndef __GXVMORT_H__
|
||||
#define __GXVMORT_H__
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
#include FT_SFNT_NAMES_H
|
||||
|
||||
|
||||
typedef struct GXV_mort_featureRec_
|
||||
{
|
||||
FT_UShort featureType;
|
||||
FT_UShort featureSetting;
|
||||
FT_ULong enableFlags;
|
||||
FT_ULong disableFlags;
|
||||
|
||||
} GXV_mort_featureRec, *GXV_mort_feature;
|
||||
|
||||
#define GXV_MORT_FEATURE_OFF \
|
||||
{0, 1, 0x00000000UL, 0x00000000UL}
|
||||
|
||||
#define IS_GXV_MORT_FEATURE_OFF( f ) \
|
||||
( (f).featureType == 0 || \
|
||||
(f).featureSetting == 1 || \
|
||||
(f).enableFlags == 0x00000000UL || \
|
||||
(f).disableFlags == 0x00000000UL )
|
||||
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_feature_validate( GXV_mort_feature f,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_featurearray_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
FT_UInt nFeatureFlags,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_coverage_validate( FT_UShort coverage,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_subtable_type0_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_subtable_type1_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_subtable_type2_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_subtable_type4_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_mort_subtable_type5_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
#endif /* Not def: __GXVMORT_H__ */
|
||||
|
||||
|
||||
/* END */
|
122
src/gxvalid/gxvmort0.c
Normal file
122
src/gxvalid/gxvmort0.c
Normal file
@ -0,0 +1,122 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort0.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT mort table validation */
|
||||
/* body for type0 (Indic Script Rearrangement) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmort.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmort
|
||||
|
||||
|
||||
static char* GXV_Mort_IndicScript_Msg [] =
|
||||
{
|
||||
"no change",
|
||||
"Ax => xA",
|
||||
"xD => Dx",
|
||||
"AxD => DxA",
|
||||
"ABx => xAB",
|
||||
"ABx => xBA",
|
||||
"xCD => CDx",
|
||||
"xCD => DCx",
|
||||
"AxCD => CDxA",
|
||||
"AxCD => DCxA",
|
||||
"ABxD => DxAB",
|
||||
"ABxD => DxBA",
|
||||
"ABxCD => CDxAB",
|
||||
"ABxCD => CDxBA",
|
||||
"ABxCD => DCxAB",
|
||||
"ABxCD => DCxBA",
|
||||
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type0_entry_validate( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort markFirst;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort markLast;
|
||||
FT_UShort reserved;
|
||||
FT_UShort verb;
|
||||
|
||||
|
||||
markFirst = flags / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
markLast = ( flags & 0x2000 ) / 0x2000;
|
||||
reserved = flags & 0x1FF0;
|
||||
verb = flags & 0x000F;
|
||||
|
||||
FT_UNUSED( GXV_Mort_IndicScript_Msg[verb] );
|
||||
|
||||
GXV_TRACE(( " IndicScript MorphRule for glyphOffset 0x%04x", glyphOffset.u ));
|
||||
GXV_TRACE(( " markFirst=%01d", markFirst ));
|
||||
GXV_TRACE(( " dontAdvance=%01d", dontAdvance ));
|
||||
GXV_TRACE(( " markLast=%01d", markLast ));
|
||||
GXV_TRACE(( " %02d", verb ));
|
||||
GXV_TRACE(( " %s\n", GXV_Mort_IndicScript_Msg[verb] ));
|
||||
if ( 0 < reserved )
|
||||
{
|
||||
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
GXV_TRACE(( "\n" ));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type0_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort chain subtable type0 (Indic-Script Rearrangement)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_STATETABLE_HEADER_SIZE );
|
||||
|
||||
valid->statetable.optdata = NULL;
|
||||
valid->statetable.optdata_load_func = NULL;
|
||||
valid->statetable.subtable_setup_func = NULL;
|
||||
valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
|
||||
valid->statetable.entry_validate_func = gxv_mort_subtable_type0_entry_validate;
|
||||
gxv_StateTable_validate( p, limit, valid );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
226
src/gxvalid/gxvmort1.c
Normal file
226
src/gxvalid/gxvmort1.c
Normal file
@ -0,0 +1,226 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort1.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT mort table validation */
|
||||
/* body for type1 (Contextual Substitution) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmort.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmort
|
||||
|
||||
|
||||
typedef struct GXV_mort_subtable_type1_StateOptRec_
|
||||
{
|
||||
FT_UShort substitutionTable;
|
||||
FT_UShort substitutionTable_length;
|
||||
|
||||
} GXV_mort_subtable_type1_StateOptRec,
|
||||
*GXV_mort_subtable_type1_StateOptRecData;
|
||||
|
||||
#define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE ( GXV_STATETABLE_HEADER_SIZE + 2 )
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_mort_subtable_type1_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
optdata->substitutionTable = FT_NEXT_USHORT( p );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type1_subtable_setup( FT_UShort table_size,
|
||||
FT_UShort classTable,
|
||||
FT_UShort stateArray,
|
||||
FT_UShort entryTable,
|
||||
FT_UShort* classTable_length_p,
|
||||
FT_UShort* stateArray_length_p,
|
||||
FT_UShort* entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort o[4];
|
||||
FT_UShort *l[4];
|
||||
FT_UShort buff[5];
|
||||
GXV_mort_subtable_type1_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
|
||||
o[0] = classTable;
|
||||
o[1] = stateArray;
|
||||
o[2] = entryTable;
|
||||
o[3] = optdata->substitutionTable;
|
||||
l[0] = classTable_length_p;
|
||||
l[1] = stateArray_length_p;
|
||||
l[2] = entryTable_length_p;
|
||||
l[3] = &(optdata->substitutionTable_length);
|
||||
|
||||
gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type1_offset_to_subst_validate( FT_Short wordOffset,
|
||||
FT_String* tag,
|
||||
FT_Byte state,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort substTable;
|
||||
FT_UShort substTable_limit;
|
||||
FT_UShort min_gid;
|
||||
FT_UShort max_gid;
|
||||
|
||||
substTable = ((GXV_mort_subtable_type1_StateOptRec *)
|
||||
(valid->statetable.optdata))->substitutionTable;
|
||||
substTable_limit = substTable +
|
||||
((GXV_mort_subtable_type1_StateOptRec *)
|
||||
(valid->statetable.optdata))->substitutionTable_length;
|
||||
|
||||
min_gid = ( substTable - ( wordOffset * 2 ) ) / 2;
|
||||
max_gid = ( substTable_limit - ( wordOffset * 2 ) ) / 2;
|
||||
max_gid = FT_MAX( max_gid, valid->face->num_glyphs );
|
||||
|
||||
/* TODO: min_gid & max_gid comparison with ClassTable contents */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type1_entry_validate( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort setMark;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort reserved;
|
||||
FT_Short markOffset;
|
||||
FT_Short currentOffset;
|
||||
|
||||
|
||||
setMark = flags / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
reserved = flags & 0x3FFF;
|
||||
markOffset = GXV_USHORT_TO_SHORT( glyphOffset.ul / 0x00010000 );
|
||||
currentOffset = GXV_USHORT_TO_SHORT( glyphOffset.ul & 0x0000FFFF );
|
||||
|
||||
if ( 0 < reserved )
|
||||
{
|
||||
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
|
||||
"markOffset",
|
||||
state,
|
||||
valid );
|
||||
|
||||
gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset,
|
||||
"currentOffset",
|
||||
state,
|
||||
valid );
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type1_substTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort num_gids = ((GXV_mort_subtable_type1_StateOptRec *)
|
||||
(valid->statetable.optdata))->substitutionTable_length
|
||||
/ 2;
|
||||
FT_UShort i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER(( "validate contents in substitionTable" ));
|
||||
for ( i = 0; i < num_gids ; i ++ )
|
||||
{
|
||||
FT_UShort dst_gid;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
dst_gid = FT_NEXT_USHORT( p );
|
||||
|
||||
if ( dst_gid >= 0xFFFF )
|
||||
continue;
|
||||
|
||||
if ( dst_gid > valid->face->num_glyphs )
|
||||
{
|
||||
GXV_TRACE(( "substTable include too-large gid[%d]=%d > max defined gid #%d\n",
|
||||
i, dst_gid, valid->face->num_glyphs ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_GLYPH_ID;
|
||||
}
|
||||
}
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* subtable for Contextual glyph substition is modified StateTable.
|
||||
* In addition classTable, stateArray, entryTable, "substitutionTable"
|
||||
* is added.
|
||||
*/
|
||||
static void
|
||||
gxv_mort_subtable_type1_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_mort_subtable_type1_StateOptRec st_rec;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE );
|
||||
|
||||
valid->statetable.optdata = &st_rec;
|
||||
valid->statetable.optdata_load_func = gxv_mort_subtable_type1_substitutionTable_load;
|
||||
valid->statetable.subtable_setup_func = gxv_mort_subtable_type1_subtable_setup;
|
||||
valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_ULONG;
|
||||
valid->statetable.entry_validate_func = gxv_mort_subtable_type1_entry_validate;
|
||||
gxv_StateTable_validate( p, limit, valid );
|
||||
|
||||
gxv_mort_subtable_type1_substTable_validate( table
|
||||
+ st_rec.substitutionTable,
|
||||
table
|
||||
+ st_rec.substitutionTable
|
||||
+ st_rec.substitutionTable_length,
|
||||
valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
243
src/gxvalid/gxvmort2.c
Normal file
243
src/gxvalid/gxvmort2.c
Normal file
@ -0,0 +1,243 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort2.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT mort table validation */
|
||||
/* body for type2 (Ligature Substitution) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmort.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmort
|
||||
|
||||
|
||||
typedef struct GXV_mort_subtable_type2_StateOptRec_
|
||||
{
|
||||
FT_UShort ligActionTable;
|
||||
FT_UShort componentTable;
|
||||
FT_UShort ligatureTable;
|
||||
FT_UShort ligActionTable_length;
|
||||
FT_UShort componentTable_length;
|
||||
FT_UShort ligatureTable_length;
|
||||
|
||||
} GXV_mort_subtable_type2_StateOptRec,
|
||||
*GXV_mort_subtable_type2_StateOptRecData;
|
||||
|
||||
#define GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE ( GXV_STATETABLE_HEADER_SIZE + 2 + 2 + 2 )
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type2_opttable_load( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_mort_subtable_type2_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 2 );
|
||||
optdata->ligActionTable = FT_NEXT_USHORT( p );
|
||||
optdata->componentTable = FT_NEXT_USHORT( p );
|
||||
optdata->ligatureTable = FT_NEXT_USHORT( p );
|
||||
|
||||
GXV_TRACE(( "offset to ligActionTable=0x%04x\n", optdata->ligActionTable ));
|
||||
GXV_TRACE(( "offset to componentTable=0x%04x\n", optdata->componentTable ));
|
||||
GXV_TRACE(( "offset to ligatureTable=0x%04x\n", optdata->ligatureTable ));
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type2_subtable_setup( FT_UShort table_size,
|
||||
FT_UShort classTable,
|
||||
FT_UShort stateArray,
|
||||
FT_UShort entryTable,
|
||||
FT_UShort *classTable_length_p,
|
||||
FT_UShort *stateArray_length_p,
|
||||
FT_UShort *entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort o[6];
|
||||
FT_UShort *l[6];
|
||||
FT_UShort buff[7];
|
||||
GXV_mort_subtable_type2_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "subtable boundaries setup" );
|
||||
|
||||
o[0] = classTable;
|
||||
o[1] = stateArray;
|
||||
o[2] = entryTable;
|
||||
o[3] = optdata->ligActionTable;
|
||||
o[4] = optdata->componentTable;
|
||||
o[5] = optdata->ligatureTable;
|
||||
l[0] = classTable_length_p;
|
||||
l[1] = stateArray_length_p;
|
||||
l[2] = entryTable_length_p;
|
||||
l[3] = &(optdata->ligActionTable_length);
|
||||
l[4] = &(optdata->componentTable_length);
|
||||
l[5] = &(optdata->ligatureTable_length);
|
||||
|
||||
gxv_set_length_by_ushort_offset( o, l, buff, 6, table_size, valid );
|
||||
|
||||
GXV_TRACE(( "classTable: offset=0x%04x length=0x%04x\n",
|
||||
classTable, *classTable_length_p));
|
||||
GXV_TRACE(( "stateArray: offset=0x%04x length=0x%04x\n",
|
||||
stateArray, *stateArray_length_p));
|
||||
GXV_TRACE(( "entryTable: offset=0x%04x length=0x%04x\n",
|
||||
entryTable, *entryTable_length_p));
|
||||
GXV_TRACE(( "ligActionTable: offset=0x%04x length=0x%04x\n",
|
||||
optdata->ligActionTable,
|
||||
optdata->ligActionTable_length));
|
||||
GXV_TRACE(( "componentTable: offset=0x%04x length=0x%04x\n",
|
||||
optdata->componentTable,
|
||||
optdata->componentTable_length));
|
||||
GXV_TRACE(( "ligatureTable: offset=0x%04x length=0x%04x\n",
|
||||
optdata->ligatureTable,
|
||||
optdata->ligatureTable_length));
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type2_ligActionOffset_validate( FT_Bytes table,
|
||||
FT_UShort ligActionOffset,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* access ligActionTable */
|
||||
GXV_mort_subtable_type2_StateOptRecData optdata = valid->statetable.optdata;
|
||||
FT_Bytes lat_base = table + optdata->ligActionTable;
|
||||
FT_Bytes p = table + ligActionOffset;
|
||||
FT_Bytes lat_limit = lat_base + optdata->ligActionTable;
|
||||
|
||||
|
||||
GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset );
|
||||
if ( p < lat_base )
|
||||
{
|
||||
GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n",
|
||||
ligActionOffset, lat_base - p ));
|
||||
|
||||
/* FontValidator, ftxvalidator, ftxdumperfuser warns but continues */
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_OFFSET;
|
||||
}
|
||||
else if ( lat_limit < p )
|
||||
{
|
||||
GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n",
|
||||
ligActionOffset, p - lat_limit ));
|
||||
|
||||
/* FontValidator, ftxvalidator, ftxdumperfuser warns but continues */
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* validate entry in ligActionTable */
|
||||
FT_ULong lig_action;
|
||||
FT_UShort last;
|
||||
FT_UShort store;
|
||||
FT_ULong offset;
|
||||
|
||||
|
||||
lig_action = FT_NEXT_ULONG( p );
|
||||
last = (lig_action & 0x80000000) / 0x80000000;
|
||||
store = (lig_action & 0x40000000) / 0x40000000;
|
||||
offset = lig_action & 0x3FFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type2_entry_validate( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort setComponent;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort offset;
|
||||
|
||||
|
||||
setComponent = ( flags & 0x8000 ) / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
offset = flags & 0x3FFF;
|
||||
|
||||
if ( 0 < offset )
|
||||
gxv_mort_subtable_type2_ligActionOffset_validate( table, offset, valid );
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type2_ligatureTable_validate( FT_Bytes table,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_mort_subtable_type2_StateOptRecData optdata = valid->statetable.optdata;
|
||||
FT_Bytes p = table + optdata->ligatureTable;
|
||||
FT_Bytes limit = table + optdata->ligatureTable
|
||||
+ optdata->ligatureTable_length;
|
||||
|
||||
GXV_NAME_ENTER( "mort chain subtable type2 - substitutionTable" );
|
||||
if ( 0 != optdata->ligatureTable )
|
||||
{
|
||||
/* Apple does not give specification of ligatureTable format */
|
||||
while ( p < limit )
|
||||
{
|
||||
FT_UShort lig_gid;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
lig_gid = FT_NEXT_USHORT( p );
|
||||
}
|
||||
}
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type2_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_mort_subtable_type2_StateOptRec lig_rec;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort chain subtable type2 (Ligature Substitution)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE );
|
||||
|
||||
valid->statetable.optdata = &lig_rec;
|
||||
valid->statetable.optdata_load_func = gxv_mort_subtable_type2_opttable_load;
|
||||
valid->statetable.subtable_setup_func = gxv_mort_subtable_type2_subtable_setup;
|
||||
valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
|
||||
valid->statetable.entry_validate_func = gxv_mort_subtable_type2_entry_validate;
|
||||
gxv_StateTable_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
gxv_mort_subtable_type2_ligatureTable_validate( table, valid );
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
113
src/gxvalid/gxvmort4.c
Normal file
113
src/gxvalid/gxvmort4.c
Normal file
@ -0,0 +1,113 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort4.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT mort table validation */
|
||||
/* body for type4 (Non-Contextual Glyph Substitution) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmort.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmort
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type4_lookupval_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
gxv_glyphid_validate( value.u, valid );
|
||||
}
|
||||
|
||||
/*
|
||||
+===============+ --------+
|
||||
| lookup header | |
|
||||
+===============+ |
|
||||
| BinSrchHeader | |
|
||||
+===============+ |
|
||||
| lastGlyph[0] | |
|
||||
+---------------+ |
|
||||
| firstGlyph[0] | | head of lookup table
|
||||
+---------------+ | +
|
||||
| offset[0] | -> | offset [byte]
|
||||
+===============+ | +
|
||||
| lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
|
||||
+---------------+ |
|
||||
| firstGlyph[1] | |
|
||||
+---------------+ |
|
||||
| offset[1] | |
|
||||
+===============+ |
|
||||
|
|
||||
.... |
|
||||
|
|
||||
16bit value array |
|
||||
+===============+ |
|
||||
| value | <-------+
|
||||
....
|
||||
*/
|
||||
static GXV_LookupValueDesc
|
||||
gxv_mort_subtable_type4_lookupfmt4_transit( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p;
|
||||
FT_Bytes limit;
|
||||
FT_UShort offset;
|
||||
GXV_LookupValueDesc value;
|
||||
|
||||
|
||||
offset = base_value.u + ( relative_gindex * sizeof ( FT_UShort ) );
|
||||
|
||||
p = valid->lookuptbl_head + offset;
|
||||
limit = lookuptbl_limit;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
value.u = FT_NEXT_USHORT( p );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type4_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort chain subtable type4 (Non-Contextual Glyph Substitution)" );
|
||||
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_mort_subtable_type4_lookupval_validate;
|
||||
valid->lookupfmt4_trans = gxv_mort_subtable_type4_lookupfmt4_transit;
|
||||
gxv_LookupTable_validate( p, limit, valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
200
src/gxvalid/gxvmort5.c
Normal file
200
src/gxvalid/gxvmort5.c
Normal file
@ -0,0 +1,200 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmort5.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT mort table validation */
|
||||
/* body for type5 (Contextual Glyph Insertion) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmort.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmort
|
||||
|
||||
|
||||
/*
|
||||
* mort subtable type5 (Contextual Glyph Insertion)
|
||||
* has format of StateTable with insertion-glyph-list
|
||||
* without name. the offset is given by glyphOffset in
|
||||
* entryTable. there's no table location declaration
|
||||
* like xxxTable.
|
||||
*/
|
||||
|
||||
typedef struct GXV_mort_subtable_type5_StateOptRec_
|
||||
{
|
||||
FT_UShort classTable;
|
||||
FT_UShort stateArray;
|
||||
FT_UShort entryTable;
|
||||
#define GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE GXV_STATETABLE_HEADER_SIZE
|
||||
FT_UShort* classTable_length_p;
|
||||
FT_UShort* stateArray_length_p;
|
||||
FT_UShort* entryTable_length_p;
|
||||
} GXV_mort_subtable_type5_StateOptRec,
|
||||
*GXV_mort_subtable_type5_StateOptRecData;
|
||||
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_mort_subtable_type5_subtable_setup( FT_UShort table_size,
|
||||
FT_UShort classTable,
|
||||
FT_UShort stateArray,
|
||||
FT_UShort entryTable,
|
||||
FT_UShort* classTable_length_p,
|
||||
FT_UShort* stateArray_length_p,
|
||||
FT_UShort* entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_mort_subtable_type5_StateOptRecData optdata = valid->statetable.optdata;
|
||||
gxv_StateTable_subtable_setup( table_size,
|
||||
classTable,
|
||||
stateArray,
|
||||
entryTable,
|
||||
classTable_length_p,
|
||||
stateArray_length_p,
|
||||
entryTable_length_p,
|
||||
valid );
|
||||
|
||||
optdata->classTable = classTable;
|
||||
optdata->stateArray = stateArray;
|
||||
optdata->entryTable = entryTable;
|
||||
optdata->classTable_length_p = classTable_length_p;
|
||||
optdata->stateArray_length_p = stateArray_length_p;
|
||||
optdata->entryTable_length_p = entryTable_length_p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type5_InsertList_validate( FT_UShort offset,
|
||||
FT_UShort count,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/*
|
||||
* we don't know the range of insertion-glyph-list.
|
||||
* set range by whole of state table
|
||||
*/
|
||||
FT_Bytes p = table + offset;
|
||||
GXV_mort_subtable_type5_StateOptRecData optdata = valid->statetable.optdata;
|
||||
|
||||
if ( optdata->classTable < offset &&
|
||||
offset < optdata->classTable + *(optdata->classTable_length_p) )
|
||||
GXV_TRACE(( " offset runs into ClassTable" ));
|
||||
if ( optdata->stateArray < offset &&
|
||||
offset < optdata->stateArray + *(optdata->stateArray_length_p) )
|
||||
GXV_TRACE(( " offset runs into StateArray" ));
|
||||
if ( optdata->entryTable < offset &&
|
||||
offset < optdata->entryTable + *(optdata->entryTable_length_p) )
|
||||
GXV_TRACE(( " offset runs into EntryTable" ));
|
||||
|
||||
while ( p < table + offset + ( count * 2 ) )
|
||||
{
|
||||
FT_UShort insert_glyphID;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
insert_glyphID = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( " 0x%04x", insert_glyphID ));
|
||||
}
|
||||
|
||||
GXV_TRACE(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type5_entry_validate( FT_Byte state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bool setMark;
|
||||
FT_Bool dontAdvance;
|
||||
FT_Bool currentIsKashidaLike;
|
||||
FT_Bool markedIsKashidaLike;
|
||||
FT_Bool currentInsertBefore;
|
||||
FT_Bool markedInsertBefore;
|
||||
FT_Byte currentInsertCount;
|
||||
FT_Byte markedInsertCount;
|
||||
FT_UShort currentInsertList;
|
||||
FT_UShort markedInsertList;
|
||||
|
||||
|
||||
setMark = ( flags >> 15 ) & 1;
|
||||
dontAdvance = ( flags >> 14 ) & 1;
|
||||
currentIsKashidaLike = ( flags >> 13 ) & 1;
|
||||
markedIsKashidaLike = ( flags >> 12 ) & 1;
|
||||
currentInsertBefore = ( flags >> 11 ) & 1;
|
||||
markedInsertBefore = ( flags >> 10 ) & 1;
|
||||
currentInsertCount = ( flags & 0x03E0 ) / 0x0020;
|
||||
markedInsertCount = ( flags & 0x001F );
|
||||
currentInsertList = glyphOffset.ul / 0x00010000;
|
||||
markedInsertList = glyphOffset.ul & 0x0000FFFF;
|
||||
|
||||
if ( 0 != currentInsertList && 0 != currentInsertCount )
|
||||
{
|
||||
gxv_mort_subtable_type5_InsertList_validate( currentInsertList,
|
||||
currentInsertCount,
|
||||
table,
|
||||
limit,
|
||||
valid );
|
||||
}
|
||||
|
||||
if ( 0 != markedInsertList && 0 != markedInsertCount )
|
||||
{
|
||||
gxv_mort_subtable_type5_InsertList_validate( markedInsertList,
|
||||
markedInsertCount,
|
||||
table,
|
||||
limit,
|
||||
valid );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_mort_subtable_type5_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_mort_subtable_type5_StateOptRec et_rec;
|
||||
GXV_mort_subtable_type5_StateOptRecData et = &et_rec;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "mort chain subtable type5 (Glyph Insertion)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE );
|
||||
|
||||
valid->statetable.optdata = et;
|
||||
valid->statetable.optdata_load_func = NULL;
|
||||
valid->statetable.subtable_setup_func = gxv_mort_subtable_type5_subtable_setup;
|
||||
valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_ULONG;
|
||||
valid->statetable.entry_validate_func = gxv_mort_subtable_type5_entry_validate;
|
||||
gxv_StateTable_validate( p, limit, valid );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
168
src/gxvalid/gxvmorx.c
Normal file
168
src/gxvalid/gxvmorx.c
Normal file
@ -0,0 +1,168 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT morx table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvmorx.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmorx
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtables_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
FT_UShort nSubtables,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_Validate_Func fmt_funcs_table [] =
|
||||
{
|
||||
gxv_morx_subtable_type0_validate, /* 0 */
|
||||
gxv_morx_subtable_type1_validate, /* 1 */
|
||||
gxv_morx_subtable_type2_validate, /* 2 */
|
||||
NULL, /* 3 */
|
||||
gxv_morx_subtable_type4_validate, /* 4 */
|
||||
gxv_morx_subtable_type5_validate, /* 5 */
|
||||
|
||||
};
|
||||
GXV_Validate_Func func;
|
||||
FT_UShort i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER(( "subtables in a chain" ));
|
||||
for ( i = 0; i < nSubtables; i++ )
|
||||
{
|
||||
FT_ULong length;
|
||||
FT_ULong coverage;
|
||||
FT_ULong subFeatureFlags;
|
||||
FT_UInt type;
|
||||
FT_UInt rest;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 4 );
|
||||
length = FT_NEXT_ULONG( p );
|
||||
coverage = FT_NEXT_ULONG( p );
|
||||
subFeatureFlags = FT_NEXT_ULONG( p );
|
||||
|
||||
GXV_TRACE(( "validate chain subtable %d/%d (%d bytes)\n",
|
||||
i + 1, nSubtables, length ));
|
||||
|
||||
type = coverage & 0x0007;
|
||||
rest = length - ( 4 + 4 + 4 );
|
||||
GXV_LIMIT_CHECK( rest );
|
||||
|
||||
/* morx coverage consists of mort_coverage & 16bit padding */
|
||||
gxv_mort_coverage_validate( ( coverage >> 16 ) | coverage, valid );
|
||||
|
||||
if ( type > 5 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
func = fmt_funcs_table[type];
|
||||
if ( func == NULL )
|
||||
GXV_TRACE(( "morx type %d is reserved\n", type ));
|
||||
|
||||
func( p, p + rest, valid );
|
||||
|
||||
p += rest;
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_chain_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_ULong defaultFlags;
|
||||
FT_ULong chainLength;
|
||||
FT_ULong nFeatureFlags;
|
||||
FT_ULong nSubtables;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "morx chain header" );
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
|
||||
defaultFlags = FT_NEXT_ULONG( p );
|
||||
chainLength = FT_NEXT_ULONG( p );
|
||||
nFeatureFlags = FT_NEXT_ULONG( p );
|
||||
nSubtables = FT_NEXT_ULONG( p );
|
||||
|
||||
/* feature-array of morx is same with that of mort */
|
||||
gxv_mort_featurearray_validate( p, limit, nFeatureFlags, valid );
|
||||
p += valid->subtable_length;
|
||||
gxv_morx_subtables_validate( p, table + chainLength, nSubtables, valid );
|
||||
valid->subtable_length = chainLength;
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_morx_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
FT_ULong version;
|
||||
FT_ULong nChains;
|
||||
FT_ULong i;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation morx table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
nChains = FT_NEXT_ULONG( p );
|
||||
|
||||
if (version != 0x00020000)
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
for ( i = 0; i < nChains; i++ )
|
||||
{
|
||||
GXV_TRACE(( "validate chain %d/%d\n", i + 1, nChains ));
|
||||
GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
|
||||
gxv_morx_chain_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
}
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
64
src/gxvalid/gxvmorx.h
Normal file
64
src/gxvalid/gxvmorx.h
Normal file
@ -0,0 +1,64 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx.h */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT common definition for morx table (specification). */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#ifndef __GXVMORX_H_
|
||||
#define __GXVMORX_H_
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
#include "gxvmort.h"
|
||||
|
||||
#include FT_SFNT_NAMES_H
|
||||
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_morx_subtable_type0_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_morx_subtable_type1_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_morx_subtable_type2_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_morx_subtable_type4_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
FT_LOCAL( void )
|
||||
gxv_morx_subtable_type5_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid );
|
||||
|
||||
|
||||
#endif /* Not def: __GXVMORX_H__ */
|
||||
|
||||
|
||||
/* END */
|
87
src/gxvalid/gxvmorx0.c
Normal file
87
src/gxvalid/gxvmorx0.c
Normal file
@ -0,0 +1,87 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx0.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT morx table validation */
|
||||
/* body for type0 (Indic Script Rearrangement) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmorx.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmorx
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type0_entry_validate( FT_UShort state,
|
||||
FT_UShort flags,
|
||||
GXV_XStateTable_GlyphOffsetDesc
|
||||
glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort markFirst;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort markLast;
|
||||
FT_UShort reserved;
|
||||
FT_UShort verb;
|
||||
|
||||
|
||||
markFirst = flags / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
markLast = ( flags & 0x2000 ) / 0x2000;
|
||||
reserved = flags & 0x1FF0;
|
||||
verb = flags & 0x000F;
|
||||
|
||||
if ( 0 < reserved )
|
||||
{
|
||||
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type0_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
GXV_NAME_ENTER( "morx chain subtable type0 (Indic-Script Rearrangement)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_STATETABLE_HEADER_SIZE );
|
||||
|
||||
valid->xstatetable.optdata = NULL;
|
||||
valid->xstatetable.optdata_load_func = NULL;
|
||||
valid->xstatetable.subtable_setup_func = NULL;
|
||||
valid->xstatetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
|
||||
valid->xstatetable.entry_validate_func = gxv_morx_subtable_type0_entry_validate;
|
||||
gxv_XStateTable_validate( p, limit, valid );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
238
src/gxvalid/gxvmorx1.c
Normal file
238
src/gxvalid/gxvmorx1.c
Normal file
@ -0,0 +1,238 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx1.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT morx table validation */
|
||||
/* body for type1 (Contextual Substitution) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmorx.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmorx
|
||||
|
||||
|
||||
typedef struct GXV_morx_subtable_type1_StateOptRec_
|
||||
{
|
||||
FT_ULong substitutionTable;
|
||||
FT_ULong substitutionTable_length;
|
||||
FT_UShort substitutionTable_num_lookupTables;
|
||||
|
||||
} GXV_morx_subtable_type1_StateOptRec,
|
||||
*GXV_morx_subtable_type1_StateOptRecData;
|
||||
|
||||
#define GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE ( GXV_STATETABLE_HEADER_SIZE + 2 )
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type1_substitutionTable_load( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type1_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
optdata->substitutionTable = FT_NEXT_USHORT( p );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type1_subtable_setup( FT_ULong table_size,
|
||||
FT_ULong classTable,
|
||||
FT_ULong stateArray,
|
||||
FT_ULong entryTable,
|
||||
FT_ULong* classTable_length_p,
|
||||
FT_ULong* stateArray_length_p,
|
||||
FT_ULong* entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_ULong o[4];
|
||||
FT_ULong *l[4];
|
||||
FT_ULong buff[5];
|
||||
GXV_morx_subtable_type1_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
|
||||
o[0] = classTable;
|
||||
o[1] = stateArray;
|
||||
o[2] = entryTable;
|
||||
o[3] = optdata->substitutionTable;
|
||||
l[0] = classTable_length_p;
|
||||
l[1] = stateArray_length_p;
|
||||
l[2] = entryTable_length_p;
|
||||
l[3] = &(optdata->substitutionTable_length);
|
||||
|
||||
gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type1_entry_validate( FT_UShort state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc
|
||||
glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort setMark;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort reserved;
|
||||
FT_Short markIndex;
|
||||
FT_Short currentIndex;
|
||||
GXV_morx_subtable_type1_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
|
||||
setMark = flags / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
reserved = flags & 0x3FFF;
|
||||
markIndex = GXV_USHORT_TO_SHORT( glyphOffset.ul / 0x00010000 );
|
||||
currentIndex = GXV_USHORT_TO_SHORT( glyphOffset.ul & 0x0000FFFF );
|
||||
|
||||
GXV_TRACE(( " setMark=%01d dontAdvance=%01d\n",
|
||||
setMark, dontAdvance ));
|
||||
if ( 0 < reserved )
|
||||
{
|
||||
GXV_TRACE(( " non-zero bits found in reserved range\n" ));
|
||||
if ( valid->root->level >= FT_VALIDATE_PARANOID )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
GXV_TRACE(( "markIndex = %d, currentIndex = %d\n", markIndex, currentIndex ));
|
||||
|
||||
if ( optdata->substitutionTable_num_lookupTables < markIndex + 1 )
|
||||
optdata->substitutionTable_num_lookupTables = markIndex + 1;
|
||||
|
||||
if ( optdata->substitutionTable_num_lookupTables < currentIndex + 1 )
|
||||
optdata->substitutionTable_num_lookupTables = currentIndex + 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type1_LookupValue_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_TRACE(( "morx subtable type1 subst.: %d -> %d\n", glyph, value.u ));
|
||||
if ( value.u > valid->face->num_glyphs )
|
||||
FT_INVALID_GLYPH_ID;
|
||||
}
|
||||
|
||||
|
||||
static GXV_LookupValueDesc
|
||||
gxv_morx_subtable_type1_LookupFmt4_transit( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p;
|
||||
FT_Bytes limit;
|
||||
FT_UShort offset;
|
||||
GXV_LookupValueDesc value;
|
||||
|
||||
|
||||
offset = base_value.u + ( relative_gindex * sizeof( FT_UShort ) );
|
||||
|
||||
p = valid->lookuptbl_head + offset;
|
||||
limit = lookuptbl_limit;
|
||||
|
||||
GXV_LIMIT_CHECK ( 2 );
|
||||
value.u = FT_NEXT_USHORT( p );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO: length should be limit?
|
||||
**/
|
||||
static void
|
||||
gxv_morx_subtable_type1_substitutionTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type1_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
FT_UShort i;
|
||||
|
||||
|
||||
/* TODO: calculate offset/length for each lookupTables */
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_morx_subtable_type1_LookupValue_validate;
|
||||
valid->lookupfmt4_trans = gxv_morx_subtable_type1_LookupFmt4_transit;
|
||||
|
||||
for ( i = 0; i < optdata->substitutionTable_num_lookupTables; i++ )
|
||||
{
|
||||
FT_ULong offset;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 );
|
||||
offset = FT_NEXT_ULONG( p );
|
||||
|
||||
gxv_LookupTable_validate( table + offset, limit, valid );
|
||||
}
|
||||
|
||||
/* TODO: overlapping of lookupTables in substitutionTable */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* subtable for Contextual glyph substition is modified StateTable.
|
||||
* In addition classTable, stateArray, entryTable, "substitutionTable"
|
||||
* is added.
|
||||
*/
|
||||
static void
|
||||
gxv_morx_subtable_type1_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type1_StateOptRec st_rec;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "morx chain subtable type1 (Contextual Glyph Subst)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE );
|
||||
|
||||
st_rec.substitutionTable_num_lookupTables = 0;
|
||||
|
||||
valid->xstatetable.optdata = &st_rec;
|
||||
valid->xstatetable.optdata_load_func = gxv_morx_subtable_type1_substitutionTable_load;
|
||||
valid->xstatetable.subtable_setup_func = gxv_morx_subtable_type1_subtable_setup;
|
||||
valid->xstatetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_ULONG;
|
||||
valid->xstatetable.entry_validate_func = gxv_morx_subtable_type1_entry_validate;
|
||||
gxv_XStateTable_validate( p, limit, valid );
|
||||
|
||||
gxv_morx_subtable_type1_substitutionTable_validate( table
|
||||
+ st_rec.substitutionTable,
|
||||
table
|
||||
+ st_rec.substitutionTable
|
||||
+ st_rec.substitutionTable_length,
|
||||
valid );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
241
src/gxvalid/gxvmorx2.c
Normal file
241
src/gxvalid/gxvmorx2.c
Normal file
@ -0,0 +1,241 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx2.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT morx table validation */
|
||||
/* body for type2 (Ligature Substitution) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmorx.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmorx
|
||||
|
||||
|
||||
typedef struct GXV_morx_subtable_type2_StateOptRec_
|
||||
{
|
||||
FT_ULong ligActionTable;
|
||||
FT_ULong componentTable;
|
||||
FT_ULong ligatureTable;
|
||||
FT_ULong ligActionTable_length;
|
||||
FT_ULong componentTable_length;
|
||||
FT_ULong ligatureTable_length;
|
||||
|
||||
} GXV_morx_subtable_type2_StateOptRec,
|
||||
*GXV_morx_subtable_type2_StateOptRecData;
|
||||
|
||||
#define GXV_MORX_SUBTABLE_TYPE2_HEADER_SIZE ( GXV_XSTATETABLE_HEADER_SIZE + 4 + 4 + 4 )
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type2_opttable_load( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type2_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 4 + 4 );
|
||||
optdata->ligActionTable = FT_NEXT_ULONG( p );
|
||||
optdata->componentTable = FT_NEXT_ULONG( p );
|
||||
optdata->ligatureTable = FT_NEXT_ULONG( p );
|
||||
|
||||
GXV_TRACE(( "offset to ligActionTable=0x%08x\n", optdata->ligActionTable ));
|
||||
GXV_TRACE(( "offset to componentTable=0x%08x\n", optdata->componentTable ));
|
||||
GXV_TRACE(( "offset to ligatureTable=0x%08x\n", optdata->ligatureTable ));
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type2_subtable_setup( FT_ULong table_size,
|
||||
FT_ULong classTable,
|
||||
FT_ULong stateArray,
|
||||
FT_ULong entryTable,
|
||||
FT_ULong* classTable_length_p,
|
||||
FT_ULong* stateArray_length_p,
|
||||
FT_ULong* entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_ULong o[6];
|
||||
FT_ULong* l[6];
|
||||
FT_ULong buff[7];
|
||||
GXV_morx_subtable_type2_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "subtable boundaries setup" );
|
||||
|
||||
o[0] = classTable;
|
||||
o[1] = stateArray;
|
||||
o[2] = entryTable;
|
||||
o[3] = optdata->ligActionTable;
|
||||
o[4] = optdata->componentTable;
|
||||
o[5] = optdata->ligatureTable;
|
||||
l[0] = classTable_length_p;
|
||||
l[1] = stateArray_length_p;
|
||||
l[2] = entryTable_length_p;
|
||||
l[3] = &(optdata->ligActionTable_length);
|
||||
l[4] = &(optdata->componentTable_length);
|
||||
l[5] = &(optdata->ligatureTable_length);
|
||||
|
||||
gxv_set_length_by_ulong_offset( o, l, buff, 6, table_size, valid );
|
||||
|
||||
GXV_TRACE(( "classTable: offset=0x%08x length=0x%08x\n",
|
||||
classTable, *classTable_length_p));
|
||||
GXV_TRACE(( "stateArray: offset=0x%08x length=0x%08x\n",
|
||||
stateArray, *stateArray_length_p));
|
||||
GXV_TRACE(( "entryTable: offset=0x%08x length=0x%08x\n",
|
||||
entryTable, *entryTable_length_p));
|
||||
GXV_TRACE(( "ligActionTable: offset=0x%08x length=0x%08x\n",
|
||||
optdata->ligActionTable,
|
||||
optdata->ligActionTable_length));
|
||||
GXV_TRACE(( "componentTable: offset=0x%08x length=0x%08x\n",
|
||||
optdata->componentTable,
|
||||
optdata->componentTable_length));
|
||||
GXV_TRACE(( "ligatureTable: offset=0x%08x length=0x%08x\n",
|
||||
optdata->ligatureTable,
|
||||
optdata->ligatureTable_length));
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
#define GXV_MORX_LIGACTION_ENTRY_SIZE 4
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type2_ligActionIndex_validate( FT_Bytes table,
|
||||
FT_UShort ligActionIndex,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* access ligActionTable */
|
||||
GXV_morx_subtable_type2_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
FT_Bytes lat_base = table + optdata->ligActionTable;
|
||||
FT_Bytes p = lat_base + ligActionIndex * GXV_MORX_LIGACTION_ENTRY_SIZE;
|
||||
FT_Bytes lat_limit = lat_base + optdata->ligActionTable;
|
||||
|
||||
|
||||
if ( p < lat_base )
|
||||
{
|
||||
GXV_TRACE(( "p < lat_base (%d byte rewind)\n", lat_base - p ));
|
||||
FT_INVALID_OFFSET;
|
||||
}
|
||||
else if ( lat_limit < p )
|
||||
{
|
||||
GXV_TRACE(( "lat_limit < p (%d byte overrun)\n", p - lat_limit ));
|
||||
FT_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
{
|
||||
/* validate entry in ligActionTable */
|
||||
FT_ULong lig_action;
|
||||
FT_UShort last;
|
||||
FT_UShort store;
|
||||
FT_ULong offset;
|
||||
|
||||
|
||||
lig_action = FT_NEXT_ULONG( p );
|
||||
last = (lig_action & 0x80000000) / 0x80000000;
|
||||
store = (lig_action & 0x40000000) / 0x40000000;
|
||||
offset = lig_action & 0x3FFFFFFF;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type2_entry_validate( FT_UShort state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc
|
||||
glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_UShort setComponent;
|
||||
FT_UShort dontAdvance;
|
||||
FT_UShort performAction;
|
||||
FT_UShort reserved;
|
||||
FT_UShort ligActionIndex;
|
||||
|
||||
setComponent = ( flags & 0x8000 ) / 0x8000;
|
||||
dontAdvance = ( flags & 0x4000 ) / 0x4000;
|
||||
performAction = ( flags & 0x2000 ) / 0x2000;
|
||||
reserved = flags & 0x1FFF;
|
||||
ligActionIndex = glyphOffset.u;
|
||||
|
||||
if ( reserved > 0 )
|
||||
GXV_TRACE(( " reserved 14bit is non-zero\n" ));
|
||||
|
||||
if ( 0 < ligActionIndex )
|
||||
gxv_morx_subtable_type2_ligActionIndex_validate( table, ligActionIndex, valid );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type2_ligatureTable_validate( FT_Bytes table,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_morx_subtable_type2_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
FT_Bytes p = table + optdata->ligatureTable;
|
||||
FT_Bytes limit = table + optdata->ligatureTable
|
||||
+ optdata->ligatureTable_length;
|
||||
|
||||
GXV_NAME_ENTER( "morx chain subtable type2 - substitutionTable" );
|
||||
if ( 0 != optdata->ligatureTable )
|
||||
{
|
||||
/* Apple does not give specification of ligatureTable format */
|
||||
while ( p < limit )
|
||||
{
|
||||
FT_UShort lig_gid;
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
lig_gid = FT_NEXT_USHORT( p );
|
||||
}
|
||||
}
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type2_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type2_StateOptRec lig_rec;
|
||||
|
||||
GXV_NAME_ENTER( "morx chain subtable type2 (Ligature Substitution)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE2_HEADER_SIZE );
|
||||
|
||||
valid->xstatetable.optdata = &lig_rec;
|
||||
valid->xstatetable.optdata_load_func = gxv_morx_subtable_type2_opttable_load;
|
||||
valid->xstatetable.subtable_setup_func = gxv_morx_subtable_type2_subtable_setup;
|
||||
valid->xstatetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_USHORT;
|
||||
valid->xstatetable.entry_validate_func = gxv_morx_subtable_type2_entry_validate;
|
||||
gxv_XStateTable_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
gxv_morx_subtable_type2_ligatureTable_validate( table, valid );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
50
src/gxvalid/gxvmorx4.c
Normal file
50
src/gxvalid/gxvmorx4.c
Normal file
@ -0,0 +1,50 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx4.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT morx table validation */
|
||||
/* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmorx.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmorx
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type4_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_NAME_ENTER( "morx chain subtable type4 (Non-Contextual Glyph Substitution)" );
|
||||
|
||||
gxv_mort_subtable_type4_validate( table, limit, valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
197
src/gxvalid/gxvmorx5.c
Normal file
197
src/gxvalid/gxvmorx5.c
Normal file
@ -0,0 +1,197 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvmorx5.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT morx table validation */
|
||||
/* body for type5 (Contextual Glyph Insertion) subtable. */
|
||||
/* */
|
||||
/* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
#include "gxvmorx.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvmorx
|
||||
|
||||
|
||||
/*
|
||||
* morx subtable type5 (Contextual Glyph Insertion)
|
||||
* has format of StateTable with insertion-glyph-list
|
||||
* without name. however, 32bit offset from the head
|
||||
* of subtable to the i-g-l is given after "entryTable",
|
||||
* without variable name specification (the exist of
|
||||
* offset to the table is different from mort type5).
|
||||
*/
|
||||
|
||||
|
||||
typedef struct GXV_morx_subtable_type5_StateOptRec_
|
||||
{
|
||||
FT_ULong insertionGlyphList;
|
||||
FT_ULong insertionGlyphList_length;
|
||||
|
||||
} GXV_morx_subtable_type5_StateOptRec,
|
||||
*GXV_morx_subtable_type5_StateOptRecData;
|
||||
|
||||
#define GXV_MORX_SUBTABLE_TYPE5_HEADER_SIZE ( GXV_STATETABLE_HEADER_SIZE + 4 )
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type5_insertionGlyphList_load( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type5_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 );
|
||||
optdata->insertionGlyphList = FT_NEXT_ULONG( p );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type5_subtable_setup( FT_ULong table_size,
|
||||
FT_ULong classTable,
|
||||
FT_ULong stateArray,
|
||||
FT_ULong entryTable,
|
||||
FT_ULong* classTable_length_p,
|
||||
FT_ULong* stateArray_length_p,
|
||||
FT_ULong* entryTable_length_p,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_ULong o[4];
|
||||
FT_ULong* l[4];
|
||||
FT_ULong buff[5];
|
||||
GXV_morx_subtable_type5_StateOptRecData optdata = valid->xstatetable.optdata;
|
||||
|
||||
|
||||
o[0] = classTable;
|
||||
o[1] = stateArray;
|
||||
o[2] = entryTable;
|
||||
o[3] = optdata->insertionGlyphList;
|
||||
l[0] = classTable_length_p;
|
||||
l[1] = stateArray_length_p;
|
||||
l[2] = entryTable_length_p;
|
||||
l[3] = &(optdata->insertionGlyphList_length);
|
||||
|
||||
gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type5_InsertList_validate( FT_UShort index,
|
||||
FT_UShort count,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table + ( index * 2 );
|
||||
|
||||
while ( p < table + ( count * 2 ) + ( index * 2 ) )
|
||||
{
|
||||
FT_UShort insert_glyphID;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
insert_glyphID = FT_NEXT_USHORT( p );
|
||||
GXV_TRACE(( " 0x%04x", insert_glyphID ));
|
||||
}
|
||||
|
||||
GXV_TRACE(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type5_entry_validate( FT_UShort state,
|
||||
FT_UShort flags,
|
||||
GXV_StateTable_GlyphOffsetDesc
|
||||
glyphOffset,
|
||||
FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bool setMark;
|
||||
FT_Bool dontAdvance;
|
||||
FT_Bool currentIsKashidaLike;
|
||||
FT_Bool markedIsKashidaLike;
|
||||
FT_Bool currentInsertBefore;
|
||||
FT_Bool markedInsertBefore;
|
||||
FT_Bool currentInsertCount;
|
||||
FT_Byte markedInsertCount;
|
||||
FT_Byte currentInsertList;
|
||||
FT_UShort markedInsertList;
|
||||
|
||||
|
||||
setMark = ( flags >> 15 ) & 1;
|
||||
dontAdvance = ( flags >> 14 ) & 1;
|
||||
currentIsKashidaLike = ( flags >> 13 ) & 1;
|
||||
markedIsKashidaLike = ( flags >> 12 ) & 1;
|
||||
currentInsertBefore = ( flags >> 11 ) & 1;
|
||||
markedInsertBefore = ( flags >> 10 ) & 1;
|
||||
currentInsertCount = ( flags & 0x03E0 ) / 0x20;
|
||||
markedInsertCount = ( flags & 0x001F );
|
||||
currentInsertList = glyphOffset.ul / 0x00010000;
|
||||
markedInsertList = glyphOffset.ul & 0x0000FFFF;
|
||||
|
||||
if ( currentInsertList && 0 != currentInsertCount )
|
||||
{
|
||||
gxv_morx_subtable_type5_InsertList_validate( currentInsertList,
|
||||
currentInsertCount,
|
||||
table, limit,
|
||||
valid );
|
||||
}
|
||||
|
||||
if ( markedInsertList && 0 != markedInsertCount )
|
||||
{
|
||||
gxv_morx_subtable_type5_InsertList_validate( markedInsertList,
|
||||
markedInsertCount,
|
||||
table, limit,
|
||||
valid );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_morx_subtable_type5_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
GXV_morx_subtable_type5_StateOptRec et_rec;
|
||||
GXV_morx_subtable_type5_StateOptRecData et = &et_rec;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "morx chain subtable type5 (Glyph Insertion)" );
|
||||
|
||||
GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE5_HEADER_SIZE );
|
||||
|
||||
valid->xstatetable.optdata = et;
|
||||
valid->xstatetable.optdata_load_func = gxv_morx_subtable_type5_insertionGlyphList_load;
|
||||
valid->xstatetable.subtable_setup_func = gxv_morx_subtable_type5_subtable_setup;
|
||||
valid->xstatetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_ULONG;
|
||||
valid->xstatetable.entry_validate_func = gxv_morx_subtable_type5_entry_validate;
|
||||
gxv_XStateTable_validate( p, limit, valid );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
205
src/gxvalid/gxvopbd.c
Normal file
205
src/gxvalid/gxvopbd.c
Normal file
@ -0,0 +1,205 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvopbd.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT opbd table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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 "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvopbd
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
typedef struct GXV_opbd_DataRec_
|
||||
{
|
||||
FT_UShort format;
|
||||
FT_UShort valueOffset_min;
|
||||
|
||||
} GXV_opbd_DataRec, *GXV_opbd_Data;
|
||||
|
||||
#define GXV_OPBD_DATA(FIELD) GXV_TABLE_DATA( opbd, FIELD )
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_opbd_LookupValue_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
/* offset in LookupTable is measured from the head of opbd table */
|
||||
FT_Bytes p = valid->root->base + value.u;
|
||||
FT_Bytes limit = valid->root->limit;
|
||||
FT_Short delta_value;
|
||||
int i;
|
||||
|
||||
|
||||
if ( value.u < GXV_OPBD_DATA( valueOffset_min ) )
|
||||
GXV_OPBD_DATA( valueOffset_min ) = value.u;
|
||||
|
||||
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
GXV_LIMIT_CHECK( 2 );
|
||||
delta_value = FT_NEXT_SHORT( p );
|
||||
|
||||
if ( GXV_OPBD_DATA( format ) ) /* format 1, value is ctrl pt. */
|
||||
{
|
||||
if ( delta_value == -1 )
|
||||
continue;
|
||||
|
||||
gxv_ctlPoint_validate( glyph, delta_value, valid );
|
||||
}
|
||||
else /* format 0, value is distance */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
opbd ---------------------+
|
||||
|
|
||||
+===============+ |
|
||||
| lookup header | |
|
||||
+===============+ |
|
||||
| BinSrchHeader | |
|
||||
+===============+ |
|
||||
| lastGlyph[0] | |
|
||||
+---------------+ |
|
||||
| firstGlyph[0] | | head of opbd sfnt table
|
||||
+---------------+ | +
|
||||
| offset[0] | -> | offset [byte]
|
||||
+===============+ | +
|
||||
| lastGlyph[1] | | (glyphID - firstGlyph) * 4 * sizeof(FT_Short) [byte]
|
||||
+---------------+ |
|
||||
| firstGlyph[1] | |
|
||||
+---------------+ |
|
||||
| offset[1] | |
|
||||
+===============+ |
|
||||
|
|
||||
.... |
|
||||
|
|
||||
48bit value array |
|
||||
+===============+ |
|
||||
| value | <-------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+---------------+
|
||||
.... */
|
||||
|
||||
static GXV_LookupValueDesc
|
||||
gxv_opbd_LookupFmt4_transit( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
GXV_LookupValueDesc value;
|
||||
|
||||
|
||||
value.u = base_value.u + ( relative_gindex * 4 * sizeof ( FT_Short ) );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** opbd TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_opbd_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
GXV_opbd_DataRec opbdrec;
|
||||
GXV_opbd_Data opbd = &opbdrec;
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
|
||||
FT_ULong version;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = opbd;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation opbd table\n" ));
|
||||
GXV_INIT;
|
||||
GXV_OPBD_DATA( valueOffset_min ) = 0xFFFF;
|
||||
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 2 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
GXV_OPBD_DATA( format ) = FT_NEXT_USHORT( p );
|
||||
|
||||
|
||||
/* 0x00010000 is only defined (1996) */
|
||||
GXV_TRACE(( "(version=0x%08x)\n", version ));
|
||||
if ( 0x00010000UL != version )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
/* 0, 1 are only defined (1996) */
|
||||
GXV_TRACE(( "(format=0x%04x)\n", GXV_OPBD_DATA( format ) ));
|
||||
if ( 0x0001 < GXV_OPBD_DATA( format ) )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_opbd_LookupValue_validate;
|
||||
valid->lookupfmt4_trans = gxv_opbd_LookupFmt4_transit;
|
||||
gxv_LookupTable_validate( p, limit, valid );
|
||||
p += valid->subtable_length;
|
||||
|
||||
|
||||
if ( p > table + GXV_OPBD_DATA( valueOffset_min ) )
|
||||
{
|
||||
GXV_TRACE(( "found overlap between LookupTable and opbd_value array\n" ));
|
||||
FT_INVALID_OFFSET;
|
||||
}
|
||||
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
302
src/gxvalid/gxvprop.c
Normal file
302
src/gxvalid/gxvprop.c
Normal file
@ -0,0 +1,302 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvprop.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT prop table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvprop
|
||||
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
#define GXV_PROP_HEADER_SIZE ( 4 + 2 + 2 )
|
||||
#define GXV_PROP_SIZE_MIN GXV_PROP_HEADER_SIZE
|
||||
|
||||
typedef struct GXV_prop_DataRec_
|
||||
{
|
||||
FT_Fixed version;
|
||||
|
||||
} GXV_prop_DataRec, *GXV_prop_Data;
|
||||
#define GXV_PROP_DATA(field) GXV_TABLE_DATA( prop, field )
|
||||
|
||||
#define GXV_PROP_FLOATER 0x8000
|
||||
#define GXV_PROP_USE_COMPLEMENTARY_BRACKET 0x1000
|
||||
#define GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET 0x0F00
|
||||
#define GXV_PROP_ATTACHING_TO_RIGHT 0x0080
|
||||
#define GXV_PROP_RESERVED 0x0060
|
||||
#define GXV_PROP_DIRECTIONALITY_CLASS 0x001F
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_prop_zero_advance_validate( FT_UShort gid,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Face face;
|
||||
FT_Error error;
|
||||
FT_GlyphSlot glyph;
|
||||
|
||||
|
||||
GXV_NAME_ENTER(" zero advance " );
|
||||
|
||||
face = valid->face;
|
||||
|
||||
error = FT_Load_Glyph( face,
|
||||
gid,
|
||||
FT_LOAD_IGNORE_TRANSFORM );
|
||||
if ( error )
|
||||
FT_INVALID_GLYPH_ID;
|
||||
|
||||
glyph = face->glyph;
|
||||
|
||||
if ( glyph->advance.x != (FT_Pos)0 ||
|
||||
glyph->advance.y != (FT_Pos)0 )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
/* Pass 0 as GLYPH to check the default property */
|
||||
static void
|
||||
gxv_prop_property_validate( FT_UShort property,
|
||||
FT_UShort glyph,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
if ( glyph != 0 && ( property & GXV_PROP_FLOATER ) )
|
||||
{
|
||||
gxv_prop_zero_advance_validate( glyph, valid );
|
||||
}
|
||||
|
||||
|
||||
if ( property & GXV_PROP_USE_COMPLEMENTARY_BRACKET )
|
||||
{
|
||||
FT_UShort offset;
|
||||
char complement;
|
||||
|
||||
offset = property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET;
|
||||
if ( offset == 0 )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
complement = offset >> 8;
|
||||
if ( complement & 0x08 )
|
||||
{
|
||||
/* Top bit is set: nagative */
|
||||
|
||||
/* Calculated the absolute offset */
|
||||
complement = ( complement & 0x07 ) + 1;
|
||||
|
||||
/* The gid for complement must be greater than 0 */
|
||||
if ( glyph <= complement )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The gid for complement must be the face. */
|
||||
gxv_glyphid_validate( glyph + complement, valid );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET ) )
|
||||
GXV_TRACE(( "glyph %d cannot have complementary bracketing\n",
|
||||
glyph ));
|
||||
}
|
||||
|
||||
|
||||
/* this is introduced in ver 2.0 */
|
||||
if ( property & GXV_PROP_ATTACHING_TO_RIGHT )
|
||||
{
|
||||
if ( GXV_PROP_DATA( version ) == 0x00010000 )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
|
||||
if ( property & GXV_PROP_RESERVED )
|
||||
{
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
|
||||
if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 )
|
||||
{
|
||||
/* TODO: Too restricted. Use the validation level. */
|
||||
if ( GXV_PROP_DATA( version ) == 0x00010000 ||
|
||||
GXV_PROP_DATA( version ) == 0x00020000 )
|
||||
FT_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gxv_prop_LookupValue_validate( FT_UShort glyph,
|
||||
GXV_LookupValueDesc value,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
gxv_prop_property_validate( value.u, glyph, valid );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
+===============+ --------+
|
||||
| lookup header | |
|
||||
+===============+ |
|
||||
| BinSrchHeader | |
|
||||
+===============+ |
|
||||
| lastGlyph[0] | |
|
||||
+---------------+ |
|
||||
| firstGlyph[0] | | head of lookup table
|
||||
+---------------+ | +
|
||||
| offset[0] | -> | offset [byte]
|
||||
+===============+ | +
|
||||
| lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
|
||||
+---------------+ |
|
||||
| firstGlyph[1] | |
|
||||
+---------------+ |
|
||||
| offset[1] | |
|
||||
+===============+ |
|
||||
|
|
||||
... |
|
||||
|
|
||||
16bit value array |
|
||||
+===============+ |
|
||||
| value | <-------+
|
||||
...
|
||||
*/
|
||||
|
||||
static GXV_LookupValueDesc
|
||||
gxv_prop_LookupFmt4_transit( FT_UShort relative_gindex,
|
||||
GXV_LookupValueDesc base_value,
|
||||
FT_Bytes lookuptbl_limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p;
|
||||
FT_Bytes limit;
|
||||
FT_UShort offset;
|
||||
GXV_LookupValueDesc value;
|
||||
|
||||
|
||||
offset = base_value.u + ( relative_gindex * sizeof( FT_UShort ) );
|
||||
p = valid->lookuptbl_head + offset;
|
||||
limit = lookuptbl_limit;
|
||||
|
||||
GXV_LIMIT_CHECK ( 2 );
|
||||
value.u = FT_NEXT_USHORT( p );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** prop TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_prop_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
|
||||
GXV_prop_DataRec proprec;
|
||||
GXV_prop_Data prop = &proprec;
|
||||
|
||||
FT_Fixed version;
|
||||
FT_UShort format;
|
||||
FT_UShort defaultProp;
|
||||
|
||||
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = prop;
|
||||
valid->face = face;
|
||||
|
||||
FT_TRACE3(( "validation prop table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
format = FT_NEXT_USHORT( p );
|
||||
defaultProp = FT_NEXT_USHORT( p );
|
||||
|
||||
|
||||
/* version 1.0, 2.0, 3.0 are only defined (1996) */
|
||||
if ( version != 0x00010000 &&
|
||||
version != 0x00020000 &&
|
||||
version != 0x00030000 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
|
||||
/* format 0x0000, 0x0001 are only defined (1996) */
|
||||
if ( format > 1 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
gxv_prop_property_validate( defaultProp, 0, valid );
|
||||
|
||||
if ( format == 0 )
|
||||
{
|
||||
FT_TRACE3(( "(format 0, no per-glyph properties, "
|
||||
"rest %d bytes are skipped)", limit - p ));
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* format == 1 */
|
||||
GXV_PROP_DATA( version ) = version;
|
||||
|
||||
valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
|
||||
valid->lookupval_func = gxv_prop_LookupValue_validate;
|
||||
valid->lookupfmt4_trans = gxv_prop_LookupFmt4_transit;
|
||||
gxv_LookupTable_validate( p, limit, valid );
|
||||
|
||||
Exit:
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
282
src/gxvalid/gxvtrak.c
Normal file
282
src/gxvalid/gxvtrak.c
Normal file
@ -0,0 +1,282 @@
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* gxvtrak.c */
|
||||
/* */
|
||||
/* TrueTypeGX/AAT trak table validation (body). */
|
||||
/* */
|
||||
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
|
||||
/* 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. */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/***************************************************************************/
|
||||
/* gxvalid is derived from both gxlayout module and otvalid module. */
|
||||
/* Development of gxlayout was support of Information-technology Promotion */
|
||||
/* Agency(IPA), Japan. */
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
#include "gxvalid.h"
|
||||
#include "gxvcommn.h"
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
||||
/* messages during execution. */
|
||||
/* */
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_gxvtrak
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** Data and Types *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
/*
|
||||
* refered track table format specification:
|
||||
* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6trak.html
|
||||
* last update is 1996.
|
||||
* ----------------------------------------------
|
||||
* [MINIMUM HEADER]: GXV_TRAK_SIZE_MIN
|
||||
* version (fixed: 32bit) = 0x00010000
|
||||
* format (uint16: 16bit) = 0 is only defined (1996)
|
||||
* horizOffset (uint16: 16bit)
|
||||
* vertOffset (uint16: 16bit)
|
||||
* reserved (uint16: 16bit) = 0
|
||||
* ----------------------------------------------
|
||||
* [VARIABLE BODY]:
|
||||
* horizData
|
||||
* header ( 2 + 2 + 4
|
||||
* trackTable + nTracks * ( 4 + 2 + 2 )
|
||||
* sizeTable + nSizes * 4 )
|
||||
* ----------------------------------------------
|
||||
* vertData
|
||||
* header ( 2 + 2 + 4
|
||||
* trackTable + nTracks * ( 4 + 2 + 2 )
|
||||
* sizeTable + nSizes * 4 )
|
||||
* ----------------------------------------------
|
||||
*/
|
||||
typedef struct GXV_trak_DataRec_
|
||||
{
|
||||
FT_UShort trackValueOffset_min;
|
||||
FT_UShort trackValueOffset_max;
|
||||
|
||||
} GXV_trak_DataRec, *GXV_trak_Data;
|
||||
|
||||
#define GXV_TRAK_DATA(FIELD) GXV_TABLE_DATA( trak, FIELD )
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** UTILITY FUNCTIONS *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
static void
|
||||
gxv_trak_trackTable_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
FT_UShort nTracks,
|
||||
FT_UShort nSizes,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
|
||||
FT_Fixed track;
|
||||
FT_UShort nameIndex;
|
||||
FT_UShort offset;
|
||||
FT_UShort i;
|
||||
|
||||
|
||||
GXV_NAME_ENTER( "trackTable" );
|
||||
|
||||
GXV_TRAK_DATA( trackValueOffset_min ) = 0xFFFF;
|
||||
GXV_TRAK_DATA( trackValueOffset_max ) = 0x0000;
|
||||
|
||||
for ( i = 0; i < nTracks; i ++ )
|
||||
{
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 );
|
||||
track = FT_NEXT_LONG( p );
|
||||
nameIndex = FT_NEXT_USHORT( p );
|
||||
offset = FT_NEXT_USHORT( p );
|
||||
|
||||
if ( offset < GXV_TRAK_DATA( trackValueOffset_min ) )
|
||||
GXV_TRAK_DATA( trackValueOffset_min ) = offset;
|
||||
if ( offset > GXV_TRAK_DATA( trackValueOffset_max ) )
|
||||
GXV_TRAK_DATA( trackValueOffset_max ) = offset;
|
||||
|
||||
gxv_sfntName_validate( nameIndex, 256, 32767, valid );
|
||||
}
|
||||
|
||||
valid->subtable_length = ( p - table );
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gxv_trak_trackData_validate( FT_Bytes table,
|
||||
FT_Bytes limit,
|
||||
GXV_Validator valid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_UShort nTracks;
|
||||
FT_UShort nSizes;
|
||||
FT_ULong sizeTableOffset;
|
||||
|
||||
GXV_ODTECT( 4, odtect );
|
||||
|
||||
|
||||
GXV_ODTECT_INIT( odtect );
|
||||
GXV_NAME_ENTER( "trackData" );
|
||||
|
||||
/* read the header of trackData */
|
||||
GXV_LIMIT_CHECK( 2 + 2 + 4 );
|
||||
nTracks = FT_NEXT_USHORT( p );
|
||||
nSizes = FT_NEXT_USHORT( p );
|
||||
sizeTableOffset = FT_NEXT_ULONG( p );
|
||||
|
||||
gxv_odtect_add_range( table, p - table, "trackData header", odtect );
|
||||
|
||||
|
||||
/* validate trackTable */
|
||||
gxv_trak_trackTable_validate( p, limit, nTracks, nSizes, valid );
|
||||
gxv_odtect_add_range( p, valid->subtable_length,
|
||||
"trackTable", odtect );
|
||||
|
||||
|
||||
/* sizeTable is array of FT_Fixed, don't check contents */
|
||||
p = valid->root->base + sizeTableOffset;
|
||||
GXV_LIMIT_CHECK( nSizes * 4 );
|
||||
gxv_odtect_add_range( p, ( nSizes * 4 ), "sizeTable", odtect );
|
||||
|
||||
|
||||
/* validate trackValueOffet */
|
||||
p = valid->root->base + GXV_TRAK_DATA( trackValueOffset_min );
|
||||
if ( ( limit - p ) < ( nTracks * nSizes * 2 ) )
|
||||
GXV_TRACE(( "too short trackValue array\n" ));
|
||||
|
||||
p = valid->root->base + GXV_TRAK_DATA( trackValueOffset_max );
|
||||
GXV_LIMIT_CHECK( nSizes * 2 );
|
||||
|
||||
gxv_odtect_add_range( valid->root->base
|
||||
+ GXV_TRAK_DATA( trackValueOffset_min ),
|
||||
GXV_TRAK_DATA( trackValueOffset_max )
|
||||
- GXV_TRAK_DATA( trackValueOffset_min )
|
||||
+ ( nSizes * 2 ),
|
||||
"trackValue array", odtect );
|
||||
|
||||
|
||||
gxv_odtect_validate( odtect, valid );
|
||||
|
||||
GXV_EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
/***** *****/
|
||||
/***** trak TABLE *****/
|
||||
/***** *****/
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( void )
|
||||
gxv_trak_validate( FT_Bytes table,
|
||||
FT_Face face,
|
||||
FT_Validator ftvalid )
|
||||
{
|
||||
FT_Bytes p = table;
|
||||
FT_Bytes limit = 0;
|
||||
FT_UInt table_size;
|
||||
|
||||
GXV_ValidatorRec validrec;
|
||||
GXV_Validator valid = &validrec;
|
||||
GXV_trak_DataRec trakrec;
|
||||
GXV_trak_Data trak = &trakrec;
|
||||
|
||||
FT_ULong version;
|
||||
FT_UShort format;
|
||||
FT_UShort horizOffset;
|
||||
FT_UShort vertOffset;
|
||||
FT_UShort reserved;
|
||||
|
||||
|
||||
GXV_ODTECT( 3, odtect );
|
||||
|
||||
|
||||
GXV_ODTECT_INIT( odtect );
|
||||
valid->root = ftvalid;
|
||||
valid->table_data = trak;
|
||||
valid->face = face;
|
||||
|
||||
|
||||
limit = valid->root->limit;
|
||||
table_size = limit - table;
|
||||
|
||||
FT_TRACE3(( "validation trak table\n" ));
|
||||
GXV_INIT;
|
||||
|
||||
GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 + 2 );
|
||||
version = FT_NEXT_ULONG( p );
|
||||
format = FT_NEXT_USHORT( p );
|
||||
horizOffset = FT_NEXT_USHORT( p );
|
||||
vertOffset = FT_NEXT_USHORT( p );
|
||||
reserved = FT_NEXT_USHORT( p );
|
||||
|
||||
GXV_TRACE(( " (version = 0x%08x)\n", version ));
|
||||
GXV_TRACE(( " (format = 0x%04x)\n", format ));
|
||||
GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset ));
|
||||
GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset ));
|
||||
GXV_TRACE(( " (reserved = 0x%04x)\n", reserved ));
|
||||
|
||||
/* Version 1.0 (always:1996) */
|
||||
if ( version != 0x00010000UL )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
/* format 0 (always:1996) */
|
||||
if ( format != 0x0000 )
|
||||
FT_INVALID_FORMAT;
|
||||
|
||||
GXV_32BIT_ALIGNMENT_VALIDATE( horizOffset );
|
||||
GXV_32BIT_ALIGNMENT_VALIDATE( vertOffset );
|
||||
|
||||
/* Reserved Fixed Value (always) */
|
||||
if ( reserved != 0x0000 )
|
||||
FT_INVALID_DATA;
|
||||
|
||||
|
||||
/* validate trackData */
|
||||
if ( 0 < horizOffset )
|
||||
{
|
||||
gxv_trak_trackData_validate( table + horizOffset, limit, valid );
|
||||
gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
|
||||
"horizJustData", odtect );
|
||||
}
|
||||
|
||||
if ( 0 < vertOffset )
|
||||
{
|
||||
gxv_trak_trackData_validate( table + vertOffset, limit, valid );
|
||||
gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
|
||||
"vertJustData", odtect );
|
||||
}
|
||||
|
||||
gxv_odtect_validate( odtect, valid );
|
||||
|
||||
|
||||
FT_TRACE4(( "\n" ));
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
21
src/gxvalid/module.mk
Normal file
21
src/gxvalid/module.mk
Normal file
@ -0,0 +1,21 @@
|
||||
#
|
||||
# FreeType 2 gxvalid module definition
|
||||
#
|
||||
|
||||
# Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
|
||||
# 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.
|
||||
|
||||
|
||||
make_module_list: add_gxvalid_module
|
||||
|
||||
add_gxvalid_module:
|
||||
$(OPEN_DRIVER)gxvalid_module_class$(CLOSE_DRIVER)
|
||||
$(ECHO_DRIVER)gxvalid $(ECHO_DRIVER_DESC)TrueTypeGX/AAT validation module$(ECHO_DRIVER_DONE)
|
||||
|
||||
# EOF
|
93
src/gxvalid/rules.mk
Normal file
93
src/gxvalid/rules.mk
Normal file
@ -0,0 +1,93 @@
|
||||
#
|
||||
# FreeType 2 TrueTypeGX/AAT validation driver configuration rules
|
||||
#
|
||||
|
||||
|
||||
# Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
|
||||
# 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.
|
||||
|
||||
|
||||
# GXV driver directory
|
||||
#
|
||||
GXV_DIR := $(SRC_DIR)/gxvalid
|
||||
|
||||
|
||||
# compilation flags for the driver
|
||||
#
|
||||
GXV_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(GXV_DIR))
|
||||
|
||||
|
||||
# GXV driver sources (i.e., C files)
|
||||
#
|
||||
GXV_DRV_SRC := $(GXV_DIR)/gxvcommn.c \
|
||||
$(GXV_DIR)/gxvfeat.c \
|
||||
$(GXV_DIR)/gxvbsln.c \
|
||||
$(GXV_DIR)/gxvtrak.c \
|
||||
$(GXV_DIR)/gxvopbd.c \
|
||||
$(GXV_DIR)/gxvprop.c \
|
||||
$(GXV_DIR)/gxvjust.c \
|
||||
$(GXV_DIR)/gxvmort.c \
|
||||
$(GXV_DIR)/gxvmort0.c \
|
||||
$(GXV_DIR)/gxvmort1.c \
|
||||
$(GXV_DIR)/gxvmort2.c \
|
||||
$(GXV_DIR)/gxvmort4.c \
|
||||
$(GXV_DIR)/gxvmort5.c \
|
||||
$(GXV_DIR)/gxvmorx.c \
|
||||
$(GXV_DIR)/gxvmorx0.c \
|
||||
$(GXV_DIR)/gxvmorx1.c \
|
||||
$(GXV_DIR)/gxvmorx2.c \
|
||||
$(GXV_DIR)/gxvmorx4.c \
|
||||
$(GXV_DIR)/gxvmorx5.c \
|
||||
$(GXV_DIR)/gxvlcar.c \
|
||||
$(GXV_DIR)/gxvkern.c \
|
||||
$(GXV_DIR)/gxvmod.c
|
||||
|
||||
# GXV driver headers
|
||||
#
|
||||
GXV_DRV_H := $(GXV_DIR)/gxvalid.h \
|
||||
$(GXV_DIR)/gxverror.h \
|
||||
$(GXV_DIR)/gxvcommn.h \
|
||||
$(GXV_DIR)/gxvmod.h \
|
||||
$(GXV_DIR)/gxvmort.h \
|
||||
$(GXV_DIR)/gxvmorx.h
|
||||
|
||||
|
||||
# GXV driver object(s)
|
||||
#
|
||||
# GXV_DRV_OBJ_M is used during `multi' builds.
|
||||
# GXV_DRV_OBJ_S is used during `single' builds.
|
||||
#
|
||||
GXV_DRV_OBJ_M := $(GXV_DRV_SRC:$(GXV_DIR)/%.c=$(OBJ_DIR)/%.$O)
|
||||
GXV_DRV_OBJ_S := $(OBJ_DIR)/gxvalid.$O
|
||||
|
||||
# GXV driver source file for single build
|
||||
#
|
||||
GXV_DRV_SRC_S := $(GXV_DIR)/gxvalid.c
|
||||
|
||||
|
||||
# GXV driver - single object
|
||||
#
|
||||
$(GXV_DRV_OBJ_S): $(GXV_DRV_SRC_S) $(GXV_DRV_SRC) \
|
||||
$(FREETYPE_H) $(GXV_DRV_H)
|
||||
$(GXV_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(GXV_DRV_SRC_S))
|
||||
|
||||
|
||||
# GXV driver - multiple objects
|
||||
#
|
||||
$(OBJ_DIR)/%.$O: $(GXV_DIR)/%.c $(FREETYPE_H) $(GXV_DRV_H)
|
||||
$(GXV_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
|
||||
|
||||
|
||||
# update main driver object lists
|
||||
#
|
||||
DRV_OBJS_S += $(GXV_DRV_OBJ_S)
|
||||
DRV_OBJS_M += $(GXV_DRV_OBJ_M)
|
||||
|
||||
|
||||
# EOF
|
Loading…
Reference in New Issue
Block a user