} else if ( en[1].equals ( "BaseCoverage" ) ) {
coverages.put ( "base", extractCoverage() );
} else if ( en[1].equals ( "BaseRecord" ) ) {
baseOrMarkAnchors.add ( extractAnchors() );
} else if ( en[1].equals ( "ChainContextPos" ) || en[1].equals ( "ChainContextSubst" ) ) {
GlyphCoverageTable coverage = null;
if ( stFormat == 3 ) {
GlyphCoverageTable igca[] = getCoveragesWithPrefix ( "in" );
GlyphCoverageTable bgca[] = getCoveragesWithPrefix ( "bk" );
GlyphCoverageTable lgca[] = getCoveragesWithPrefix ( "la" );
if ( ( igca.length == 0 ) || hasMissingCoverage ( igca ) ) {
missingCoverage ( en, "input", igca.length );
} else if ( hasMissingCoverage ( bgca ) ) {
missingCoverage ( en, "backtrack", bgca.length );
} else if ( hasMissingCoverage ( lgca ) ) {
missingCoverage ( en, "lookahead", lgca.length );
} else {
GlyphTable.Rule r = new GlyphTable.ChainedCoverageSequenceRule ( extractRuleLookups(), igca.length, igca, bgca, lgca );
GlyphTable.RuleSet rs = new GlyphTable.HomogeneousRuleSet ( new GlyphTable.Rule[] {r} );
GlyphTable.RuleSet[] rsa = new GlyphTable.RuleSet[] {rs};
coverage = igca [ 0 ];
subtableEntries.add ( rsa );
}
} else {
unsupportedFormat ( en, stFormat );
}
if ( en[1].equals ( "ChainContextPos" ) ) {
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_CHAINED_CONTEXTUAL, coverage );
} else if ( en[1].equals ( "ChainContextSubst" ) ) {
addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_CHAINED_CONTEXTUAL, coverage );
}
} else if ( en[1].equals ( "ComponentRecord" ) ) {
components.add ( extractAnchors() );
} else if ( en[1].equals ( "Coverage" ) ) {
coverages.put ( "main", extractCoverage() );
} else if ( en[1].equals ( "DefaultLangSys" ) || en[1].equals ( "LangSysRecord" ) ) {
if ( languageTag == null ) {
missingTag ( en, "language" );
} else if ( languages.containsKey ( languageTag ) ) {
duplicateTag ( en, "language", languageTag );
} else {
languages.put ( languageTag, extractLanguageFeatures() );
languageTag = null;
}
} else if ( en[1].equals ( "CursivePos" ) ) {
GlyphCoverageTable ct = coverages.get ( "main" );
if ( ct == null ) {
missingParameter ( en, "coverages" );
} else if ( stFormat == 1 ) {
subtableEntries.add ( extractAttachmentAnchors() );
} else {
unsupportedFormat ( en, stFormat );
}
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_CURSIVE, ct );
} else if ( en[1].equals ( "EntryExitRecord" ) ) {
int na = anchors.size();
if ( na == 0 ) {
missingParameter ( en, "entry or exit anchor" );
} else if ( na == 1 ) {
anchors.add ( null );
} else if ( na > 2 ) {
duplicateParameter ( en, "entry or exit anchor" );
}
attachmentAnchors.add ( extractAnchors() );
} else if ( en[1].equals ( "BaseRecord" ) ) {
baseOrMarkAnchors.add ( extractAnchors() );
} else if ( en[1].equals ( "FeatureRecord" ) ) {
if ( flIndex != flSequence ) {
mismatchedIndex ( en, "feature", flIndex, flSequence );
} else if ( featureTag == null ) {
missingTag ( en, "feature" );
} else {
String fid = makeFeatureId ( flIndex );
features.put ( fid, extractFeature() );
nextFeature();
}
} else if ( en[1].equals ( "GDEF" ) ) {
if ( subtables.size() > 0 ) {
gdef = new GlyphDefinitionTable ( subtables );
}
clearTable();
} else if ( en[1].equals ( "GPOS" ) ) {
if ( subtables.size() > 0 ) {
gpos = new GlyphPositioningTable ( gdef, extractLookups(), subtables );
}
clearTable();
} else if ( en[1].equals ( "GSUB" ) ) {
if ( subtables.size() > 0 ) {
gsub = new GlyphSubstitutionTable ( gdef, extractLookups(), subtables );
}
clearTable();
} else if ( en[1].equals ( "GlyphClassDef" ) ) {
GlyphMappingTable mapping = extractClassDefMapping ( glyphClasses, stFormat, true );
addGDEFSubtable ( GlyphDefinitionTable.GDEF_LOOKUP_TYPE_GLYPH_CLASS, mapping );
} else if ( en[1].equals ( "InputCoverage" ) ) {
String ck = makeCoverageKey ( "in", ctIndex );
if ( coverages.containsKey ( ck ) ) {
duplicateCoverageIndex ( en, ctIndex );
} else {
coverages.put ( ck, extractCoverage() );
}
} else if ( en[1].equals ( "LigatureAttach" ) ) {
ligatureAnchors.add ( extractComponents() );
} else if ( en[1].equals ( "LigatureCoverage" ) ) {
coverages.put ( "liga", extractCoverage() );
} else if ( en[1].equals ( "LigatureSet" ) ) {
subtableEntries.add ( extractLigatures() );
} else if ( en[1].equals ( "LigatureSubst" ) ) {
if ( ! sortEntries ( coverageEntries, subtableEntries ) ) {
mismatchedEntries ( en, coverageEntries.size(), subtableEntries.size() );
}
GlyphCoverageTable coverage = extractCoverage();
addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_LIGATURE, coverage );
} else if ( en[1].equals ( "LookAheadCoverage" ) ) {
String ck = makeCoverageKey ( "la", ctIndex );
if ( coverages.containsKey ( ck ) ) {
duplicateCoverageIndex ( en, ctIndex );
} else {
coverages.put ( ck, extractCoverage() );
}
} else if ( en[1].equals ( "Lookup" ) ) {
if ( ltIndex != ltSequence ) {
mismatchedIndex ( en, "lookup", ltIndex, ltSequence );
} else {
nextLookup();
}
} else if ( en[1].equals ( "MarkAttachClassDef" ) ) {
GlyphMappingTable mapping = extractClassDefMapping ( glyphClasses, stFormat, true );
addGDEFSubtable ( GlyphDefinitionTable.GDEF_LOOKUP_TYPE_MARK_ATTACHMENT, mapping );
} else if ( en[1].equals ( "MarkCoverage" ) ) {
coverages.put ( "mark", extractCoverage() );
} else if ( en[1].equals ( "Mark1Coverage" ) ) {
coverages.put ( "mrk1", extractCoverage() );
} else if ( en[1].equals ( "Mark2Coverage" ) ) {
coverages.put ( "mrk2", extractCoverage() );
} else if ( en[1].equals ( "MarkBasePos" ) ) {
GlyphCoverageTable mct = coverages.get ( "mark" );
GlyphCoverageTable bct = coverages.get ( "base" );
if ( mct == null ) {
missingParameter ( en, "mark coverages" );
} else if ( bct == null ) {
missingParameter ( en, "base coverages" );
} else if ( stFormat == 1 ) {
MarkAnchor[] maa = extractMarkAnchors();
Anchor[][] bam = extractBaseOrMarkAnchors();
subtableEntries.add ( bct );
subtableEntries.add ( computeClassCount ( bam ) );
subtableEntries.add ( maa );
subtableEntries.add ( bam );
} else {
unsupportedFormat ( en, stFormat );
}
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_BASE, mct );
} else if ( en[1].equals ( "MarkLigPos" ) ) {
GlyphCoverageTable mct = coverages.get ( "mark" );
GlyphCoverageTable lct = coverages.get ( "liga" );
if ( mct == null ) {
missingParameter ( en, "mark coverages" );
} else if ( lct == null ) {
missingParameter ( en, "ligature coverages" );
} else if ( stFormat == 1 ) {
MarkAnchor[] maa = extractMarkAnchors();
Anchor[][][] lam = extractLigatureAnchors();
subtableEntries.add ( lct );
subtableEntries.add ( computeLigaturesClassCount ( lam ) );
subtableEntries.add ( computeLigaturesComponentCount ( lam ) );
subtableEntries.add ( maa );
subtableEntries.add ( lam );
} else {
unsupportedFormat ( en, stFormat );
}
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_LIGATURE, mct );
} else if ( en[1].equals ( "MarkMarkPos" ) ) {
GlyphCoverageTable mct1 = coverages.get ( "mrk1" );
GlyphCoverageTable mct2 = coverages.get ( "mrk2" );
if ( mct1 == null ) {
missingParameter ( en, "mark coverages 1" );
} else if ( mct2 == null ) {
missingParameter ( en, "mark coverages 2" );
} else if ( stFormat == 1 ) {
MarkAnchor[] maa = extractMarkAnchors();
Anchor[][] mam = extractBaseOrMarkAnchors();
subtableEntries.add ( mct2 );
subtableEntries.add ( computeClassCount ( mam ) );
subtableEntries.add ( maa );
subtableEntries.add ( mam );
} else {
unsupportedFormat ( en, stFormat );
}
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_MARK_TO_MARK, mct1 );
} else if ( en[1].equals ( "MarkRecord" ) ) {
if ( markClass == -1 ) {
missingParameter ( en, "mark class" );
} else if ( anchors.size() == 0 ) {
missingParameter ( en, "mark anchor" );
} else if ( anchors.size() > 1 ) {
duplicateParameter ( en, "mark anchor" );
} else {
markAnchors.add ( new GlyphPositioningTable.MarkAnchor ( markClass, anchors.get(0) ) );
markClass = -1;
anchors.clear();
}
} else if ( en[1].equals ( "Mark2Record" ) ) {
baseOrMarkAnchors.add ( extractAnchors() );
} else if ( en[1].equals ( "MultipleSubst" ) ) {
GlyphCoverageTable coverage = coverages.get ( "main" );
addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_MULTIPLE, coverage, extractSequenceEntries() );
} else if ( en[1].equals ( "PairPos" ) ) {
assertSubtableEntriesClear();
if ( stFormat == 1 ) {
if ( pairSets.size() == 0 ) {
missingParameter ( en, "pair set" );
} else {
subtableEntries.add ( extractPairSets() );
}
} else if ( stFormat == 2 ) {
unsupportedFormat ( en, stFormat );
}
GlyphCoverageTable coverage = coverages.get ( "main" );
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_PAIR, coverage );
vf1 = vf2 = -1; psIndex = -1;
} else if ( en[1].equals ( "PairSet" ) ) {
if ( psIndex != pairSets.size() ) {
invalidIndex ( en, psIndex, pairSets.size() );
} else {
pairSets.add ( extractPairs() );
}
} else if ( en[1].equals ( "PairValueRecord" ) ) {
if ( g2 == -1 ) {
missingParameter ( en, "second glyph" );
} else if ( ( v1 == null ) && ( v2 == null ) ) {
missingParameter ( en, "first or second value" );
} else {
pairs.add ( new PairValues ( g2, v1, v2 ) );
clearPair();
}
} else if ( en[1].equals ( "PosLookupRecord" ) || en[1].equals ( "SubstLookupRecord" ) ) {
if ( rlSequence < 0 ) {
missingParameter ( en, "sequence index" );
} else if ( rlLookup < 0 ) {
missingParameter ( en, "lookup index" );
} else {
ruleLookups.add ( new GlyphTable.RuleLookup ( rlSequence, rlLookup ) );
rlSequence = rlLookup = -1;
}
} else if ( en[1].equals ( "Script" ) ) {
if ( scriptTag == null ) {
missingTag ( en, "script" );
} else if ( scripts.containsKey ( scriptTag ) ) {
duplicateTag ( en, "script", scriptTag );
} else {
scripts.put ( scriptTag, extractLanguages() );
scriptTag = null;
}
} else if ( en[1].equals ( "Sequence" ) ) {
subtableEntries.add ( extractSubstitutes() );
} else if ( en[1].equals ( "SinglePos" ) ) {
int nv = subtableEntries.size();
if ( stFormat == 1 ) {
if ( nv < 0 ) {
missingParameter ( en, "value" );
} else if ( nv > 1 ) {
duplicateParameter ( en, "value" );
}
} else if ( stFormat == 2 ) {
GlyphPositioningTable.Value[] pva = (GlyphPositioningTable.Value[]) subtableEntries.toArray ( new GlyphPositioningTable.Value [ nv ] );
subtableEntries.clear();
subtableEntries.add ( pva );
}
GlyphCoverageTable coverage = coverages.get ( "main" );
addGPOSSubtable ( GlyphPositioningTable.GPOS_LOOKUP_TYPE_SINGLE, coverage );
vf1 = -1;
} else if ( en[1].equals ( "SingleSubst" ) ) {
if ( ! sortEntries ( coverageEntries, subtableEntries ) ) {
mismatchedEntries ( en, coverageEntries.size(), subtableEntries.size() );
}
GlyphCoverageTable coverage = extractCoverage();
addGSUBSubtable ( GlyphSubstitutionTable.GSUB_LOOKUP_TYPE_SINGLE, coverage );
} else if ( en[1].equals ( "cmap" ) ) {
cmap = getCMAP();
gmap = getGMAP();
cmapEntries.clear();