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:
Suzuki, Toshiya (鈴木俊哉) 2005-08-24 04:31:31 +00:00
parent 2752bd1a46
commit a438621451
49 changed files with 9821 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>
/* */

View File

@ -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)

View File

@ -41,6 +41,7 @@
/* pfr_fonts */
/* winfnt_fonts */
/* ot_validation */
/* gx_validation */
/* */
/***************************************************************************/

302
include/freetype/ftgxval.h Normal file
View 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 */

View File

@ -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 ::

View File

@ -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>

View File

@ -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 */

View 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 */

View File

@ -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' )

View File

@ -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
View 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 */

View File

@ -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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

452
src/gxvalid/gxvcommn.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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