From: handa Date: Wed, 26 Feb 2003 13:25:10 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: REL-0-9-1~109 X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eea56792d95156f22b7b12450f80de700b4efe9c;p=m17n%2Flibotf.git *** empty log message *** --- diff --git a/example/otfdump.c b/example/otfdump.c index f788c55..d9d10dc 100644 --- a/example/otfdump.c +++ b/example/otfdump.c @@ -630,6 +630,9 @@ dump_chain_class_set_list (int indent, OTF_ChainClassSet *set, int count) } } + + + /* GSUB */ @@ -697,15 +700,15 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, if (subtable->Format == 1) { dump_coverage (indent, NULL, &subtable->Coverage); - dump_rule_set_list (indent, subtable->u.context1.SubRuleSet, - subtable->u.context1.SubRuleSetCount); + dump_rule_set_list (indent, subtable->u.context1.RuleSet, + subtable->u.context1.RuleSetCount); } else if (subtable->Format == 2) { dump_coverage (indent, NULL, &subtable->Coverage); dump_class_def (indent, NULL, &subtable->u.context2.ClassDef); - dump_class_set_list (indent, subtable->u.context2.SubClassSet, - subtable->u.context2.SubClassSetCnt); + dump_class_set_list (indent, subtable->u.context2.ClassSet, + subtable->u.context2.ClassSetCnt); } else if (subtable->Format == 3) { @@ -714,7 +717,7 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, subtable->u.context3.GlyphCount); dump_lookup_record_list (indent, subtable->u.context3.LookupRecord, - subtable->u.context3.SubstCount); + subtable->u.context3.LookupCount); } else printf (" invalid"); @@ -726,22 +729,22 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, dump_coverage (indent, NULL, &subtable->Coverage); dump_chain_rule_set_list (indent, - subtable->u.chain_context1.ChainSubRuleSet, - subtable->u.chain_context1.ChainSubRuleSetCount); + subtable->u.chain_context1.ChainRuleSet, + subtable->u.chain_context1.ChainRuleSetCount); } else if (subtable->Format == 2) { dump_coverage (indent, NULL, &subtable->Coverage); dump_class_def (indent, "BacktrackClassDef", - &subtable->u.chain_context2.Backtrack); + &subtable->u.chain_context2.BacktrackClassDef); dump_class_def (indent, "InputClassDef", - &subtable->u.chain_context2.Input); + &subtable->u.chain_context2.InputClassDef); dump_class_def (indent, "LookaheadClassDef", - &subtable->u.chain_context2.LookAhead); + &subtable->u.chain_context2.LookaheadClassDef); dump_chain_class_set_list (indent, - subtable->u.chain_context2.ChainSubClassSet, - subtable->u.chain_context2.ChainSubClassSetCnt); + subtable->u.chain_context2.ChainClassSet, + subtable->u.chain_context2.ChainClassSetCnt); } else if (subtable->Format == 3) { @@ -760,7 +763,7 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type, dump_lookup_record_list (indent, subtable->u.chain_context3.LookupRecord, - subtable->u.chain_context3.SubstCount); + subtable->u.chain_context3.LookupCount); } else printf (" invalid"); @@ -911,15 +914,15 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, if (subtable->Format == 1) { dump_coverage (indent, NULL, &subtable->Coverage); - dump_rule_set_list (indent, subtable->u.context1.PosRuleSet, - subtable->u.context1.PosRuleSetCount); + dump_rule_set_list (indent, subtable->u.context1.RuleSet, + subtable->u.context1.RuleSetCount); } else if (subtable->Format == 2) { dump_coverage (indent, NULL, &subtable->Coverage); dump_class_def (indent, NULL, &subtable->u.context2.ClassDef); - dump_class_set_list (indent, subtable->u.context2.PosClassSet, - subtable->u.context2.PosClassSetCnt); + dump_class_set_list (indent, subtable->u.context2.ClassSet, + subtable->u.context2.ClassSetCnt); } else if (subtable->Format == 3) { @@ -928,7 +931,7 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, subtable->u.context3.GlyphCount); dump_lookup_record_list (indent, subtable->u.context3.LookupRecord, - subtable->u.context3.PosCount); + subtable->u.context3.LookupCount); } else printf (" invalid"); @@ -940,22 +943,22 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, dump_coverage (indent, NULL, &subtable->Coverage); dump_chain_rule_set_list (indent, - subtable->u.chain_context1.ChainPosRuleSet, - subtable->u.chain_context1.ChainPosRuleSetCount); + subtable->u.chain_context1.ChainRuleSet, + subtable->u.chain_context1.ChainRuleSetCount); } else if (subtable->Format == 2) { dump_coverage (indent, NULL, &subtable->Coverage); dump_class_def (indent, "BacktrackClassDef", - &subtable->u.chain_context2.Backtrack); + &subtable->u.chain_context2.BacktrackClassDef); dump_class_def (indent, "InputClassDef", - &subtable->u.chain_context2.Input); + &subtable->u.chain_context2.InputClassDef); dump_class_def (indent, "LookaheadClassDef", - &subtable->u.chain_context2.LookAhead); + &subtable->u.chain_context2.LookaheadClassDef); dump_chain_class_set_list (indent, - subtable->u.chain_context2.ChainPosClassSet, - subtable->u.chain_context2.ChainPosClassSetCnt); + subtable->u.chain_context2.ChainClassSet, + subtable->u.chain_context2.ChainClassSetCnt); } else if (subtable->Format == 3) { @@ -974,7 +977,7 @@ dump_lookup_subtable_gpos (int indent, int index, unsigned type, dump_lookup_record_list (indent, subtable->u.chain_context3.LookupRecord, - subtable->u.chain_context3.PosCount); + subtable->u.chain_context3.LookupCount); } else printf (" invalid"); diff --git a/example/otfview.c b/example/otfview.c index 79eb728..5706e4c 100644 --- a/example/otfview.c +++ b/example/otfview.c @@ -13,7 +13,7 @@ #include #include -#define PIXEL_SIZE 20 +#define PIXEL_SIZE 40 //#define FONT_NAME "-adobe-courier-medium-r-normal--12-120-75-75-m-70-iso8859-1" #define FONT_NAME "6x13" @@ -145,10 +145,7 @@ main (int argc, char **argv) otf = OTF_open (argv[1]); if (! otf || OTF_get_table (otf, "head") < 0 - || OTF_get_table (otf, "cmap") < 0 - || OTF_get_table (otf, "GDEF") < 0 - || OTF_get_table (otf, "GSUB") < 0 - || OTF_get_table (otf, "GPOS") < 0) + || OTF_get_table (otf, "cmap") < 0) { OTF_perror ("otfview"); exit (1); diff --git a/src/otf.h b/src/otf.h index c84368e..31ff7b5 100644 --- a/src/otf.h +++ b/src/otf.h @@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */ /*** Table of contents: - (1) Structures for OTF tables and OTF itself + (1) Structures for OTF Layout tables and OTF itself (1-1) Basic types (1-2) "head" table (1-3) "name" table @@ -35,9 +35,10 @@ Boston, MA 02111-1307, USA. */ (1-5) Structures common to GDEF, GSUB, and GPOS (1-6) "GDEF" table (1-7) Structures for ScriptList, FeatureList, and LookupList - (1-8) "GSUB" table - (1-9) "GPOS" table - (1-9) Structure for OTF + (1-8) Structures common to GSUB and GPOS + (1-9) "GSUB" table + (1-10) "GPOS" table + (1-11) Structure for OTF (2) APIs for reading OTF (2-1) OTF_open() @@ -60,7 +61,8 @@ Boston, MA 02111-1307, USA. */ */ -/*** (1) Structures for OTF tables and OTF itself */ + +/*** (1) Structures for OTF Layout tables and OTF itself */ /*** (1-1) Basic types */ @@ -464,215 +466,231 @@ typedef struct OTF_Lookup *Lookup; } OTF_LookupList; -/*** (1-8) "GSUB" table */ + +/*** (1-8) Structures common to GSUB and GPOS */ + +/* For SubstLookupRecord (GSUB) and PosLookupRecord (GPOS). */ typedef struct { - int DeltaGlyphID; -} OTF_GSUB_Single1; + unsigned SequenceIndex; + unsigned LookupListIndex; +} OTF_LookupRecord; typedef struct { + OTF_Offset offset; unsigned GlyphCount; - OTF_GlyphID *Substitute; -} OTF_GSUB_Single2; - -typedef struct OTF_Sequence OTF_Sequence; + unsigned LookupCount; + OTF_GlyphID *Input; /* [ - 1] */ + OTF_LookupRecord *LookupRecord; /* [] */ +} OTF_Rule; typedef struct { - unsigned SequenceCount; - OTF_Sequence *Sequence; -} OTF_GSUB_Multiple1; + OTF_Offset offset; + unsigned RuleCount; + OTF_Rule *Rule; /* [] */ +} OTF_RuleSet; -struct OTF_Sequence +typedef struct { OTF_Offset offset; unsigned GlyphCount; - OTF_GlyphID *Substitute; -}; - -typedef struct OTF_AlternateSet OTF_AlternateSet; + unsigned LookupCount; + unsigned *Class; /* [ - 1] */ + OTF_LookupRecord *LookupRecord; /* [] */ +} OTF_ClassRule; typedef struct { - unsigned AlternateSetCount; - OTF_AlternateSet *AlternateSet; -} OTF_GSUB_Alternate1; - -struct OTF_AlternateSet -{ OTF_Offset offset; - unsigned GlyphCount; - OTF_GlyphID *Alternate; -}; - -typedef struct OTF_LigatureSet OTF_LigatureSet; -typedef struct OTF_Ligature OTF_Ligature; + unsigned ClassRuleCnt; + OTF_ClassRule *ClassRule; /* [] */ +} OTF_ClassSet; typedef struct { - unsigned LigSetCount; - OTF_LigatureSet *LigatureSet; -} OTF_GSUB_Ligature1; + OTF_Offset offset; + unsigned BacktrackGlyphCount; + OTF_GlyphID *Backtrack; + unsigned InputGlyphCount; + OTF_GlyphID *Input; + unsigned LookaheadGlyphCount; + OTF_GlyphID *LookAhead; + unsigned LookupCount; + OTF_LookupRecord *LookupRecord; +} OTF_ChainRule; -struct OTF_LigatureSet +typedef struct { OTF_Offset offset; - unsigned LigatureCount; - OTF_Ligature *Ligature; -}; + unsigned ChainRuleCount; + OTF_ChainRule *ChainRule; +} OTF_ChainRuleSet; -struct OTF_Ligature +typedef struct { OTF_Offset offset; - OTF_GlyphID LigGlyph; - unsigned CompCount; - OTF_GlyphID *Component; -}; + unsigned BacktrackGlyphCount; + unsigned *Backtrack; + unsigned InputGlyphCount; + unsigned *Input; + unsigned LookaheadGlyphCount; + unsigned *LookAhead; + unsigned LookupCount; + OTF_LookupRecord *LookupRecord; +} OTF_ChainClassRule; typedef struct { - unsigned SequenceIndex; - unsigned LookupListIndex; -} OTF_LookupRecord; + OTF_Offset offset; + unsigned ChainClassRuleCnt; + OTF_ChainClassRule *ChainClassRule; +} OTF_ChainClassSet; -typedef struct OTF_RuleSet OTF_RuleSet; + +/* Common to OTF_GSUB/GPOS_Context1/2/3. */ typedef struct { - unsigned SubRuleSetCount; - OTF_RuleSet *SubRuleSet; /* [] */ -} OTF_GSUB_Context1; - -typedef struct OTF_Rule OTF_Rule; + unsigned RuleSetCount; + OTF_RuleSet *RuleSet; /* [] */ +} OTF_Context1; -struct OTF_RuleSet +typedef struct { - OTF_Offset offset; - unsigned RuleCount; - OTF_Rule *Rule; /* [] */ -}; + OTF_ClassDef ClassDef; + unsigned ClassSetCnt; + OTF_ClassSet *ClassSet; /* [] */ +} OTF_Context2; -struct OTF_Rule +typedef struct { - OTF_Offset offset; unsigned GlyphCount; unsigned LookupCount; - OTF_GlyphID *Input; /* [ - 1] */ + OTF_Coverage *Coverage; /* [] */ OTF_LookupRecord *LookupRecord; /* [] */ -}; +} OTF_Context3; -typedef struct OTF_ClassSet OTF_ClassSet; + +/* Common to OTF_GSUB/GPOS_ChainContext1/2/3. */ typedef struct { - OTF_ClassDef ClassDef; - unsigned SubClassSetCnt; - OTF_ClassSet *SubClassSet; /* [] */ -} OTF_GSUB_Context2; + unsigned ChainRuleSetCount; + OTF_ChainRuleSet *ChainRuleSet; +} OTF_ChainContext1; -typedef struct OTF_ClassRule OTF_ClassRule; - -struct OTF_ClassSet +typedef struct { - OTF_Offset offset; - unsigned ClassRuleCnt; - OTF_ClassRule *ClassRule; /* [] */ -}; + OTF_ClassDef BacktrackClassDef; + OTF_ClassDef InputClassDef; + OTF_ClassDef LookaheadClassDef; + unsigned ChainClassSetCnt; + OTF_ChainClassSet *ChainClassSet; +} OTF_ChainContext2; -struct OTF_ClassRule +typedef struct { - OTF_Offset offset; - unsigned GlyphCount; + unsigned BacktrackGlyphCount; + OTF_Coverage *Backtrack; + unsigned InputGlyphCount; + OTF_Coverage *Input; + unsigned LookaheadGlyphCount; + OTF_Coverage *LookAhead; unsigned LookupCount; - unsigned *Class; /* [ - 1] */ - OTF_LookupRecord *LookupRecord; /* [] */ -}; + OTF_LookupRecord *LookupRecord; +} OTF_ChainContext3; + +/* Common to OTF_GSUB/GPOS. */ typedef struct { - unsigned GlyphCount; - unsigned SubstCount; - OTF_Coverage *Coverage; - OTF_LookupRecord *LookupRecord; -} OTF_GSUB_Context3; + OTF_Fixed Version; + OTF_ScriptList ScriptList; + OTF_FeatureList FeatureList; + OTF_LookupList LookupList; +} OTF_GSUB_GPOS; -typedef struct OTF_ChainRuleSet OTF_ChainRuleSet; +/*** (1-9) "GSUB" table */ typedef struct { - unsigned ChainSubRuleSetCount; - OTF_ChainRuleSet *ChainSubRuleSet; -} OTF_GSUB_ChainContext1; + int DeltaGlyphID; +} OTF_GSUB_Single1; + +typedef struct +{ + unsigned GlyphCount; + OTF_GlyphID *Substitute; +} OTF_GSUB_Single2; -typedef struct OTF_ChainRule OTF_ChainRule; +typedef struct OTF_Sequence OTF_Sequence; + +typedef struct +{ + unsigned SequenceCount; + OTF_Sequence *Sequence; +} OTF_GSUB_Multiple1; -struct OTF_ChainRuleSet +struct OTF_Sequence { OTF_Offset offset; - unsigned ChainRuleCount; - OTF_ChainRule *ChainRule; + unsigned GlyphCount; + OTF_GlyphID *Substitute; }; -struct OTF_ChainRule +typedef struct OTF_AlternateSet OTF_AlternateSet; + +typedef struct +{ + unsigned AlternateSetCount; + OTF_AlternateSet *AlternateSet; +} OTF_GSUB_Alternate1; + +struct OTF_AlternateSet { OTF_Offset offset; - unsigned BacktrackGlyphCount; - OTF_GlyphID *Backtrack; - unsigned InputGlyphCount; - OTF_GlyphID *Input; - unsigned LookaheadGlyphCount; - OTF_GlyphID *LookAhead; - unsigned LookupCount; - OTF_LookupRecord *LookupRecord; + unsigned GlyphCount; + OTF_GlyphID *Alternate; }; -typedef struct OTF_ChainClassSet OTF_ChainClassSet; +typedef struct OTF_LigatureSet OTF_LigatureSet; +typedef struct OTF_Ligature OTF_Ligature; typedef struct { - OTF_ClassDef Backtrack; - OTF_ClassDef Input; - OTF_ClassDef LookAhead; - unsigned ChainSubClassSetCnt; - OTF_ChainClassSet *ChainSubClassSet; -} OTF_GSUB_ChainContext2; - -typedef struct OTF_ChainClassRule OTF_ChainClassRule; + unsigned LigSetCount; + OTF_LigatureSet *LigatureSet; +} OTF_GSUB_Ligature1; -struct OTF_ChainClassSet +struct OTF_LigatureSet { OTF_Offset offset; - unsigned ChainClassRuleCnt; - OTF_ChainClassRule *ChainClassRule; + unsigned LigatureCount; + OTF_Ligature *Ligature; }; -struct OTF_ChainClassRule +struct OTF_Ligature { OTF_Offset offset; - unsigned BacktrackGlyphCount; - unsigned *Backtrack; - unsigned InputGlyphCount; - unsigned *Input; - unsigned LookaheadGlyphCount; - unsigned *LookAhead; - unsigned LookupCount; - OTF_LookupRecord *LookupRecord; + OTF_GlyphID LigGlyph; + unsigned CompCount; + OTF_GlyphID *Component; }; +typedef OTF_Context1 OTF_GSUB_Context1; -typedef struct -{ - unsigned BacktrackGlyphCount; - OTF_Coverage *Backtrack; - unsigned InputGlyphCount; - OTF_Coverage *Input; - unsigned LookaheadGlyphCount; - OTF_Coverage *LookAhead; - unsigned SubstCount; - OTF_LookupRecord *LookupRecord; -} OTF_GSUB_ChainContext3; +typedef OTF_Context2 OTF_GSUB_Context2; + +typedef OTF_Context3 OTF_GSUB_Context3; + +typedef OTF_ChainContext1 OTF_GSUB_ChainContext1; + +typedef OTF_ChainContext2 OTF_GSUB_ChainContext2; + +typedef OTF_ChainContext3 OTF_GSUB_ChainContext3; typedef struct { @@ -719,15 +737,9 @@ struct OTF_LookupSubTableGSUB } u; }; -typedef struct -{ - OTF_Fixed Version; - OTF_ScriptList ScriptList; - OTF_FeatureList FeatureList; - OTF_LookupList LookupList; -} OTF_GSUB; +typedef OTF_GSUB_GPOS OTF_GSUB; -/*** (1-8) "GPOS" table */ +/*** (1-10) "GPOS" table */ enum OTF_ValueFormat { @@ -861,54 +873,17 @@ typedef struct OTF_AnchorArray Mark2Array; } OTF_GPOS_MarkMark1; +typedef OTF_Context1 OTF_GPOS_Context1; -typedef struct -{ - unsigned PosRuleSetCount; - OTF_RuleSet *PosRuleSet; -} OTF_GPOS_Context1; +typedef OTF_Context2 OTF_GPOS_Context2; -typedef struct -{ - OTF_ClassDef ClassDef; - unsigned PosClassSetCnt; - OTF_ClassSet *PosClassSet; -} OTF_GPOS_Context2; +typedef OTF_Context3 OTF_GPOS_Context3; -typedef struct -{ - unsigned GlyphCount; - unsigned PosCount; - OTF_Coverage *Coverage; /* [] */ - OTF_LookupRecord *LookupRecord; /* [] */ -} OTF_GPOS_Context3; +typedef OTF_ChainContext1 OTF_GPOS_ChainContext1; -typedef struct -{ - unsigned ChainPosRuleSetCount; - OTF_ChainRuleSet *ChainPosRuleSet; -} OTF_GPOS_ChainContext1; +typedef OTF_ChainContext2 OTF_GPOS_ChainContext2; -typedef struct -{ - OTF_ClassDef Backtrack; - OTF_ClassDef Input; - OTF_ClassDef LookAhead; - unsigned ChainPosClassSetCnt; - OTF_ChainClassSet *ChainPosClassSet; -} OTF_GPOS_ChainContext2; - -typedef struct -{ - unsigned BacktrackGlyphCount; - OTF_Coverage *Backtrack; - unsigned InputGlyphCount; - OTF_Coverage *Input; - unsigned LookaheadGlyphCount; - OTF_Coverage *LookAhead; - unsigned PosCount; - OTF_LookupRecord *LookupRecord; -} OTF_GPOS_ChainContext3; +typedef OTF_ChainContext3 OTF_GPOS_ChainContext3; typedef struct { @@ -948,15 +923,9 @@ struct OTF_LookupSubTableGPOS } u; }; -typedef struct -{ - OTF_Fixed Version; - OTF_ScriptList ScriptList; - OTF_FeatureList FeatureList; - OTF_LookupList LookupList; -} OTF_GPOS; +typedef OTF_GSUB_GPOS OTF_GPOS; -/*** (1-9) Structure for OTF */ +/*** (1-11) Structure for OTF */ typedef struct { @@ -1281,9 +1250,9 @@ extern OTF_Tag OTF_tag (char *name); /*** Convert OTF tag to name string. - The OTF_tag_name() function converts OTF tag $TAG to a 5-byte - name string (including the terminating NUL), and store it in - $NAME. At least 5-byte space must be at $NAME. */ + The OTF_tag_name() function converts OTF tag $TAG to a 5-byte name + string (including the terminating NULL), and store it in $NAME. + At least 5-byte space must be at $NAME. */ extern void OTF_tag_name (OTF_Tag tag, char *name); diff --git a/src/otfdrive.c b/src/otfdrive.c index 336f0d8..e1cf19d 100644 --- a/src/otfdrive.c +++ b/src/otfdrive.c @@ -1,3 +1,26 @@ +/* otfdrive.c -- OpenType font driver. + +Copyright (C) 2003 + by AIST (National Institute of Advanced Industrial Science and Technology) + Registration Number H15PRO??? + +This file is part of the OTF library. + +The OTF library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2, or (at +your option) any later version. + +The OTF library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the OTF library; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + #include #include #include @@ -284,7 +307,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, if (subtable->Format == 1) { OTF_GSUB_Context1 *context1 = &subtable->u.context1; - OTF_RuleSet *set = context1->SubRuleSet + coverage_idx; + OTF_RuleSet *set = context1->RuleSet + coverage_idx; OTF_Rule *rule; int orig_used; int j, k; @@ -315,7 +338,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, int j, k; class = get_class_def (&context2->ClassDef, g->glyph_id); - set = context2->SubClassSet + class; + set = context2->ClassSet + class; for (j = 0; j < set->ClassRuleCnt; j++) { rule = set->ClassRule + j; @@ -353,7 +376,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, if (j < context3->GlyphCount) continue; orig_used = gstring->used; - for (k = 0; k < context3->SubstCount; k++) + for (k = 0; k < context3->LookupCount; k++) lookup_gsub (lookup_list, context3->LookupRecord[k].LookupListIndex, gstring, @@ -366,11 +389,61 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, if (subtable->Format == 1) OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)"); else if (subtable->Format == 2) - OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (not yet supported)"); + { + OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2; + OTF_ChainClassSet *set; + unsigned class; + int j; + int orig_used; + + printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id); + class = get_class_def (&context2->InputClassDef, g->glyph_id); + set = context2->ChainClassSet + class; + for (j = 0; j < set->ChainClassRuleCnt; j++) + { + OTF_ChainClassRule *rule = set->ChainClassRule + j; + int fore_idx = gidx + rule->InputGlyphCount; + int k; + + if (gidx < rule->BacktrackGlyphCount + || (gidx + rule->InputGlyphCount + + rule->LookaheadGlyphCount) >= gstring->used) + continue; + for (k = 0; k < rule->BacktrackGlyphCount; k++) + if (get_class_def (&context2->BacktrackClassDef, + gstring->glyphs[gidx - 1 - k].glyph_id) + != rule->Backtrack[k]) + break; + if (k < rule->BacktrackGlyphCount) + continue; + for (k = 1; k < rule->InputGlyphCount; k++) + if (get_class_def (&context2->InputClassDef, + gstring->glyphs[gidx + k].glyph_id) + != rule->Input[k - 1]) + break; + if (k < rule->InputGlyphCount) + continue; + for (k = 0; k < rule->LookaheadGlyphCount; k++) + if (get_class_def (&context2->LookaheadClassDef, + gstring->glyphs[fore_idx + k].glyph_id) + != rule->LookAhead[k]) + break; + if (k < rule->LookaheadGlyphCount) + continue; + + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gsub (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->InputGlyphCount + (gstring->used - orig_used); + break; + } + } else { - OTF_GSUB_ChainContext3 *context3 - = &subtable->u.chain_context3; + OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3; int back_gidx = gidx - context3->BacktrackGlyphCount; int fore_gidx = gidx + context3->InputGlyphCount; int orig_used; @@ -382,7 +455,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, for (j = 0; j < context3->BacktrackGlyphCount; j++) if (get_coverage_index (context3->Backtrack + j, - gstring->glyphs[back_gidx + j].glyph_id) + gstring->glyphs[gidx - 1 - j].glyph_id) < 0) break; if (j < context3->BacktrackGlyphCount) @@ -408,7 +481,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, continue; orig_used = gstring->used; - for (j = 0; j < context3->SubstCount; j++) + for (j = 0; j < context3->LookupCount; j++) lookup_gsub (lookup_list, context3->LookupRecord[j].LookupListIndex, gstring, @@ -593,7 +666,65 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, break; case 8: - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + if (subtable->Format == 1) + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + else if (subtable->Format == 2) + { + OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2; + OTF_ChainClassSet *set; + unsigned class; + int j; + int orig_used; + + printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id); + class = get_class_def (&context2->InputClassDef, g->glyph_id); + set = context2->ChainClassSet + class; + for (j = 0; j < set->ChainClassRuleCnt; j++) + { + OTF_ChainClassRule *rule = set->ChainClassRule + j; + int fore_idx = gidx + rule->InputGlyphCount; + int k; + + if (gidx < rule->BacktrackGlyphCount + || (gidx + rule->InputGlyphCount + + rule->LookaheadGlyphCount) >= gstring->used) + continue; + for (k = 0; k < rule->BacktrackGlyphCount; k++) + if (get_class_def (&context2->BacktrackClassDef, + gstring->glyphs[gidx - 1 - k].glyph_id) + != rule->Backtrack[k]) + break; + if (k < rule->BacktrackGlyphCount) + continue; + for (k = 1; k < rule->InputGlyphCount; k++) + if (get_class_def (&context2->InputClassDef, + gstring->glyphs[gidx + k].glyph_id) + != rule->Input[k - 1]) + break; + if (k < rule->InputGlyphCount) + continue; + for (k = 0; k < rule->LookaheadGlyphCount; k++) + if (get_class_def (&context2->LookaheadClassDef, + gstring->glyphs[fore_idx + k].glyph_id) + != rule->LookAhead[k]) + break; + if (k < rule->LookaheadGlyphCount) + continue; + + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->InputGlyphCount + (gstring->used - orig_used); + break; + } + } + else if (subtable->Format == 3) + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + else + OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)"); break; case 9: @@ -619,6 +750,8 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, static int lookup_cmap (OTF_cmap *cmap, int c) { + char *errfmt = "cmap driving%s"; + int errret = -1; int i; if (! cmap || ! cmap->Unicode) @@ -626,9 +759,6 @@ lookup_cmap (OTF_cmap *cmap, int c) switch (cmap->Unicode->subtable.format) { - case 0: - break; - case 4: { OTF_EncodingSubtable4 *sub4 = cmap->Unicode->subtable.f.f4; @@ -641,11 +771,18 @@ lookup_cmap (OTF_cmap *cmap, int c) return 0; if (sub4->segments[i].idRangeOffset == 0xFFFF) return c + sub4->segments[i].idDelta; + if (c == 0xFFFF) + return 0; return sub4->glyphIdArray[sub4->segments[i].idRangeOffset + (c - sub4->segments[i].startCount)]; } break; + + default: + OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (not yet supported)"); + break; } + return 0; } @@ -665,8 +802,11 @@ OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring) cmap = otf->cmap; for (i = 0; i < gstring->used; i++) + { gstring->glyphs[i].glyph_id = lookup_cmap (cmap, gstring->glyphs[i].c); - + if (gstring->glyphs[i].glyph_id < 0) + return -1; + } return 0; } @@ -712,12 +852,12 @@ OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, if (! otf->gsub && OTF_get_table (otf, "GSUB") < 0) - return -1; + return errret; gsub = otf->gsub; LangSys = get_langsys (&gsub->ScriptList, script, language); if (! LangSys) - return -1; + return errret; feature_index = alloca (sizeof (int) * gsub->FeatureList.FeatureCount); if (! feature_index) @@ -737,8 +877,12 @@ OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, int gidx = 0; while (gidx < gstring->used) - gidx = lookup_gsub (&gsub->LookupList, feature->LookupListIndex[j], - gstring, gidx); + { + gidx = lookup_gsub (&gsub->LookupList, + feature->LookupListIndex[j], gstring, gidx); + if (gidx < 0) + return errret; + } } } @@ -759,12 +903,12 @@ OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring, if (! otf->gpos && OTF_get_table (otf, "GPOS") < 0) - return -1; + return errret; gpos = otf->gpos; LangSys = get_langsys (&gpos->ScriptList, script, language); if (! LangSys) - return -1; + return errret; feature_index = alloca (sizeof (int) * gpos->FeatureList.FeatureCount); if (! feature_index) @@ -784,8 +928,12 @@ OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring, int gidx = 0; while (gidx < gstring->used) - gidx = lookup_gpos (&gpos->LookupList, feature->LookupListIndex[j], - gstring, gidx); + { + gidx = lookup_gpos (&gpos->LookupList, + feature->LookupListIndex[j], gstring, gidx); + if (gidx < 0) + return errret; + } } } diff --git a/src/otferror.c b/src/otferror.c index aed9623..315d3c9 100644 --- a/src/otferror.c +++ b/src/otferror.c @@ -23,7 +23,7 @@ int otf__error (int err, char *fmt, void *arg) { if (! error_message) - error_message = (char *) malloc (256); + error_message = (char *) malloc (1024); sprintf (error_message, "OTF-Error (%s): ", error_string[err]); sprintf (error_message + strlen (error_message), fmt, arg); OTF_error = err; diff --git a/src/otfopen.c b/src/otfopen.c index 648429f..d931462 100644 --- a/src/otfopen.c +++ b/src/otfopen.c @@ -1,3 +1,26 @@ +/* otfopen.c -- OpenType font reader. + +Copyright (C) 2003 + by AIST (National Institute of Advanced Industrial Science and Technology) + Registration Number H15PRO??? + +This file is part of the OTF library. + +The OTF library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2, or (at +your option) any later version. + +The OTF library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the OTF library; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + #include #include #include @@ -5,7 +28,33 @@ #include "otf.h" #include "otferror.h" -/* OTF_Stream +/*** + Table of contents (almost parallel to otf.h): + + (0) Stream handler + + (1) Readers for OTF Layout tables and OTF itself + (1-1) Basic types and functions + (1-2) "head" table + (1-3) "name" table + (1-4) "cmap" table + (1-5) Structures common to GDEF, GSUB, and GPOS + (1-6) "GDEF" table + (1-7) Structures for ScriptList, FeatureList, and LookupList + (1-8) Structures common to GSUB and GPOS + (1-9) "GSUB" table + (1-10) "GPOS" table + (1-11) Structure for OTF + + (2) APIs for reading OTF + (2-1) OTF_open() + (2-2) OTF_close() + (2-3) OTF_get_table() + + (5) APIs miscellaneous +*/ + +/* (0) Stream handler Example of typical usage of OTF_Stream. @@ -162,6 +211,9 @@ free_stream (OTF_Stream *stream) #define READ_GLYPHID READ_USHORT +/*** (1) Structures for OTF Layout tables and OTF itself */ + +/*** (1-1) Basic types and functions */ enum OTF_TableType { @@ -259,134 +311,8 @@ allocate_memory_record (OTF *otf) } \ } while (0) - - - -static void *read_head_table (OTF *otf, OTF_Stream *stream); -static void *read_name_table (OTF *otf, OTF_Stream *stream); -static void *read_cmap_table (OTF *otf, OTF_Stream *stream); -static void *read_gdef_table (OTF *otf, OTF_Stream *stream); -static void *read_gsub_table (OTF *otf, OTF_Stream *stream); -static void *read_gpos_table (OTF *otf, OTF_Stream *stream); - -int -read_offset_table (OTF *otf, OTF_Stream *stream, OTF_OffsetTable *table) -{ - int errret = -1; - - READ_FIXED (stream, table->sfnt_version); - READ_USHORT (stream, table->numTables); - READ_USHORT (stream, table->searchRange); - READ_USHORT (stream, table->enterSelector); - READ_USHORT (stream, table->rangeShift); - return 0; -} - -static OTF_Tag -read_table_directory (OTF_Stream *stream, OTF_TableDirectory *table) -{ - int errret = 0; - OTF_Tag tag; - - READ_TAG (stream, tag); - table->tag = tag; - table->name[0] = tag >> 24; - table->name[1] = (tag >> 16) & 0xFF; - table->name[0] = (tag >> 8) & 0xFF; - table->name[0] = tag >> 8; - table->name[0] = '\0'; - READ_ULONG (stream, table->checkSum); - READ_ULONG (stream, table->offset); - READ_ULONG (stream, table->length); - return tag; -} - -static int -read_header_part (OTF *otf, FILE *fp) -{ - char *errfmt = "otf header%s"; - int errret = -1; - OTF_Tag head_tag, name_tag, cmap_tag, gdef_tag, gsub_tag, gpos_tag; - OTF_Stream *stream; - int i; - OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data; - - internal_data->table_info[OTF_TABLE_TYPE_HEAD].address = (void *) &otf->head; - internal_data->table_info[OTF_TABLE_TYPE_HEAD].reader = read_head_table; - internal_data->table_info[OTF_TABLE_TYPE_NAME].address = (void *) &otf->name; - internal_data->table_info[OTF_TABLE_TYPE_NAME].reader = read_name_table; - internal_data->table_info[OTF_TABLE_TYPE_CMAP].address = (void *) &otf->cmap; - internal_data->table_info[OTF_TABLE_TYPE_CMAP].reader = read_cmap_table; - internal_data->table_info[OTF_TABLE_TYPE_GDEF].address = (void *) &otf->gdef; - internal_data->table_info[OTF_TABLE_TYPE_GDEF].reader = read_gdef_table; - internal_data->table_info[OTF_TABLE_TYPE_GSUB].address = (void *) &otf->gsub; - internal_data->table_info[OTF_TABLE_TYPE_GSUB].reader = read_gsub_table; - internal_data->table_info[OTF_TABLE_TYPE_GPOS].address = (void *) &otf->gpos; - internal_data->table_info[OTF_TABLE_TYPE_GPOS].reader = read_gpos_table; - - head_tag = OTF_tag ("head"); - name_tag = OTF_tag ("name"); - cmap_tag = OTF_tag ("cmap"); - gdef_tag = OTF_tag ("GDEF"); - gsub_tag = OTF_tag ("GSUB"); - gpos_tag = OTF_tag ("GPOS"); - - stream = make_stream (); - if (! stream) - return -1; - - internal_data->header_stream = stream; - - /* Size of Offset Table is 12 bytes. */ - if (setup_stream (stream, fp, 0, 12, "Offset Table") < 0) - return -1; - if (read_offset_table (otf, stream, &otf->offset_table) < 0) - return -1; - - /* Size of each Table Directory is 16 bytes. */ - if (setup_stream (stream, fp, 12, 16 * otf->offset_table.numTables, - "Table Directory") < 0) - return -1; - - OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables, " (OffsetTable)"); - for (i = 0; i < otf->offset_table.numTables; i++) - { - OTF_Tag tag = read_table_directory (stream, otf->table_dirs + i); - OTF_TableInfo *table_info = NULL; - - if (! tag) - return -1; - if (tag == head_tag) - table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD; - else if (tag == name_tag) - table_info = internal_data->table_info + OTF_TABLE_TYPE_NAME; - else if (tag == cmap_tag) - table_info = internal_data->table_info + OTF_TABLE_TYPE_CMAP; - else if (tag == gdef_tag) - table_info = internal_data->table_info + OTF_TABLE_TYPE_GDEF; - else if (tag == gsub_tag) - table_info = internal_data->table_info + OTF_TABLE_TYPE_GSUB; - else if (tag == gpos_tag) - table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS; - - if (table_info) - { - table_info->stream = make_stream (); - if (setup_stream (table_info->stream, fp, - otf->table_dirs[i].offset, - otf->table_dirs[i].length, - otf->table_dirs[i].name) < 0) - return -1; - } - } - - internal_data->header_stream = NULL; - free_stream (stream); - return 0; -} - - +/*** (1-2) "head" table */ static void * read_head_table (OTF *otf, OTF_Stream *stream) @@ -407,162 +333,207 @@ read_head_table (OTF *otf, OTF_Stream *stream) } +/*** (1-3) "name" table */ -static int -read_script_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_ScriptList *list) +static char * +read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec, int bytes) { - char *errfmt = "Script List%s"; - int errret = -1; - int i, j, k; + char *errfmt = "nameID (%d)"; + void *errret = NULL; + OTF_StreamState state; + char *str; + int i; + int c; - SEEK_STREAM (stream, offset); - READ_USHORT (stream, list->ScriptCount); - OTF_CALLOC (list->Script, list->ScriptCount, ""); + SAVE_STREAM (stream, state); + SEEK_STREAM (stream, stream->pos + rec->offset); - for (i = 0; i < list->ScriptCount; i++) + if (bytes == 1) { - READ_TAG (stream, list->Script[i].ScriptTag); - READ_OFFSET (stream, list->Script[i].offset); + OTF_MALLOC (str, rec->length + 1, (void *) rec->nameID); + READ_BYTES (stream, str, rec->length); + for (i = 0; i < rec->length; i++) + if (str[i] < 0) + str[i] = '?'; } - for (i = 0; i < list->ScriptCount; i++) + else if (bytes == 2) { - OTF_Script *script = list->Script + i; - long script_offset = offset + script->offset; - - SEEK_STREAM (stream, script_offset); - READ_OFFSET (stream, script->DefaultLangSysOffset); - READ_USHORT (stream, script->LangSysCount); - OTF_MALLOC (script->LangSysRecord, script->LangSysCount, " (LangSys)"); - OTF_CALLOC (script->LangSys, script->LangSysCount, " (LangSys)"); - for (j = 0; j < script->LangSysCount; j++) - { - READ_TAG (stream, script->LangSysRecord[j].LangSysTag); - READ_OFFSET (stream, script->LangSysRecord[j].LangSys); - } - - if (script->DefaultLangSysOffset) + OTF_MALLOC (str, rec->length / 2 + 1, (void *) rec->nameID); + for (i = 0; i < rec->length / 2; i++) { - OTF_LangSys *langsys = &script->DefaultLangSys; - - SEEK_STREAM (stream, script_offset + script->DefaultLangSysOffset); - READ_OFFSET (stream, langsys->LookupOrder); - READ_USHORT (stream, langsys->ReqFeatureIndex); - READ_USHORT (stream, langsys->FeatureCount); - OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount, - " (FeatureIndex)"); - for (k = 0; k < langsys->FeatureCount; k++) - READ_USHORT (stream, langsys->FeatureIndex[k]); + READ_USHORT (stream, c); + if (c >= 128) + c = '?'; + str[i] = c; } - - for (j = 0; j < script->LangSysCount; j++) + } + else if (bytes == 4) + { + OTF_MALLOC (str, rec->length / 4 + 1, (void *) rec->nameID); + for (i = 0; i < rec->length / 4; i++) { - OTF_LangSys *langsys = script->LangSys + j; - - SEEK_STREAM (stream, - script_offset + script->LangSysRecord[j].LangSys); - READ_OFFSET (stream, langsys->LookupOrder); - READ_USHORT (stream, langsys->ReqFeatureIndex); - READ_USHORT (stream, langsys->FeatureCount); - OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount, - " (FeatureIndex)"); - for (k = 0; k < langsys->FeatureCount; k++) - READ_USHORT (stream, langsys->FeatureIndex[k]); + READ_ULONG (stream, c); + if (c >= 128) + c = '?'; + str[i] = c; } } - - return 0; + str[i] = '\0'; + RESTORE_STREAM (stream, state); + return str; } -static int -read_feature_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_FeatureList *list) +static void * +read_name_table (OTF *otf, OTF_Stream *stream) { - char *errfmt = "Feature List%s"; - int errret = -1; - int i, j; + char *errfmt = "name%s"; + void *errret = NULL; + OTF_name *name; + int i; - READ_UINT16 (stream, list->FeatureCount); - OTF_CALLOC (list->Feature, list->FeatureCount, ""); - for (i = 0; i < list->FeatureCount; i++) + OTF_CALLOC (name, 1, ""); + READ_USHORT (stream, name->format); + READ_USHORT (stream, name->count); + READ_USHORT (stream, name->stringOffset); + OTF_MALLOC (name->nameRecord, name->count, ""); + for (i = 0; i < name->count; i++) { - READ_TAG (stream, list->Feature[i].FeatureTag); - READ_OFFSET (stream, list->Feature[i].offset); + OTF_NameRecord *rec = name->nameRecord + i; + + READ_USHORT (stream, rec->platformID); + READ_USHORT (stream, rec->encodingID); + READ_USHORT (stream, rec->languageID); + READ_USHORT (stream, rec->nameID); + READ_USHORT (stream, rec->length); + READ_USHORT (stream, rec->offset); } - for (i = 0; i < list->FeatureCount; i++) + for (i = 0; i < name->count; i++) { - OTF_Feature *feature = list->Feature + i; + OTF_NameRecord *rec = name->nameRecord + i; + int nameID = rec->nameID; - SEEK_STREAM (stream, offset + feature->offset); - READ_OFFSET (stream, feature->FeatureParams); - READ_UINT16 (stream, feature->LookupCount); - OTF_MALLOC (feature->LookupListIndex, feature->LookupCount, - " (LookupListIndex)"); - for (j = 0; j < feature->LookupCount; j++) - READ_UINT16 (stream, feature->LookupListIndex[j]); + if (nameID <= OTF_max_nameID + && ! name->name[nameID]) + { + if (rec->platformID == 0) + name->name[nameID] = read_name (otf, stream, rec, + rec->encodingID <= 3 ? 2 : 4); + else if (rec->platformID == 1 + && rec->encodingID == 0) + name->name[nameID] = read_name (otf, stream, rec, 1); + else if (rec->platformID == 3 + && (rec->encodingID == 1 || rec->encodingID == 10)) + name->name[nameID] = read_name (otf, stream, + rec, rec->encodingID == 1 ? 2 : 4); + } } - return 0; + return name; } -static int read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, - long offset, unsigned type, - OTF_LookupSubTableGSUB *subtable); -static int read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, - long offset, unsigned type, - OTF_LookupSubTableGPOS *subtable); + +/*** (1-4) "cmap" table */ -static int -read_lookup_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_LookupList *list, int gsub) +static void * +read_cmap_table (OTF *otf, OTF_Stream *stream) { - char *errfmt = "Lookup List%s"; - int errret = -1; - int i, j; - - SEEK_STREAM (stream, offset); - READ_UINT16 (stream, list->LookupCount); - OTF_CALLOC (list->Lookup, list->LookupCount, ""); + char *errfmt = "cmap%s"; + void *errret = NULL; + OTF_cmap *cmap; + int i; - for (i = 0; i < list->LookupCount; i++) - READ_OFFSET (stream, list->Lookup[i].offset); - for (i = 0; i < list->LookupCount; i++) + OTF_CALLOC (cmap, 1, ""); + READ_USHORT (stream, cmap->version); + READ_USHORT (stream, cmap->numTables); + OTF_MALLOC (cmap->EncodingRecord, cmap->numTables, ""); + for (i = 0; i < cmap->numTables; i++) { - OTF_Lookup *lookup = list->Lookup + i; + READ_USHORT (stream, cmap->EncodingRecord[i].platformID); + READ_USHORT (stream, cmap->EncodingRecord[i].encodingID); + READ_ULONG (stream, cmap->EncodingRecord[i].offset); + if (cmap->EncodingRecord[i].platformID == 3 + && cmap->EncodingRecord[i].encodingID == 1) + cmap->Unicode = cmap->EncodingRecord + i; + } + for (i = 0; i < cmap->numTables; i++) + { + unsigned format; - SEEK_STREAM (stream, offset + lookup->offset); - READ_UINT16 (stream, lookup->LookupType); - READ_UINT16 (stream, lookup->LookupFlag); - READ_UINT16 (stream, lookup->SubTableCount); - OTF_MALLOC (lookup->SubTableOffset, lookup->SubTableCount, - " (SubTableOffset)"); - if (gsub) - OTF_CALLOC (lookup->SubTable.gsub, lookup->SubTableCount, - " (SubTable)"); + SEEK_STREAM (stream, cmap->EncodingRecord[i].offset); + READ_USHORT (stream, format); + cmap->EncodingRecord[i].subtable.format = format; + READ_USHORT (stream, cmap->EncodingRecord[i].subtable.length); + if (format == 8 || format == 10 || format == 12) + { + READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length); + READ_ULONG (stream, cmap->EncodingRecord[i].subtable.language); + } else - OTF_CALLOC (lookup->SubTable.gpos, lookup->SubTableCount, - " (SubTable)"); - for (j = 0; j < lookup->SubTableCount; j++) - READ_OFFSET (stream, lookup->SubTableOffset[j]); - for (j = 0; j < lookup->SubTableCount; j++) { - long this_offset - = offset + lookup->offset + lookup->SubTableOffset[j]; + READ_USHORT (stream, cmap->EncodingRecord[i].subtable.language); + } + switch (format) + { + case 0: + { + OTF_MALLOC (cmap->EncodingRecord[i].subtable.f.f0, 1, + " (EncodingRecord)"); + READ_BYTES (stream, + cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray, + 256); + } + break; - if (gsub - ? read_lookup_subtable_gsub (otf, stream, this_offset, - lookup->LookupType, - lookup->SubTable.gsub + j) < 0 - : read_lookup_subtable_gpos (otf, stream, this_offset, - lookup->LookupType, - lookup->SubTable.gpos + j) < 0) - return errret; + case 2: + break; + + case 4: + { + OTF_EncodingSubtable4 *sub4; + int segCount; + int j; + unsigned dummy; + + OTF_MALLOC (sub4, 1, " (EncodingSubtable4)"); + cmap->EncodingRecord[i].subtable.f.f4 = sub4; + READ_USHORT (stream, sub4->segCountX2); + segCount = sub4->segCountX2 / 2; + READ_USHORT (stream, sub4->searchRange); + READ_USHORT (stream, sub4->entrySelector); + READ_USHORT (stream, sub4->rangeShift); + OTF_MALLOC (sub4->segments, segCount, " (segCount)"); + for (j = 0; j < segCount; j++) + READ_USHORT (stream, sub4->segments[j].endCount); + READ_USHORT (stream, dummy); + for (j = 0; j < segCount; j++) + READ_USHORT (stream, sub4->segments[j].startCount); + for (j = 0; j < segCount; j++) + READ_SHORT (stream, sub4->segments[j].idDelta); + for (j = 0; j < segCount; j++) + { + unsigned off; + unsigned rest = 2 * (segCount - j); + + READ_USHORT (stream, off); + if (off == 0) + sub4->segments[j].idRangeOffset = 0xFFFF; + else + sub4->segments[j].idRangeOffset = (off - rest) / 2; + } + j = (cmap->EncodingRecord[i].subtable.length + - (14 + 2 * (segCount * 4 + 1))); + sub4->GlyphCount = j / 2; + OTF_MALLOC (sub4->glyphIdArray, sub4->GlyphCount, " (GlyphCount)"); + for (j = 0; j < sub4->GlyphCount; j++) + READ_USHORT (stream, sub4->glyphIdArray[j]); + } } } - - return 0; + return cmap; } + +/*** (1-5) Structures common to GDEF, GSUB, and GPOS */ /* Read Glyph-IDs from STREAM. Allocate memory for IDS, and store the Glyph-IDs there. If COUNT is negative, read the number of @@ -789,76 +760,367 @@ read_device_table (OTF *otf, OTF_Stream *stream, long offset, return 0; } -static unsigned -read_lookup_record_list (OTF *otf, OTF_Stream *stream, - OTF_LookupRecord **record, int count) + +/*** (1-6) "GDEF" table */ + +static int +read_attach_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_AttachList *list) { - char *errfmt = "LookupRecord%s"; - unsigned errret = 0; - int i; + char *errfmt = "AttachList%s"; + int errret = -1; + int i, j; - if (count < 0) - READ_UINT16 (stream, count); - if (! count) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - OTF_MALLOC (*record, count, ""); - for (i = 0; i < count; i++) + if (read_coverage (otf, stream, offset, &list->Coverage) < 0) + return -1; + READ_UINT16 (stream, list->GlyphCount); + OTF_MALLOC (list->AttachPoint, list->GlyphCount, ""); + for (i = 0; i < list->GlyphCount; i++) + READ_OFFSET (stream, list->AttachPoint[i].offset); + for (i = 0; i < list->GlyphCount; i++) { - READ_UINT16 (stream, (*record)[i].SequenceIndex); - READ_UINT16 (stream, (*record)[i].LookupListIndex); + int count; + + SEEK_STREAM (stream, offset + list->AttachPoint[i].offset); + READ_UINT16 (stream, count); + list->AttachPoint[i].PointCount = count; + OTF_MALLOC (list->AttachPoint[i].PointIndex, count, " (PointIndex)"); + for (j = 0; j < count; j++) + READ_UINT16 (stream, list->AttachPoint[i].PointIndex[j]); } - return count; + return 0; } -static unsigned -read_rule_list (OTF *otf, OTF_Stream *stream, long offset, OTF_Rule **rule) +static int +read_caret_value (OTF *otf, OTF_Stream *stream, long offset, + OTF_CaretValue *caret) { - char *errfmt = "List of Rule%s"; - unsigned errret = 0; - OTF_StreamState state; - unsigned count; - int i; + char *errfmt = "CaretValue%s"; + int errret = -1; - READ_UINT16 (stream, count); - if (! count) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - OTF_MALLOC (*rule, count, ""); - for (i = 0; i < count; i++) - { - READ_OFFSET (stream, (*rule)[i].offset); - if (! (*rule)[i].offset) - OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); - } - SAVE_STREAM (stream, state); - for (i = 0; i < count; i++) + SEEK_STREAM (stream, offset + caret->offset); + READ_UINT16 (stream, caret->CaretValueFormat); + if (caret->CaretValueFormat == 1) + READ_INT16 (stream, caret->f.f1.Coordinate); + else if (caret->CaretValueFormat == 2) + READ_UINT16 (stream, caret->f.f2.CaretValuePoint); + else if (caret->CaretValueFormat == 3) { - SEEK_STREAM (stream, offset + (*rule)[i].offset); - READ_UINT16 (stream, (*rule)[i].GlyphCount); - if ((*rule)[i].GlyphCount == 0) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - READ_UINT16 (stream, (*rule)[i].LookupCount); - if (read_glyph_ids (otf, stream, &(*rule)[i].Input, 0, - (*rule)[i].GlyphCount) < 0) - return errret; - if (read_lookup_record_list (otf, stream, &(*rule)[i].LookupRecord, - (*rule)[i].LookupCount) == 0) - return errret; + READ_INT16 (stream, caret->f.f3.Coordinate); + if (read_device_table (otf, stream, offset + caret->offset, + &caret->f.f3.DeviceTable) < 0) + return -1; } - RESTORE_STREAM (stream, state); - return count; + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid format)"); + return 0; } - -static unsigned -read_rule_set_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_RuleSet **set) +static int +read_lig_caret_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_LigCaretList *list) { - char *errfmt = "List of RuleSet%s"; - unsigned errret = 0; - OTF_StreamState state; - unsigned count; - int i; - + char *errfmt = "LigCaretList%s"; + int errret = -1; + int i, j; + + if (read_coverage (otf, stream, offset, &list->Coverage) < 0) + return -1; + READ_UINT16 (stream, list->LigGlyphCount); + OTF_MALLOC (list->LigGlyph, list->LigGlyphCount, ""); + for (i = 0; i < list->LigGlyphCount; i++) + READ_OFFSET (stream, list->LigGlyph[i].offset); + for (i = 0; i < list->LigGlyphCount; i++) + { + int count; + + SEEK_STREAM (stream, offset + list->LigGlyph[i].offset); + READ_UINT16 (stream, count); + list->LigGlyph[i].CaretCount = count; + OTF_MALLOC (list->LigGlyph[i].CaretValue, count, " (CaretValue)"); + for (j = 0; j < count; j++) + READ_OFFSET (stream, list->LigGlyph[i].CaretValue[j].offset); + for (j = 0; j < count; j++) + if (read_caret_value (otf, stream, offset + list->LigGlyph[i].offset, + &list->LigGlyph[i].CaretValue[j]) < 0) + return -1; + } + return 0; +} + +static int +read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header) +{ + int errret = -1; + + READ_FIXED (stream, header->Version); + READ_OFFSET (stream, header->GlyphClassDef); + READ_OFFSET (stream, header->AttachList); + READ_OFFSET (stream, header->LigCaretList); + READ_OFFSET (stream, header->MarkAttachClassDef); + return 0; +} + +static void * +read_gdef_table (OTF *otf, OTF_Stream *stream) +{ + char *errfmt = "GDEF%s"; + void *errret = NULL; + OTF_GDEF *gdef; + + OTF_CALLOC (gdef, 1, ""); + read_gdef_header (stream, (OTF_GDEFHeader *) &gdef->header); + if (gdef->header.GlyphClassDef) + { + gdef->glyph_class_def.offset = gdef->header.GlyphClassDef; + read_class_def_without_offset (otf, stream, &gdef->glyph_class_def); + } + if (gdef->header.AttachList) + read_attach_list (otf, stream, gdef->header.AttachList, + &gdef->attach_list); + if (gdef->header.LigCaretList) + read_lig_caret_list (otf, stream, gdef->header.LigCaretList, + &gdef->lig_caret_list); + if (gdef->header.MarkAttachClassDef) + { + gdef->mark_attach_class_def.offset = gdef->header.MarkAttachClassDef; + read_class_def_without_offset (otf, stream, &gdef->mark_attach_class_def); + } + + return gdef; +} + + +/*** (1-7) Structures for ScriptList, FeatureList, and LookupList */ + +static int +read_script_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_ScriptList *list) +{ + char *errfmt = "Script List%s"; + int errret = -1; + int i, j, k; + + SEEK_STREAM (stream, offset); + READ_USHORT (stream, list->ScriptCount); + OTF_CALLOC (list->Script, list->ScriptCount, ""); + + for (i = 0; i < list->ScriptCount; i++) + { + READ_TAG (stream, list->Script[i].ScriptTag); + READ_OFFSET (stream, list->Script[i].offset); + } + for (i = 0; i < list->ScriptCount; i++) + { + OTF_Script *script = list->Script + i; + long script_offset = offset + script->offset; + + SEEK_STREAM (stream, script_offset); + READ_OFFSET (stream, script->DefaultLangSysOffset); + READ_USHORT (stream, script->LangSysCount); + OTF_MALLOC (script->LangSysRecord, script->LangSysCount, " (LangSys)"); + OTF_CALLOC (script->LangSys, script->LangSysCount, " (LangSys)"); + for (j = 0; j < script->LangSysCount; j++) + { + READ_TAG (stream, script->LangSysRecord[j].LangSysTag); + READ_OFFSET (stream, script->LangSysRecord[j].LangSys); + } + + if (script->DefaultLangSysOffset) + { + OTF_LangSys *langsys = &script->DefaultLangSys; + + SEEK_STREAM (stream, script_offset + script->DefaultLangSysOffset); + READ_OFFSET (stream, langsys->LookupOrder); + READ_USHORT (stream, langsys->ReqFeatureIndex); + READ_USHORT (stream, langsys->FeatureCount); + OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount, + " (FeatureIndex)"); + for (k = 0; k < langsys->FeatureCount; k++) + READ_USHORT (stream, langsys->FeatureIndex[k]); + } + + for (j = 0; j < script->LangSysCount; j++) + { + OTF_LangSys *langsys = script->LangSys + j; + + SEEK_STREAM (stream, + script_offset + script->LangSysRecord[j].LangSys); + READ_OFFSET (stream, langsys->LookupOrder); + READ_USHORT (stream, langsys->ReqFeatureIndex); + READ_USHORT (stream, langsys->FeatureCount); + OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount, + " (FeatureIndex)"); + for (k = 0; k < langsys->FeatureCount; k++) + READ_USHORT (stream, langsys->FeatureIndex[k]); + } + } + + return 0; +} + +static int +read_feature_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_FeatureList *list) +{ + char *errfmt = "Feature List%s"; + int errret = -1; + int i, j; + + READ_UINT16 (stream, list->FeatureCount); + OTF_CALLOC (list->Feature, list->FeatureCount, ""); + for (i = 0; i < list->FeatureCount; i++) + { + READ_TAG (stream, list->Feature[i].FeatureTag); + READ_OFFSET (stream, list->Feature[i].offset); + } + for (i = 0; i < list->FeatureCount; i++) + { + OTF_Feature *feature = list->Feature + i; + + SEEK_STREAM (stream, offset + feature->offset); + READ_OFFSET (stream, feature->FeatureParams); + READ_UINT16 (stream, feature->LookupCount); + OTF_MALLOC (feature->LookupListIndex, feature->LookupCount, + " (LookupListIndex)"); + for (j = 0; j < feature->LookupCount; j++) + READ_UINT16 (stream, feature->LookupListIndex[j]); + } + + return 0; +} + +static int read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, + long offset, unsigned type, + OTF_LookupSubTableGSUB *subtable); +static int read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, + long offset, unsigned type, + OTF_LookupSubTableGPOS *subtable); + +static int +read_lookup_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_LookupList *list, int gsubp) +{ + char *errfmt = "Lookup List%s"; + int errret = -1; + int i, j; + + SEEK_STREAM (stream, offset); + READ_UINT16 (stream, list->LookupCount); + OTF_CALLOC (list->Lookup, list->LookupCount, ""); + + for (i = 0; i < list->LookupCount; i++) + READ_OFFSET (stream, list->Lookup[i].offset); + for (i = 0; i < list->LookupCount; i++) + { + OTF_Lookup *lookup = list->Lookup + i; + + SEEK_STREAM (stream, offset + lookup->offset); + READ_UINT16 (stream, lookup->LookupType); + READ_UINT16 (stream, lookup->LookupFlag); + READ_UINT16 (stream, lookup->SubTableCount); + OTF_MALLOC (lookup->SubTableOffset, lookup->SubTableCount, + " (SubTableOffset)"); + if (gsubp) + OTF_CALLOC (lookup->SubTable.gsub, lookup->SubTableCount, + " (SubTable)"); + else + OTF_CALLOC (lookup->SubTable.gpos, lookup->SubTableCount, + " (SubTable)"); + for (j = 0; j < lookup->SubTableCount; j++) + READ_OFFSET (stream, lookup->SubTableOffset[j]); + for (j = 0; j < lookup->SubTableCount; j++) + { + long this_offset + = offset + lookup->offset + lookup->SubTableOffset[j]; + + if (gsubp + ? read_lookup_subtable_gsub (otf, stream, this_offset, + lookup->LookupType, + lookup->SubTable.gsub + j) < 0 + : read_lookup_subtable_gpos (otf, stream, this_offset, + lookup->LookupType, + lookup->SubTable.gpos + j) < 0) + return errret; + } + } + + return 0; +} + + +/*** (1-8) Structures common to GSUB and GPOS */ + +static unsigned +read_lookup_record_list (OTF *otf, OTF_Stream *stream, + OTF_LookupRecord **record, int count) +{ + char *errfmt = "LookupRecord%s"; + unsigned errret = 0; + int i; + + if (count < 0) + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*record, count, ""); + for (i = 0; i < count; i++) + { + READ_UINT16 (stream, (*record)[i].SequenceIndex); + READ_UINT16 (stream, (*record)[i].LookupListIndex); + } + return count; +} + +static unsigned +read_rule_list (OTF *otf, OTF_Stream *stream, long offset, OTF_Rule **rule) +{ + char *errfmt = "List of Rule%s"; + unsigned errret = 0; + OTF_StreamState state; + unsigned count; + int i; + + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*rule, count, ""); + for (i = 0; i < count; i++) + { + READ_OFFSET (stream, (*rule)[i].offset); + if (! (*rule)[i].offset) + OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)"); + } + SAVE_STREAM (stream, state); + for (i = 0; i < count; i++) + { + SEEK_STREAM (stream, offset + (*rule)[i].offset); + READ_UINT16 (stream, (*rule)[i].GlyphCount); + if ((*rule)[i].GlyphCount == 0) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + READ_UINT16 (stream, (*rule)[i].LookupCount); + if (read_glyph_ids (otf, stream, &(*rule)[i].Input, 0, + (*rule)[i].GlyphCount) < 0) + return errret; + if (read_lookup_record_list (otf, stream, &(*rule)[i].LookupRecord, + (*rule)[i].LookupCount) == 0) + return errret; + } + RESTORE_STREAM (stream, state); + return count; +} + + +static unsigned +read_rule_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_RuleSet **set) +{ + char *errfmt = "List of RuleSet%s"; + unsigned errret = 0; + OTF_StreamState state; + unsigned count; + int i; + READ_UINT16 (stream, count); if (! count) OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); @@ -1069,559 +1331,305 @@ read_chain_class_rule_list (OTF *otf, OTF_Stream *stream, long offset, static unsigned read_chain_class_set_list (OTF *otf, OTF_Stream *stream, long offset, OTF_ChainClassSet **set) -{ - char *errfmt = "ChainClassSet%s"; - unsigned errret = 0; - OTF_StreamState state; - unsigned count; - int i; - - READ_UINT16 (stream, count); - if (! count) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - OTF_MALLOC (*set, count, ""); - for (i = 0; i < count; i++) - /* Offset may be zero. */ - READ_OFFSET (stream, (*set)[i].offset); - SAVE_STREAM (stream, state); - for (i = 0; i < count; i++) - if ((*set)[i].offset) - { - SEEK_STREAM (stream, offset + (*set)[i].offset); - (*set)[i].ChainClassRuleCnt - = read_chain_class_rule_list (otf, stream, offset + (*set)[i].offset, - &(*set)[i].ChainClassRule); - if (! (*set)[i].ChainClassRuleCnt) - return errret; - } - RESTORE_STREAM (stream, state); - return count; -} - - -/* GSUB */ - -static void * -read_gsub_table (OTF *otf, OTF_Stream *stream) -{ - char *errfmt = "GSUB%s"; - void *errret = NULL; - OTF_GSUB *gsub; - - OTF_CALLOC (gsub, 1, ""); - READ_FIXED (stream, gsub->Version); - READ_OFFSET (stream, gsub->ScriptList.offset); - READ_OFFSET (stream, gsub->FeatureList.offset); - READ_OFFSET (stream, gsub->LookupList.offset); - - if (read_script_list (otf, stream, gsub->ScriptList.offset, - &gsub->ScriptList) < 0 - || read_feature_list (otf, stream, gsub->FeatureList.offset, - &gsub->FeatureList) < 0 - || read_lookup_list (otf, stream, gsub->LookupList.offset, - &gsub->LookupList, 1) < 0) - return NULL; - return gsub; -} - -static unsigned -read_sequence (OTF *otf, OTF_Stream *stream, long offset, OTF_Sequence **seq) -{ - char *errfmt = "Sequence%s"; - unsigned errret = 0; - unsigned count; - int i; - - READ_UINT16 (stream, count); - if (! count) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - OTF_MALLOC (*seq, count, ""); - for (i = 0; i < count; i++) - READ_OFFSET (stream, (*seq)[i].offset); - for (i = 0; i < count; i++) - { - SEEK_STREAM (stream, offset + (*seq)[i].offset); - (*seq)[i].GlyphCount = read_glyph_ids (otf, stream, - &(*seq)[i].Substitute, 0, -1); - if (! (*seq)[i].GlyphCount) - return 0; - } - return count; -} - -static int -read_ligature (OTF *otf, OTF_Stream *stream, long offset, - OTF_Ligature **ligature) -{ - char *errfmt = "Ligature%s"; - int errret = -1; - int count; - int i; - - READ_UINT16 (stream, count); - if (! count) - return 0; - OTF_MALLOC (*ligature, count, ""); - for (i = 0; i < count; i++) - READ_OFFSET (stream, (*ligature)[i].offset); - for (i = 0; i < count; i++) - { - SEEK_STREAM (stream, offset + (*ligature)[i].offset); - READ_GLYPHID (stream, (*ligature)[i].LigGlyph); - (*ligature)[i].CompCount - = read_glyph_ids (otf, stream, &(*ligature)[i].Component, -1, -1); - if (! (*ligature)[i].CompCount) - return -1; - } - return count; -} - -static unsigned -read_ligature_set_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_LigatureSet **ligset) -{ - char *errfmt = "LigatureSet%s"; - int errret = 0; - int count; - int i; - - READ_UINT16 (stream, count); - if (! count) - return errret; - OTF_MALLOC (*ligset, count, ""); - for (i = 0; i < count; i++) - READ_OFFSET (stream, (*ligset)[i].offset); - for (i = 0; i < count; i++) - { - int lig_count; - - SEEK_STREAM (stream, offset + (*ligset)[i].offset); - lig_count = read_ligature (otf, stream, offset + (*ligset)[i].offset, - &(*ligset)[i].Ligature); - if (lig_count < 0) - return errret; - (*ligset)[i].LigatureCount = (unsigned) lig_count; - } - return count; -} - -static unsigned -read_alternate_set_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_AlternateSet **altset) -{ - char *errfmt = "AlternateSet%s"; - int errret = -1; +{ + char *errfmt = "ChainClassSet%s"; + unsigned errret = 0; + OTF_StreamState state; unsigned count; int i; READ_UINT16 (stream, count); if (! count) OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - OTF_MALLOC (*altset, count, ""); + OTF_MALLOC (*set, count, ""); for (i = 0; i < count; i++) - READ_OFFSET (stream, (*altset)[i].offset); + /* Offset may be zero. */ + READ_OFFSET (stream, (*set)[i].offset); + SAVE_STREAM (stream, state); for (i = 0; i < count; i++) - { - int alt_count; - - SEEK_STREAM (stream, offset + (*altset)[i].offset); - alt_count = read_glyph_ids (otf, stream, &(*altset)[i].Alternate, 0, -1); - if (alt_count < 0) - return errret; - (*altset)[i].GlyphCount = (unsigned) alt_count; - } + if ((*set)[i].offset) + { + SEEK_STREAM (stream, offset + (*set)[i].offset); + (*set)[i].ChainClassRuleCnt + = read_chain_class_rule_list (otf, stream, offset + (*set)[i].offset, + &(*set)[i].ChainClassRule); + if (! (*set)[i].ChainClassRuleCnt) + return errret; + } + RESTORE_STREAM (stream, state); return count; } -static int -read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset, - unsigned type, OTF_LookupSubTableGSUB *subtable) +static int +read_context1 (OTF *otf, OTF_Stream *stream, long offset, + OTF_Coverage *coverage,OTF_Context1 *context1) { - char errfmt[256]; - int errret = -1; - int count; - - SEEK_STREAM (stream, offset); - READ_UINT16 (stream, subtable->Format); - sprintf (errfmt, "GSUB Lookup %d-%d%%s", type, subtable->Format); - switch (type) - { - case 1: - if (subtable->Format == 1) - { - if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) - return -1; - READ_INT16 (stream, subtable->u.single1.DeltaGlyphID); - } - else if (subtable->Format == 2) - { - if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) - return -1; - subtable->u.single2.GlyphCount - = read_glyph_ids (otf, stream, &subtable->u.single2.Substitute, - 0, -1); - if (! subtable->u.single2.GlyphCount) - return -1; - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); - break; - - case 2: - if (subtable->Format == 1) - { - read_coverage (otf, stream, offset, &subtable->Coverage); - subtable->u.multiple1.SequenceCount - = read_sequence (otf, stream, offset, - &subtable->u.multiple1.Sequence); - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); - break; - - case 3: - if (subtable->Format == 1) - { - if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) - return -1; - subtable->u.alternate1.AlternateSetCount - = read_alternate_set_list (otf, stream, offset, - &subtable->u.alternate1.AlternateSet); - if (! subtable->u.alternate1.AlternateSetCount) - return -1; - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); - break; - - case 4: - if (subtable->Format == 1) - { - if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) - return -1; - subtable->u.ligature1.LigSetCount - = read_ligature_set_list (otf, stream, offset, - &subtable->u.ligature1.LigatureSet); - if (! subtable->u.ligature1.LigSetCount) - return -1; - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); - break; - - case 5: - if (subtable->Format == 1) - { - OTF_GSUB_Context1 *context1 = &subtable->u.context1; - - read_coverage (otf, stream, offset, &subtable->Coverage); - context1->SubRuleSetCount - = read_rule_set_list (otf, stream, offset, &context1->SubRuleSet); - } - else if (subtable->Format == 2) - { - OTF_GSUB_Context2 *context2 = &subtable->u.context2; - - read_coverage (otf, stream, offset, &subtable->Coverage); - read_class_def (otf, stream, offset, &context2->ClassDef); - context2->SubClassSetCnt - = read_class_set_list (otf, stream, offset, &context2->SubClassSet); - } - else if (subtable->Format == 3) - { - OTF_GSUB_Context3 *context3 = &subtable->u.context3; - - READ_USHORT (stream, context3->GlyphCount); - if (context3->GlyphCount < 0) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - READ_USHORT (stream, context3->SubstCount); - if (read_coverage_list (otf, stream, offset, - &context3->Coverage, - context3->GlyphCount) < 0) - return -1; - if (read_lookup_record_list (otf, stream, - &context3->LookupRecord, - context3->SubstCount) < 0) - return -1; - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); - break; - - case 6: - if (subtable->Format == 1) - { - OTF_GSUB_ChainContext1 *chain_context1 = &subtable->u.chain_context1; - - read_coverage (otf, stream, offset, &subtable->Coverage); - chain_context1->ChainSubRuleSetCount - = read_chain_rule_set_list (otf, stream, offset, - &chain_context1->ChainSubRuleSet); - } - else if (subtable->Format == 2) - { - OTF_GSUB_ChainContext2 *chain_context2 = &subtable->u.chain_context2; - - read_coverage (otf, stream, offset, &subtable->Coverage); - read_class_def (otf, stream, offset, &chain_context2->Backtrack); - read_class_def (otf, stream, offset, &chain_context2->Input); - read_class_def (otf, stream, offset, &chain_context2->LookAhead); - chain_context2->ChainSubClassSetCnt - = read_chain_class_set_list (otf, stream, offset, - &chain_context2->ChainSubClassSet); - } - else if (subtable->Format == 3) - { - OTF_GSUB_ChainContext3 *chain_context3 = &subtable->u.chain_context3; - - count = read_coverage_list (otf, stream, offset, - &chain_context3->Backtrack, -1); - if (count < 0) - return -1; - chain_context3->BacktrackGlyphCount = (unsigned) count; - count = read_coverage_list (otf, stream, offset, - &chain_context3->Input, -1); - if (count <= 0) - return -1; - chain_context3->InputGlyphCount = (unsigned) count; - subtable->Coverage = chain_context3->Input[0]; - count = read_coverage_list (otf, stream, offset, - &chain_context3->LookAhead, -1); - chain_context3->LookaheadGlyphCount = (unsigned) count; - chain_context3->SubstCount - = read_lookup_record_list (otf, stream, - &chain_context3->LookupRecord, -1); - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); - break; - - case 7: - case 8: - OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); - break; - - default: - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)"); - } + if (read_coverage (otf, stream, offset, coverage) < 0) + return -1; + context1->RuleSetCount + = read_rule_set_list (otf, stream, offset, &context1->RuleSet); + if (! context1->RuleSetCount) + return -1; return 0; } - -/* GPOS */ +static int +read_context2 (OTF *otf, OTF_Stream *stream, long offset, + OTF_Coverage *coverage,OTF_Context2 *context2) +{ + if (read_coverage (otf, stream, offset, coverage) < 0 + || read_class_def (otf, stream, offset, &context2->ClassDef) < 0) + return -1; + context2->ClassSetCnt + = read_class_set_list (otf, stream, offset, &context2->ClassSet); + if (! context2->ClassSetCnt) + return -1; + return 0; +} static int -read_value_record (OTF *otf, OTF_Stream *stream, long offset, - enum OTF_ValueFormat bit, OTF_ValueRecord *value_record) +read_context3 (OTF *otf, OTF_Stream *stream, long offset, + OTF_Coverage *coverage,OTF_Context3 *context3) { + char *errfmt = "Context1%s"; int errret = -1; - OTF_StreamState state; - int size, i; - - if (! bit) - return 0; - for (i = 0, size = 0; i < 8; i++) - if (bit & (1 << i)) - size += 2; - if (bit & OTF_XPlacement) - READ_INT16 (stream, value_record->XPlacement); - if (bit & OTF_XPlacement) - READ_INT16 (stream, value_record->YPlacement); - if (bit & OTF_XAdvance) - READ_INT16 (stream, value_record->XAdvance); - if (bit & OTF_YAdvance) - READ_INT16 (stream, value_record->YAdvance); - if (bit & OTF_XPlaDevice) - READ_OFFSET (stream, value_record->XPlaDevice.offset); - if (bit & OTF_YPlaDevice) - READ_OFFSET (stream, value_record->YPlaDevice.offset); - if (bit & OTF_XAdvDevice) - READ_OFFSET (stream, value_record->XAdvDevice.offset); - if (bit & OTF_YAdvDevice) - READ_OFFSET (stream, value_record->YAdvDevice.offset); - SAVE_STREAM (stream, state); - if (value_record->XPlaDevice.offset) - { - if (read_device_table (otf, stream, offset, &value_record->XPlaDevice) < 0) - return -1; - } - if (value_record->YPlaDevice.offset) - { - if (read_device_table (otf, stream, offset, &value_record->YPlaDevice) < 0) - return -1; - } - if (value_record->XAdvDevice.offset) - { - if (read_device_table (otf, stream, offset, &value_record->XAdvDevice) < 0) - return -1; - } - if (value_record->YAdvDevice.offset) - { - if (read_device_table (otf, stream, offset, &value_record->YAdvDevice) < 0) - return -1; - } - RESTORE_STREAM (stream, state); + READ_USHORT (stream, context3->GlyphCount); + if (context3->GlyphCount < 0) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + READ_USHORT (stream, context3->LookupCount); + if (read_coverage_list (otf, stream, offset, &context3->Coverage, + context3->GlyphCount) < 0) + return errret; + if (read_lookup_record_list (otf, stream, &context3->LookupRecord, + context3->LookupCount) < 0) + return errret; return 0; } +static int +read_chain_context1 (OTF *otf, OTF_Stream *stream, long offset, + OTF_Coverage *coverage, OTF_ChainContext1 *chain_context1) +{ + if (read_coverage (otf, stream, offset, coverage) < 0) + return -1; + chain_context1->ChainRuleSetCount + = read_chain_rule_set_list (otf, stream, offset, + &chain_context1->ChainRuleSet); + if (! chain_context1->ChainRuleSetCount) + return -1; + return 0; +} static int -read_anchor (OTF *otf, OTF_Stream *stream, long offset, OTF_Anchor *anchor) +read_chain_context2 (OTF *otf, OTF_Stream *stream, long offset, + OTF_Coverage *coverage, OTF_ChainContext2 *chain_context2) { - char *errfmt = "Anchor%s"; - int errret = -1; + if (read_coverage (otf, stream, offset, coverage) < 0 + || read_class_def (otf, stream, offset, + &chain_context2->BacktrackClassDef) < 0 + || read_class_def (otf, stream, offset, + &chain_context2->InputClassDef) < 0 + || read_class_def (otf, stream, offset, + &chain_context2->LookaheadClassDef) < 0) + return -1; + chain_context2->ChainClassSetCnt + = read_chain_class_set_list (otf, stream, offset, + &chain_context2->ChainClassSet); + if (! chain_context2->ChainClassSetCnt) + return -1; + return 0; +} - SEEK_STREAM (stream, offset + anchor->offset); - READ_UINT16 (stream, anchor->AnchorFormat); - READ_INT16 (stream, anchor->XCoordinate); - READ_INT16 (stream, anchor->YCoordinate); - if (anchor->AnchorFormat == 1) - ; - else if (anchor->AnchorFormat == 2) - { - READ_UINT16 (stream, anchor->f.f1.AnchorPoint); - } - else if (anchor->AnchorFormat == 3) - { - READ_OFFSET (stream, anchor->f.f2.XDeviceTable.offset); - READ_OFFSET (stream, anchor->f.f2.YDeviceTable.offset); - if (anchor->f.f2.XDeviceTable.offset) - { - if (read_device_table (otf, stream, offset + anchor->offset, - &anchor->f.f2.XDeviceTable) < 0) - return -1; - } - if (anchor->f.f2.YDeviceTable.offset) - { - if (read_device_table (otf, stream, offset + anchor->offset, - &anchor->f.f2.YDeviceTable) < 0) - return -1; - } - } - else - OTF_ERROR (OTF_ERROR_TABLE, " (invalid format)"); +static int +read_chain_context3 (OTF *otf, OTF_Stream *stream, long offset, + OTF_Coverage *coverage, OTF_ChainContext3 *chain_context3) +{ + int count; + count = read_coverage_list (otf, stream, offset, + &chain_context3->Backtrack, -1); + if (count < 0) + return -1; + chain_context3->BacktrackGlyphCount = (unsigned) count; + count = read_coverage_list (otf, stream, offset, + &chain_context3->Input, -1); + if (count <= 0) + return -1; + chain_context3->InputGlyphCount = (unsigned) count; + *coverage = chain_context3->Input[0]; + count = read_coverage_list (otf, stream, offset, + &chain_context3->LookAhead, -1); + chain_context3->LookaheadGlyphCount = (unsigned) count; + chain_context3->LookupCount + = read_lookup_record_list (otf, stream, + &chain_context3->LookupRecord, -1); return 0; } -static int -read_mark_array (OTF *otf, OTF_Stream *stream, long offset, - OTF_MarkArray *array) +static void * +read_gsub_gpos_table (OTF *otf, OTF_Stream *stream, int gsubp) { - char *errfmt = "MarkArray%s"; - int errret = -1; - OTF_StreamState state; + char *errfmt = gsubp ? "GSUB%s" : "GPOS%s"; + void *errret = NULL; + OTF_GSUB_GPOS *gsub_gpos; + + OTF_CALLOC (gsub_gpos, 1, ""); + READ_FIXED (stream, gsub_gpos->Version); + READ_OFFSET (stream, gsub_gpos->ScriptList.offset); + READ_OFFSET (stream, gsub_gpos->FeatureList.offset); + READ_OFFSET (stream, gsub_gpos->LookupList.offset); + + if (read_script_list (otf, stream, gsub_gpos->ScriptList.offset, + &gsub_gpos->ScriptList) < 0 + || read_feature_list (otf, stream, gsub_gpos->FeatureList.offset, + &gsub_gpos->FeatureList) < 0 + || read_lookup_list (otf, stream, gsub_gpos->LookupList.offset, + &gsub_gpos->LookupList, gsubp) < 0) + return NULL; + return gsub_gpos; +} + + +/* (1-9) "GSUB" table */ + +static unsigned +read_sequence (OTF *otf, OTF_Stream *stream, long offset, OTF_Sequence **seq) +{ + char *errfmt = "Sequence%s"; + unsigned errret = 0; + unsigned count; int i; - - READ_OFFSET (stream, array->offset); - SAVE_STREAM (stream, state); - SEEK_STREAM (stream, offset + array->offset); - READ_UINT16 (stream, array->MarkCount); - OTF_MALLOC (array->MarkRecord, array->MarkCount, ""); - for (i = 0; i < array->MarkCount; i++) + + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*seq, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*seq)[i].offset); + for (i = 0; i < count; i++) { - READ_UINT16 (stream, array->MarkRecord[i].Class); - READ_OFFSET (stream, array->MarkRecord[i].MarkAnchor.offset); + SEEK_STREAM (stream, offset + (*seq)[i].offset); + (*seq)[i].GlyphCount = read_glyph_ids (otf, stream, + &(*seq)[i].Substitute, 0, -1); + if (! (*seq)[i].GlyphCount) + return 0; } - for (i = 0; i < array->MarkCount; i++) - if (read_anchor (otf, stream, offset + array->offset, - &array->MarkRecord[i].MarkAnchor) < 0) - return -1;; - RESTORE_STREAM (stream, state); - return 0; + return count; } static int -read_anchor_array (OTF *otf, OTF_Stream *stream, long offset, - unsigned ClassCount, OTF_AnchorArray *array) +read_ligature (OTF *otf, OTF_Stream *stream, long offset, + OTF_Ligature **ligature) { - char *errfmt = "AnchorArray%s"; + char *errfmt = "Ligature%s"; int errret = -1; - OTF_StreamState state; - int i, j; - - READ_OFFSET (stream, array->offset); - SAVE_STREAM (stream, state); - SEEK_STREAM (stream, offset + array->offset); - READ_UINT16 (stream, array->Count); - OTF_MALLOC (array->AnchorRecord, array->Count, ""); - for (i = 0; i < array->Count; i++) + int count; + int i; + + READ_UINT16 (stream, count); + if (! count) + return 0; + OTF_MALLOC (*ligature, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*ligature)[i].offset); + for (i = 0; i < count; i++) { - OTF_MALLOC (array->AnchorRecord[i].Anchor, ClassCount, - " (AnchorRecord)"); - for (j = 0; j < ClassCount; j++) - READ_OFFSET (stream, array->AnchorRecord[i].Anchor[j].offset); - } - for (i = 0; i < array->Count; i++) - for (j = 0; j < ClassCount; j++) - if (read_anchor (otf, stream, offset + array->offset, - &array->AnchorRecord[i].Anchor[j]) < 0) + SEEK_STREAM (stream, offset + (*ligature)[i].offset); + READ_GLYPHID (stream, (*ligature)[i].LigGlyph); + (*ligature)[i].CompCount + = read_glyph_ids (otf, stream, &(*ligature)[i].Component, -1, -1); + if (! (*ligature)[i].CompCount) return -1; - RESTORE_STREAM (stream, state); - return 0; + } + return count; } +static unsigned +read_ligature_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_LigatureSet **ligset) +{ + char *errfmt = "LigatureSet%s"; + int errret = 0; + int count; + int i; -static OTF_Class1Record * -read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset, - unsigned num1, enum OTF_ValueFormat bit1, - unsigned num2, enum OTF_ValueFormat bit2) + READ_UINT16 (stream, count); + if (! count) + return errret; + OTF_MALLOC (*ligset, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*ligset)[i].offset); + for (i = 0; i < count; i++) + { + int lig_count; + + SEEK_STREAM (stream, offset + (*ligset)[i].offset); + lig_count = read_ligature (otf, stream, offset + (*ligset)[i].offset, + &(*ligset)[i].Ligature); + if (lig_count < 0) + return errret; + (*ligset)[i].LigatureCount = (unsigned) lig_count; + } + return count; +} + +static unsigned +read_alternate_set_list (OTF *otf, OTF_Stream *stream, long offset, + OTF_AlternateSet **altset) { - char *errfmt = "Class1Record%s"; - void *errret = NULL; - OTF_Class1Record *rec; - int i, j; + char *errfmt = "AlternateSet%s"; + int errret = -1; + unsigned count; + int i; - OTF_MALLOC (rec, num1, ""); - for (i = 0; i < num1; i++) + READ_UINT16 (stream, count); + if (! count) + OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); + OTF_MALLOC (*altset, count, ""); + for (i = 0; i < count; i++) + READ_OFFSET (stream, (*altset)[i].offset); + for (i = 0; i < count; i++) { - OTF_CALLOC (rec[i].Class2Record, num2, " (Class2Record)"); - for (j = 0; j < num2; j++) - { - if (read_value_record (otf, stream, offset, - bit1, &rec[i].Class2Record[j].Value1) < 0 - || read_value_record (otf, stream, offset, - bit2, &rec[i].Class2Record[j].Value2) < 0) - return NULL; - } + int alt_count; + + SEEK_STREAM (stream, offset + (*altset)[i].offset); + alt_count = read_glyph_ids (otf, stream, &(*altset)[i].Alternate, 0, -1); + if (alt_count < 0) + return errret; + (*altset)[i].GlyphCount = (unsigned) alt_count; } - return rec; + return count; } static int -read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, - long offset, unsigned type, - OTF_LookupSubTableGPOS *subtable) +read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset, + unsigned type, OTF_LookupSubTableGSUB *subtable) { char errfmt[256]; int errret = -1; - int count; SEEK_STREAM (stream, offset); READ_UINT16 (stream, subtable->Format); - sprintf (errfmt, "GPOS Lookup %d-%d%%s", type, subtable->Format); + sprintf (errfmt, "GSUB Lookup %d-%d%%s", type, subtable->Format); switch (type) { case 1: if (subtable->Format == 1) { - READ_UINT16 (stream, subtable->u.single1.ValueFormat); - read_value_record (otf, stream, offset, - subtable->u.single1.ValueFormat, - &subtable->u.single1.Value); + if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) + return -1; + READ_INT16 (stream, subtable->u.single1.DeltaGlyphID); } else if (subtable->Format == 2) { - OTF_GPOS_Single2 *single2 = &subtable->u.single2; - int i; - - READ_UINT16 (stream, single2->ValueFormat); - READ_UINT16 (stream, single2->ValueCount); - OTF_CALLOC (single2->Value, single2->ValueCount," (ValueRecord)"); - for (i = 0; i < single2->ValueCount; i++) - read_value_record (otf, stream, offset, single2->ValueFormat, - single2->Value + i); + if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) + return -1; + subtable->u.single2.GlyphCount + = read_glyph_ids (otf, stream, &subtable->u.single2.Substitute, + 0, -1); + if (! subtable->u.single2.GlyphCount) + return -1; } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); @@ -1630,163 +1638,94 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, case 2: if (subtable->Format == 1) { - OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); - } - else if (subtable->Format == 2) - { - SEEK_STREAM (stream, offset + 2); read_coverage (otf, stream, offset, &subtable->Coverage); - READ_UINT16 (stream, subtable->u.pair2.ValueFormat1); - READ_UINT16 (stream, subtable->u.pair2.ValueFormat2); - read_class_def (otf, stream, offset, - &subtable->u.pair2.ClassDef1); - read_class_def (otf, stream, offset, - &subtable->u.pair2.ClassDef2); - READ_UINT16 (stream, subtable->u.pair2.Class1Count); - READ_UINT16 (stream, subtable->u.pair2.Class2Count); - subtable->u.pair2.Class1Record - = read_class1_record_list (otf, stream, offset, - subtable->u.pair2.Class1Count, - subtable->u.pair2.ValueFormat1, - subtable->u.pair2.Class2Count, - subtable->u.pair2.ValueFormat2); + subtable->u.multiple1.SequenceCount + = read_sequence (otf, stream, offset, + &subtable->u.multiple1.Sequence); } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; case 3: - OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); - break; - - case 4: if (subtable->Format == 1) { - read_coverage (otf, stream, offset, &subtable->Coverage); - read_coverage (otf, stream, offset, - &subtable->u.mark_base1.BaseCoverage); - READ_UINT16 (stream, subtable->u.mark_base1.ClassCount); - read_mark_array (otf, stream, offset, - &subtable->u.mark_base1.MarkArray); - read_anchor_array (otf, stream, offset, - subtable->u.mark_base1.ClassCount, - &subtable->u.mark_base1.BaseArray); + if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) + return -1; + subtable->u.alternate1.AlternateSetCount + = read_alternate_set_list (otf, stream, offset, + &subtable->u.alternate1.AlternateSet); + if (! subtable->u.alternate1.AlternateSetCount) + return -1; } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; - case 5: - OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); - break; - - case 6: + case 4: if (subtable->Format == 1) - { - read_coverage (otf, stream, offset, &subtable->Coverage); - read_coverage (otf, stream, offset, - &subtable->u.mark_mark1.Mark2Coverage); - READ_UINT16 (stream, subtable->u.mark_base1.ClassCount); - read_mark_array (otf, stream, offset, - &subtable->u.mark_mark1.Mark1Array); - read_anchor_array (otf, stream, offset, - subtable->u.mark_mark1.ClassCount, - &subtable->u.mark_mark1.Mark2Array); + { + if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0) + return -1; + subtable->u.ligature1.LigSetCount + = read_ligature_set_list (otf, stream, offset, + &subtable->u.ligature1.LigatureSet); + if (! subtable->u.ligature1.LigSetCount) + return -1; } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; - case 7: + case 5: if (subtable->Format == 1) { - OTF_GPOS_Context1 *context1 = &subtable->u.context1; - - read_coverage (otf, stream, offset, &subtable->Coverage); - context1->PosRuleSetCount - = read_rule_set_list (otf, stream, offset, &context1->PosRuleSet); + if (read_context1 (otf, stream, offset, &subtable->Coverage, + &subtable->u.context1) < 0) + return errret; } else if (subtable->Format == 2) { - OTF_GPOS_Context2 *context2 = &subtable->u.context2; - - read_coverage (otf, stream, offset, &subtable->Coverage); - read_class_def (otf, stream, offset, &context2->ClassDef); - context2->PosClassSetCnt - = read_class_set_list (otf, stream, offset, &context2->PosClassSet); - + if (read_context2 (otf, stream, offset, &subtable->Coverage, + &subtable->u.context2) < 0) + return errret; } else if (subtable->Format == 3) { - OTF_GPOS_Context3 *context3 = &subtable->u.context3; - - READ_USHORT (stream, context3->GlyphCount); - if (context3->GlyphCount < 0) - OTF_ERROR (OTF_ERROR_TABLE, " (zero count)"); - READ_USHORT (stream, context3->PosCount); - if (read_coverage_list (otf, stream, offset, - &context3->Coverage, - context3->GlyphCount) < 0) - return -1; - if (read_lookup_record_list (otf, stream, - &context3->LookupRecord, - context3->PosCount) < 0) - return -1; + if (read_context3 (otf, stream, offset, &subtable->Coverage, + &subtable->u.context3) < 0) + return errret; } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; - - case 8: + + case 6: if (subtable->Format == 1) { - OTF_GPOS_ChainContext1 *chain_context1 = &subtable->u.chain_context1; - - read_coverage (otf, stream, offset, &subtable->Coverage); - chain_context1->ChainPosRuleSetCount - = read_chain_rule_set_list (otf, stream, offset, - &chain_context1->ChainPosRuleSet); + if (read_chain_context1 (otf, stream, offset, &subtable->Coverage, + &subtable->u.chain_context1) < 0) + return errret; } else if (subtable->Format == 2) { - OTF_GPOS_ChainContext2 *chain_context2 = &subtable->u.chain_context2; - - read_coverage (otf, stream, offset, &subtable->Coverage); - read_class_def (otf, stream, offset, &chain_context2->Backtrack); - read_class_def (otf, stream, offset, &chain_context2->Input); - read_class_def (otf, stream, offset, &chain_context2->LookAhead); - chain_context2->ChainPosClassSetCnt - = read_chain_class_set_list (otf, stream, offset, - &chain_context2->ChainPosClassSet); + if (read_chain_context2 (otf, stream, offset, &subtable->Coverage, + &subtable->u.chain_context2) < 0) + return errret; } else if (subtable->Format == 3) { - OTF_GPOS_ChainContext3 *chain_context3 = &subtable->u.chain_context3; - - count = read_coverage_list (otf, stream, offset, - &chain_context3->Backtrack, -1); - if (count < 0) - return -1; - chain_context3->BacktrackGlyphCount = (unsigned) count; - count = read_coverage_list (otf, stream, offset, - &chain_context3->Input, -1); - if (count <= 0) - return -1; - chain_context3->InputGlyphCount = (unsigned) count; - subtable->Coverage = chain_context3->Input[0]; - count = read_coverage_list (otf, stream, offset, - &chain_context3->LookAhead, -1); - chain_context3->LookaheadGlyphCount = (unsigned) count; - chain_context3->PosCount - = read_lookup_record_list (otf, stream, - &chain_context3->LookupRecord, -1); + if (read_chain_context3 (otf, stream, offset, &subtable->Coverage, + &subtable->u.chain_context3) < 0) + return errret; } else OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); break; - - case 9: - OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + + case 7: + case 8: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); break; default: @@ -1795,416 +1734,517 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, return 0; } - static void * -read_gpos_table (OTF *otf, OTF_Stream *stream) -{ - char *errfmt = "GPOS%s"; - void *errret = NULL; - OTF_GPOS *gpos; - - OTF_CALLOC (gpos, 1, ""); - READ_FIXED (stream, gpos->Version); - READ_OFFSET (stream, gpos->ScriptList.offset); - READ_OFFSET (stream, gpos->FeatureList.offset); - READ_OFFSET (stream, gpos->LookupList.offset); - - if (read_script_list (otf, stream, gpos->ScriptList.offset, - &gpos->ScriptList) < 0 - || read_feature_list (otf, stream, gpos->FeatureList.offset, - &gpos->FeatureList) < 0 - || read_lookup_list (otf, stream, gpos->LookupList.offset, - &gpos->LookupList, 0) < 0) - return NULL; - return gpos; -} - - -#if 0 -/* BASE */ - -static OTF_BASE * -read_base_table (OTF_Stream *stream, long offset) +read_gsub_table (OTF *otf, OTF_Stream *stream) { - OTF_BASE *base; - - OTF_MALLOC (base, 1); - - return base; + return read_gsub_gpos_table (otf, stream, 1); } -/* JSTF */ - -static OTF_JSTF * -read_jstf_table (OTF_Stream *stream, long offset) -{ - OTF_JSTF *jstf; - - OTF_MALLOC (jstf, 1); +/* (1-10) "GPOS" table */ - return jstf; -} -#endif /* 0 */ - -/* GDEF */ static int -read_attach_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_AttachList *list) +read_value_record (OTF *otf, OTF_Stream *stream, long offset, + enum OTF_ValueFormat bit, OTF_ValueRecord *value_record) { - char *errfmt = "AttachList%s"; int errret = -1; - int i, j; + OTF_StreamState state; + int size, i; - if (read_coverage (otf, stream, offset, &list->Coverage) < 0) - return -1; - READ_UINT16 (stream, list->GlyphCount); - OTF_MALLOC (list->AttachPoint, list->GlyphCount, ""); - for (i = 0; i < list->GlyphCount; i++) - READ_OFFSET (stream, list->AttachPoint[i].offset); - for (i = 0; i < list->GlyphCount; i++) - { - int count; + if (! bit) + return 0; + for (i = 0, size = 0; i < 8; i++) + if (bit & (1 << i)) + size += 2; - SEEK_STREAM (stream, offset + list->AttachPoint[i].offset); - READ_UINT16 (stream, count); - list->AttachPoint[i].PointCount = count; - OTF_MALLOC (list->AttachPoint[i].PointIndex, count, " (PointIndex)"); - for (j = 0; j < count; j++) - READ_UINT16 (stream, list->AttachPoint[i].PointIndex[j]); + if (bit & OTF_XPlacement) + READ_INT16 (stream, value_record->XPlacement); + if (bit & OTF_XPlacement) + READ_INT16 (stream, value_record->YPlacement); + if (bit & OTF_XAdvance) + READ_INT16 (stream, value_record->XAdvance); + if (bit & OTF_YAdvance) + READ_INT16 (stream, value_record->YAdvance); + if (bit & OTF_XPlaDevice) + READ_OFFSET (stream, value_record->XPlaDevice.offset); + if (bit & OTF_YPlaDevice) + READ_OFFSET (stream, value_record->YPlaDevice.offset); + if (bit & OTF_XAdvDevice) + READ_OFFSET (stream, value_record->XAdvDevice.offset); + if (bit & OTF_YAdvDevice) + READ_OFFSET (stream, value_record->YAdvDevice.offset); + SAVE_STREAM (stream, state); + if (value_record->XPlaDevice.offset) + { + if (read_device_table (otf, stream, offset, &value_record->XPlaDevice) < 0) + return -1; + } + if (value_record->YPlaDevice.offset) + { + if (read_device_table (otf, stream, offset, &value_record->YPlaDevice) < 0) + return -1; + } + if (value_record->XAdvDevice.offset) + { + if (read_device_table (otf, stream, offset, &value_record->XAdvDevice) < 0) + return -1; + } + if (value_record->YAdvDevice.offset) + { + if (read_device_table (otf, stream, offset, &value_record->YAdvDevice) < 0) + return -1; } + RESTORE_STREAM (stream, state); return 0; } + static int -read_caret_value (OTF *otf, OTF_Stream *stream, long offset, - OTF_CaretValue *caret) +read_anchor (OTF *otf, OTF_Stream *stream, long offset, OTF_Anchor *anchor) { - char *errfmt = "CaretValue%s"; + char *errfmt = "Anchor%s"; int errret = -1; - SEEK_STREAM (stream, offset + caret->offset); - READ_UINT16 (stream, caret->CaretValueFormat); - if (caret->CaretValueFormat == 1) - READ_INT16 (stream, caret->f.f1.Coordinate); - else if (caret->CaretValueFormat == 2) - READ_UINT16 (stream, caret->f.f2.CaretValuePoint); - else if (caret->CaretValueFormat == 3) + SEEK_STREAM (stream, offset + anchor->offset); + READ_UINT16 (stream, anchor->AnchorFormat); + READ_INT16 (stream, anchor->XCoordinate); + READ_INT16 (stream, anchor->YCoordinate); + if (anchor->AnchorFormat == 1) + ; + else if (anchor->AnchorFormat == 2) { - READ_INT16 (stream, caret->f.f3.Coordinate); - if (read_device_table (otf, stream, offset + caret->offset, - &caret->f.f3.DeviceTable) < 0) - return -1; + READ_UINT16 (stream, anchor->f.f1.AnchorPoint); + } + else if (anchor->AnchorFormat == 3) + { + READ_OFFSET (stream, anchor->f.f2.XDeviceTable.offset); + READ_OFFSET (stream, anchor->f.f2.YDeviceTable.offset); + if (anchor->f.f2.XDeviceTable.offset) + { + if (read_device_table (otf, stream, offset + anchor->offset, + &anchor->f.f2.XDeviceTable) < 0) + return -1; + } + if (anchor->f.f2.YDeviceTable.offset) + { + if (read_device_table (otf, stream, offset + anchor->offset, + &anchor->f.f2.YDeviceTable) < 0) + return -1; + } } else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid format)"); + OTF_ERROR (OTF_ERROR_TABLE, " (invalid format)"); + return 0; } static int -read_lig_caret_list (OTF *otf, OTF_Stream *stream, long offset, - OTF_LigCaretList *list) +read_mark_array (OTF *otf, OTF_Stream *stream, long offset, + OTF_MarkArray *array) { - char *errfmt = "LigCaretList%s"; + char *errfmt = "MarkArray%s"; int errret = -1; - int i, j; - - if (read_coverage (otf, stream, offset, &list->Coverage) < 0) - return -1; - READ_UINT16 (stream, list->LigGlyphCount); - OTF_MALLOC (list->LigGlyph, list->LigGlyphCount, ""); - for (i = 0; i < list->LigGlyphCount; i++) - READ_OFFSET (stream, list->LigGlyph[i].offset); - for (i = 0; i < list->LigGlyphCount; i++) + OTF_StreamState state; + int i; + + READ_OFFSET (stream, array->offset); + SAVE_STREAM (stream, state); + SEEK_STREAM (stream, offset + array->offset); + READ_UINT16 (stream, array->MarkCount); + OTF_MALLOC (array->MarkRecord, array->MarkCount, ""); + for (i = 0; i < array->MarkCount; i++) { - int count; - - SEEK_STREAM (stream, offset + list->LigGlyph[i].offset); - READ_UINT16 (stream, count); - list->LigGlyph[i].CaretCount = count; - OTF_MALLOC (list->LigGlyph[i].CaretValue, count, " (CaretValue)"); - for (j = 0; j < count; j++) - READ_OFFSET (stream, list->LigGlyph[i].CaretValue[j].offset); - for (j = 0; j < count; j++) - if (read_caret_value (otf, stream, offset + list->LigGlyph[i].offset, - &list->LigGlyph[i].CaretValue[j]) < 0) - return -1; + READ_UINT16 (stream, array->MarkRecord[i].Class); + READ_OFFSET (stream, array->MarkRecord[i].MarkAnchor.offset); } + for (i = 0; i < array->MarkCount; i++) + if (read_anchor (otf, stream, offset + array->offset, + &array->MarkRecord[i].MarkAnchor) < 0) + return -1;; + RESTORE_STREAM (stream, state); return 0; } static int -read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header) +read_anchor_array (OTF *otf, OTF_Stream *stream, long offset, + unsigned ClassCount, OTF_AnchorArray *array) { + char *errfmt = "AnchorArray%s"; int errret = -1; - - READ_FIXED (stream, header->Version); - READ_OFFSET (stream, header->GlyphClassDef); - READ_OFFSET (stream, header->AttachList); - READ_OFFSET (stream, header->LigCaretList); - READ_OFFSET (stream, header->MarkAttachClassDef); + OTF_StreamState state; + int i, j; + + READ_OFFSET (stream, array->offset); + SAVE_STREAM (stream, state); + SEEK_STREAM (stream, offset + array->offset); + READ_UINT16 (stream, array->Count); + OTF_MALLOC (array->AnchorRecord, array->Count, ""); + for (i = 0; i < array->Count; i++) + { + OTF_MALLOC (array->AnchorRecord[i].Anchor, ClassCount, + " (AnchorRecord)"); + for (j = 0; j < ClassCount; j++) + READ_OFFSET (stream, array->AnchorRecord[i].Anchor[j].offset); + } + for (i = 0; i < array->Count; i++) + for (j = 0; j < ClassCount; j++) + if (read_anchor (otf, stream, offset + array->offset, + &array->AnchorRecord[i].Anchor[j]) < 0) + return -1; + RESTORE_STREAM (stream, state); return 0; } -static void * -read_gdef_table (OTF *otf, OTF_Stream *stream) + +static OTF_Class1Record * +read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset, + unsigned num1, enum OTF_ValueFormat bit1, + unsigned num2, enum OTF_ValueFormat bit2) { - char *errfmt = "GDEF%s"; + char *errfmt = "Class1Record%s"; void *errret = NULL; - OTF_GDEF *gdef; + OTF_Class1Record *rec; + int i, j; - OTF_CALLOC (gdef, 1, ""); - read_gdef_header (stream, (OTF_GDEFHeader *) &gdef->header); - if (gdef->header.GlyphClassDef) - { - gdef->glyph_class_def.offset = gdef->header.GlyphClassDef; - read_class_def_without_offset (otf, stream, &gdef->glyph_class_def); - } - if (gdef->header.AttachList) - read_attach_list (otf, stream, gdef->header.AttachList, - &gdef->attach_list); - if (gdef->header.LigCaretList) - read_lig_caret_list (otf, stream, gdef->header.LigCaretList, - &gdef->lig_caret_list); - if (gdef->header.MarkAttachClassDef) + OTF_MALLOC (rec, num1, ""); + for (i = 0; i < num1; i++) { - gdef->mark_attach_class_def.offset = gdef->header.MarkAttachClassDef; - read_class_def_without_offset (otf, stream, &gdef->mark_attach_class_def); + OTF_CALLOC (rec[i].Class2Record, num2, " (Class2Record)"); + for (j = 0; j < num2; j++) + { + if (read_value_record (otf, stream, offset, + bit1, &rec[i].Class2Record[j].Value1) < 0 + || read_value_record (otf, stream, offset, + bit2, &rec[i].Class2Record[j].Value2) < 0) + return NULL; + } } - - return gdef; + return rec; } - - -/* cmap */ - -static void * -read_cmap_table (OTF *otf, OTF_Stream *stream) +static int +read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, + long offset, unsigned type, + OTF_LookupSubTableGPOS *subtable) { - char *errfmt = "cmap%s"; - void *errret = NULL; - OTF_cmap *cmap; - int i; + char errfmt[256]; + int errret = -1; - OTF_CALLOC (cmap, 1, ""); - READ_USHORT (stream, cmap->version); - READ_USHORT (stream, cmap->numTables); - OTF_MALLOC (cmap->EncodingRecord, cmap->numTables, ""); - for (i = 0; i < cmap->numTables; i++) - { - READ_USHORT (stream, cmap->EncodingRecord[i].platformID); - READ_USHORT (stream, cmap->EncodingRecord[i].encodingID); - READ_ULONG (stream, cmap->EncodingRecord[i].offset); - if (cmap->EncodingRecord[i].platformID == 3 - && cmap->EncodingRecord[i].encodingID == 1) - cmap->Unicode = cmap->EncodingRecord + i; - } - for (i = 0; i < cmap->numTables; i++) + SEEK_STREAM (stream, offset); + READ_UINT16 (stream, subtable->Format); + sprintf (errfmt, "GPOS Lookup %d-%d%%s", type, subtable->Format); + switch (type) { - unsigned format; - - SEEK_STREAM (stream, cmap->EncodingRecord[i].offset); - READ_USHORT (stream, format); - cmap->EncodingRecord[i].subtable.format = format; - READ_USHORT (stream, cmap->EncodingRecord[i].subtable.length); - if (format == 8 || format == 10 || format == 12) + case 1: + if (subtable->Format == 1) { - READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length); - READ_ULONG (stream, cmap->EncodingRecord[i].subtable.language); + READ_UINT16 (stream, subtable->u.single1.ValueFormat); + read_value_record (otf, stream, offset, + subtable->u.single1.ValueFormat, + &subtable->u.single1.Value); + } + else if (subtable->Format == 2) + { + OTF_GPOS_Single2 *single2 = &subtable->u.single2; + int i; + + READ_UINT16 (stream, single2->ValueFormat); + READ_UINT16 (stream, single2->ValueCount); + OTF_CALLOC (single2->Value, single2->ValueCount," (ValueRecord)"); + for (i = 0; i < single2->ValueCount; i++) + read_value_record (otf, stream, offset, single2->ValueFormat, + single2->Value + i); } else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + + case 2: + if (subtable->Format == 1) { - READ_USHORT (stream, cmap->EncodingRecord[i].subtable.language); + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); } - switch (format) + else if (subtable->Format == 2) { - case 0: - { - OTF_MALLOC (cmap->EncodingRecord[i].subtable.f.f0, 1, - " (EncodingRecord)"); - READ_BYTES (stream, - cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray, - 256); - } - break; - - case 2: - break; - - case 4: - { - OTF_EncodingSubtable4 *sub4; - int segCount; - int j; - unsigned dummy; - - OTF_MALLOC (sub4, 1, " (EncodingSubtable4)"); - cmap->EncodingRecord[i].subtable.f.f4 = sub4; - READ_USHORT (stream, sub4->segCountX2); - segCount = sub4->segCountX2 / 2; - READ_USHORT (stream, sub4->searchRange); - READ_USHORT (stream, sub4->entrySelector); - READ_USHORT (stream, sub4->rangeShift); - OTF_MALLOC (sub4->segments, segCount, " (segCount)"); - for (j = 0; j < segCount; j++) - READ_USHORT (stream, sub4->segments[j].endCount); - READ_USHORT (stream, dummy); - for (j = 0; j < segCount; j++) - READ_USHORT (stream, sub4->segments[j].startCount); - for (j = 0; j < segCount; j++) - READ_SHORT (stream, sub4->segments[j].idDelta); - for (j = 0; j < segCount; j++) - { - unsigned off; - unsigned rest = 2 * (segCount - j); - - READ_USHORT (stream, off); - if (off == 0) - sub4->segments[j].idRangeOffset = 0xFFFF; - else - sub4->segments[j].idRangeOffset = (off - rest) / 2; - } - j = (cmap->EncodingRecord[i].subtable.length - - (14 + 2 * (segCount * 4 + 1))); - sub4->GlyphCount = j / 2; - OTF_MALLOC (sub4->glyphIdArray, sub4->GlyphCount, " (GlyphCount)"); - for (j = 0; j < sub4->GlyphCount; j++) - READ_USHORT (stream, sub4->glyphIdArray[j]); - } + SEEK_STREAM (stream, offset + 2); + read_coverage (otf, stream, offset, &subtable->Coverage); + READ_UINT16 (stream, subtable->u.pair2.ValueFormat1); + READ_UINT16 (stream, subtable->u.pair2.ValueFormat2); + read_class_def (otf, stream, offset, + &subtable->u.pair2.ClassDef1); + read_class_def (otf, stream, offset, + &subtable->u.pair2.ClassDef2); + READ_UINT16 (stream, subtable->u.pair2.Class1Count); + READ_UINT16 (stream, subtable->u.pair2.Class2Count); + subtable->u.pair2.Class1Record + = read_class1_record_list (otf, stream, offset, + subtable->u.pair2.Class1Count, + subtable->u.pair2.ValueFormat1, + subtable->u.pair2.Class2Count, + subtable->u.pair2.ValueFormat2); } - } - return cmap; -} - - + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + + case 3: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; -/* TABLE: name */ + case 4: + if (subtable->Format == 1) + { + read_coverage (otf, stream, offset, &subtable->Coverage); + read_coverage (otf, stream, offset, + &subtable->u.mark_base1.BaseCoverage); + READ_UINT16 (stream, subtable->u.mark_base1.ClassCount); + read_mark_array (otf, stream, offset, + &subtable->u.mark_base1.MarkArray); + read_anchor_array (otf, stream, offset, + subtable->u.mark_base1.ClassCount, + &subtable->u.mark_base1.BaseArray); + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; -static char * -read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec, int bytes) -{ - char *errfmt = "nameID (%d)"; - void *errret = NULL; - OTF_StreamState state; - char *str; - int i; - int c; + case 5: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; - SAVE_STREAM (stream, state); - SEEK_STREAM (stream, stream->pos + rec->offset); + case 6: + if (subtable->Format == 1) + { + read_coverage (otf, stream, offset, &subtable->Coverage); + read_coverage (otf, stream, offset, + &subtable->u.mark_mark1.Mark2Coverage); + READ_UINT16 (stream, subtable->u.mark_base1.ClassCount); + read_mark_array (otf, stream, offset, + &subtable->u.mark_mark1.Mark1Array); + read_anchor_array (otf, stream, offset, + subtable->u.mark_mark1.ClassCount, + &subtable->u.mark_mark1.Mark2Array); + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; - if (bytes == 1) - { - OTF_MALLOC (str, rec->length + 1, (void *) rec->nameID); - READ_BYTES (stream, str, rec->length); - for (i = 0; i < rec->length; i++) - if (str[i] < 0) - str[i] = '?'; - } - else if (bytes == 2) - { - OTF_MALLOC (str, rec->length / 2 + 1, (void *) rec->nameID); - for (i = 0; i < rec->length / 2; i++) + case 7: + if (subtable->Format == 1) + { + if (read_context1 (otf, stream, offset, &subtable->Coverage, + &subtable->u.context1) < 0) + return errret; + } + else if (subtable->Format == 2) { - READ_USHORT (stream, c); - if (c >= 128) - c = '?'; - str[i] = c; + if (read_context2 (otf, stream, offset, &subtable->Coverage, + &subtable->u.context2) < 0) + return errret; } - } - else if (bytes == 4) - { - OTF_MALLOC (str, rec->length / 4 + 1, (void *) rec->nameID); - for (i = 0; i < rec->length / 4; i++) + else if (subtable->Format == 3) { - READ_ULONG (stream, c); - if (c >= 128) - c = '?'; - str[i] = c; + if (read_context3 (otf, stream, offset, &subtable->Coverage, + &subtable->u.context3) < 0) + return errret; + } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + + case 8: + if (subtable->Format == 1) + { + if (read_chain_context1 (otf, stream, offset, &subtable->Coverage, + &subtable->u.chain_context1) < 0) + return errret; + } + else if (subtable->Format == 2) + { + if (read_chain_context2 (otf, stream, offset, &subtable->Coverage, + &subtable->u.chain_context2) < 0) + return errret; + } + else if (subtable->Format == 3) + { + if (read_chain_context3 (otf, stream, offset, &subtable->Coverage, + &subtable->u.chain_context3) < 0) + return errret; } + else + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)"); + break; + + case 9: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); + break; + + default: + OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)"); } - str[i] = '\0'; - RESTORE_STREAM (stream, state); - return str; + return 0; } static void * -read_name_table (OTF *otf, OTF_Stream *stream) +read_gpos_table (OTF *otf, OTF_Stream *stream) { - char *errfmt = "name%s"; - void *errret = NULL; - OTF_name *name; - int i; + return read_gsub_gpos_table (otf, stream, 0); +} - OTF_CALLOC (name, 1, ""); - READ_USHORT (stream, name->format); - READ_USHORT (stream, name->count); - READ_USHORT (stream, name->stringOffset); - OTF_MALLOC (name->nameRecord, name->count, ""); - for (i = 0; i < name->count; i++) - { - OTF_NameRecord *rec = name->nameRecord + i; + +#if 0 +/* BASE */ - READ_USHORT (stream, rec->platformID); - READ_USHORT (stream, rec->encodingID); - READ_USHORT (stream, rec->languageID); - READ_USHORT (stream, rec->nameID); - READ_USHORT (stream, rec->length); - READ_USHORT (stream, rec->offset); - } - for (i = 0; i < name->count; i++) - { - OTF_NameRecord *rec = name->nameRecord + i; - int nameID = rec->nameID; +static OTF_BASE * +read_base_table (OTF_Stream *stream, long offset) +{ + OTF_BASE *base; - if (nameID <= OTF_max_nameID - && ! name->name[nameID]) - { - if (rec->platformID == 0) - name->name[nameID] = read_name (otf, stream, rec, - rec->encodingID <= 3 ? 2 : 4); - else if (rec->platformID == 1 - && rec->encodingID == 0) - name->name[nameID] = read_name (otf, stream, rec, 1); - else if (rec->platformID == 3 - && (rec->encodingID == 1 || rec->encodingID == 10)) - name->name[nameID] = read_name (otf, stream, - rec, rec->encodingID == 1 ? 2 : 4); - } - } + OTF_MALLOC (base, 1); - return name; + return base; } +/* JSTF */ -/* APIs */ +static OTF_JSTF * +read_jstf_table (OTF_Stream *stream, long offset) +{ + OTF_JSTF *jstf; -OTF_Tag -OTF_tag (char *name) + OTF_MALLOC (jstf, 1); + + return jstf; +} +#endif /* 0 */ + +/*** (1-11) Structure for OTF */ + +int +read_offset_table (OTF *otf, OTF_Stream *stream, OTF_OffsetTable *table) +{ + int errret = -1; + + READ_FIXED (stream, table->sfnt_version); + READ_USHORT (stream, table->numTables); + READ_USHORT (stream, table->searchRange); + READ_USHORT (stream, table->enterSelector); + READ_USHORT (stream, table->rangeShift); + return 0; +} + +static OTF_Tag +read_table_directory (OTF_Stream *stream, OTF_TableDirectory *table) { - unsigned char *p = (unsigned char *) name; + int errret = 0; + OTF_Tag tag; - if (! name) - return (OTF_Tag) 0; - return (OTF_Tag) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); + READ_TAG (stream, tag); + table->tag = tag; + table->name[0] = tag >> 24; + table->name[1] = (tag >> 16) & 0xFF; + table->name[0] = (tag >> 8) & 0xFF; + table->name[0] = tag >> 8; + table->name[0] = '\0'; + READ_ULONG (stream, table->checkSum); + READ_ULONG (stream, table->offset); + READ_ULONG (stream, table->length); + return tag; } -void -OTF_tag_name (OTF_Tag tag, char *name) +static int +read_header_part (OTF *otf, FILE *fp) { - name[0] = (char) (tag >> 24); - name[1] = (char) ((tag >> 16) & 0xFF); - name[2] = (char) ((tag >> 8) & 0xFF); - name[3] = (char) (tag & 0xFF); - name[4] = '\0'; + char *errfmt = "otf header%s"; + int errret = -1; + OTF_Tag head_tag, name_tag, cmap_tag, gdef_tag, gsub_tag, gpos_tag; + OTF_Stream *stream; + int i; + OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data; + + internal_data->table_info[OTF_TABLE_TYPE_HEAD].address = (void *) &otf->head; + internal_data->table_info[OTF_TABLE_TYPE_HEAD].reader = read_head_table; + internal_data->table_info[OTF_TABLE_TYPE_NAME].address = (void *) &otf->name; + internal_data->table_info[OTF_TABLE_TYPE_NAME].reader = read_name_table; + internal_data->table_info[OTF_TABLE_TYPE_CMAP].address = (void *) &otf->cmap; + internal_data->table_info[OTF_TABLE_TYPE_CMAP].reader = read_cmap_table; + internal_data->table_info[OTF_TABLE_TYPE_GDEF].address = (void *) &otf->gdef; + internal_data->table_info[OTF_TABLE_TYPE_GDEF].reader = read_gdef_table; + internal_data->table_info[OTF_TABLE_TYPE_GSUB].address = (void *) &otf->gsub; + internal_data->table_info[OTF_TABLE_TYPE_GSUB].reader = read_gsub_table; + internal_data->table_info[OTF_TABLE_TYPE_GPOS].address = (void *) &otf->gpos; + internal_data->table_info[OTF_TABLE_TYPE_GPOS].reader = read_gpos_table; + + head_tag = OTF_tag ("head"); + name_tag = OTF_tag ("name"); + cmap_tag = OTF_tag ("cmap"); + gdef_tag = OTF_tag ("GDEF"); + gsub_tag = OTF_tag ("GSUB"); + gpos_tag = OTF_tag ("GPOS"); + + stream = make_stream (); + if (! stream) + return -1; + + internal_data->header_stream = stream; + + /* Size of Offset Table is 12 bytes. */ + if (setup_stream (stream, fp, 0, 12, "Offset Table") < 0) + return -1; + if (read_offset_table (otf, stream, &otf->offset_table) < 0) + return -1; + + /* Size of each Table Directory is 16 bytes. */ + if (setup_stream (stream, fp, 12, 16 * otf->offset_table.numTables, + "Table Directory") < 0) + return -1; + + OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables, " (OffsetTable)"); + for (i = 0; i < otf->offset_table.numTables; i++) + { + OTF_Tag tag = read_table_directory (stream, otf->table_dirs + i); + OTF_TableInfo *table_info = NULL; + + if (! tag) + return -1; + if (tag == head_tag) + table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD; + else if (tag == name_tag) + table_info = internal_data->table_info + OTF_TABLE_TYPE_NAME; + else if (tag == cmap_tag) + table_info = internal_data->table_info + OTF_TABLE_TYPE_CMAP; + else if (tag == gdef_tag) + table_info = internal_data->table_info + OTF_TABLE_TYPE_GDEF; + else if (tag == gsub_tag) + table_info = internal_data->table_info + OTF_TABLE_TYPE_GSUB; + else if (tag == gpos_tag) + table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS; + + if (table_info) + { + table_info->stream = make_stream (); + if (setup_stream (table_info->stream, fp, + otf->table_dirs[i].offset, + otf->table_dirs[i].length, + otf->table_dirs[i].name) < 0) + return -1; + } + } + + internal_data->header_stream = NULL; + free_stream (stream); + return 0; } + +/*** (2) APIs for reading OTF */ + +/*** (2-1) OTF_open() */ -/* We can't use memory allocation macros in the following functions - because those macros returns from the functions before freeing - memory previously allocated. */ +/* Note: We can't use memory allocation macros in the following + functions because those macros return from the functions before + freeing memory previously allocated. */ OTF * OTF_open (char *otf_name) @@ -2251,6 +2291,7 @@ OTF_open (char *otf_name) return otf; } +/*** (2-2) OTF_close() */ void OTF_close (OTF *otf) @@ -2283,6 +2324,7 @@ OTF_close (OTF *otf) free (otf); } +/*** (2-3) OTF_get_table() */ int OTF_get_table (OTF *otf, char *name) @@ -2330,3 +2372,26 @@ OTF_get_table (OTF *otf, char *name) return 0; } + + +/*** (5) APIs miscellaneous ***/ + +OTF_Tag +OTF_tag (char *name) +{ + unsigned char *p = (unsigned char *) name; + + if (! name) + return (OTF_Tag) 0; + return (OTF_Tag) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +} + +void +OTF_tag_name (OTF_Tag tag, char *name) +{ + name[0] = (char) (tag >> 24); + name[1] = (char) ((tag >> 16) & 0xFF); + name[2] = (char) ((tag >> 8) & 0xFF); + name[3] = (char) (tag & 0xFF); + name[4] = '\0'; +}