parent
d9710afa38
commit
efda0541e6
49 changed files with 9821 additions and 3 deletions
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 |
@ -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 --- |
@ -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 */ |
@ -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 */ |
@ -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 */ |
File diff suppressed because it is too large
Load Diff
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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 */ |
@ -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
|
@ -0,0 +1,93 @@ |
||||
#
|
||||
# FreeType 2 TrueTypeGX/AAT validation driver configuration rules
|
||||
#
|
||||
|
||||
|
||||
# Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
|
||||
# David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
#
|
||||
# This file is part of the FreeType project, and may only be used, modified,
|
||||
# and distributed under the terms of the FreeType project license,
|
||||
# LICENSE.TXT. By continuing to use, modify, or distribute this file you
|
||||
# indicate that you have read the license and understand and accept it
|
||||
# fully.
|
||||
|
||||
|
||||
# GXV driver directory
|
||||
#
|
||||
GXV_DIR := $(SRC_DIR)/gxvalid
|
||||
|
||||
|
||||
# compilation flags for the driver
|
||||
#
|
||||
GXV_COMPILE := $(FT_COMPILE) $I$(subst /,$(COMPILER_SEP),$(GXV_DIR))
|
||||
|
||||
|
||||
# GXV driver sources (i.e., C files)
|
||||
#
|
||||
GXV_DRV_SRC := $(GXV_DIR)/gxvcommn.c \
|
||||
$(GXV_DIR)/gxvfeat.c \
|
||||
$(GXV_DIR)/gxvbsln.c \
|
||||
$(GXV_DIR)/gxvtrak.c \
|
||||
$(GXV_DIR)/gxvopbd.c \
|
||||
$(GXV_DIR)/gxvprop.c \
|
||||
$(GXV_DIR)/gxvjust.c \
|
||||
$(GXV_DIR)/gxvmort.c \
|
||||
$(GXV_DIR)/gxvmort0.c \
|
||||
$(GXV_DIR)/gxvmort1.c \
|
||||
$(GXV_DIR)/gxvmort2.c \
|
||||
$(GXV_DIR)/gxvmort4.c \
|
||||
$(GXV_DIR)/gxvmort5.c \
|
||||
$(GXV_DIR)/gxvmorx.c \
|
||||
$(GXV_DIR)/gxvmorx0.c \
|
||||
$(GXV_DIR)/gxvmorx1.c \
|
||||
$(GXV_DIR)/gxvmorx2.c \
|
||||
$(GXV_DIR)/gxvmorx4.c \
|
||||
$(GXV_DIR)/gxvmorx5.c \
|
||||
$(GXV_DIR)/gxvlcar.c \
|
||||
$(GXV_DIR)/gxvkern.c \
|
||||
$(GXV_DIR)/gxvmod.c
|
||||
|
||||
# GXV driver headers
|
||||
#
|
||||
GXV_DRV_H := $(GXV_DIR)/gxvalid.h \
|
||||
$(GXV_DIR)/gxverror.h \
|
||||
$(GXV_DIR)/gxvcommn.h \
|
||||
$(GXV_DIR)/gxvmod.h \
|
||||
$(GXV_DIR)/gxvmort.h \
|
||||
$(GXV_DIR)/gxvmorx.h
|
||||
|
||||
|
||||
# GXV driver object(s)
|
||||
#
|
||||
# GXV_DRV_OBJ_M is used during `multi' builds.
|
||||
# GXV_DRV_OBJ_S is used during `single' builds.
|
||||
#
|
||||
GXV_DRV_OBJ_M := $(GXV_DRV_SRC:$(GXV_DIR)/%.c=$(OBJ_DIR)/%.$O)
|
||||
GXV_DRV_OBJ_S := $(OBJ_DIR)/gxvalid.$O
|
||||
|
||||
# GXV driver source file for single build
|
||||
#
|
||||
GXV_DRV_SRC_S := $(GXV_DIR)/gxvalid.c
|
||||
|
||||
|
||||
# GXV driver - single object
|
||||
#
|
||||
$(GXV_DRV_OBJ_S): $(GXV_DRV_SRC_S) $(GXV_DRV_SRC) \
|
||||
$(FREETYPE_H) $(GXV_DRV_H)
|
||||
$(GXV_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(GXV_DRV_SRC_S))
|
||||
|
||||
|
||||
# GXV driver - multiple objects
|
||||
#
|
||||
$(OBJ_DIR)/%.$O: $(GXV_DIR)/%.c $(FREETYPE_H) $(GXV_DRV_H) |
||||
$(GXV_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
|
||||
|
||||
|
||||
# update main driver object lists
|
||||
#
|
||||
DRV_OBJS_S += $(GXV_DRV_OBJ_S)
|
||||
DRV_OBJS_M += $(GXV_DRV_OBJ_M)
|
||||
|
||||
|
||||
# EOF
|
Loading…
Reference in new issue